blob: b570e3512c4247e5c727964cec83f37129d8a1a5 [file] [log] [blame]
Marco Varleseb598f1d2017-09-19 14:25:28 +02001/*
2 * Copyright (c) 2017 SUSE LLC.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vlib/vlib.h>
17#include <vnet/pg/pg.h>
18#include <vnet/geneve/geneve.h>
19
Marco Varleseb598f1d2017-09-19 14:25:28 +020020typedef struct
21{
22 u32 next_index;
23 u32 tunnel_index;
24 u32 error;
Marco Varlese60d48bb2017-11-20 09:20:38 +010025 u32 vni_rsvd;
Marco Varleseb598f1d2017-09-19 14:25:28 +020026} geneve_rx_trace_t;
27
28static u8 *
29format_geneve_rx_trace (u8 * s, va_list * args)
30{
31 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
32 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
33 geneve_rx_trace_t *t = va_arg (*args, geneve_rx_trace_t *);
34
35 if (t->tunnel_index != ~0)
36 {
37 s =
38 format (s,
39 "GENEVE decap from geneve_tunnel%d vni %d next %d error %d",
Marco Varlese60d48bb2017-11-20 09:20:38 +010040 t->tunnel_index, t->vni_rsvd, t->next_index, t->error);
Marco Varleseb598f1d2017-09-19 14:25:28 +020041 }
42 else
43 {
44 s = format (s, "GENEVE decap error - tunnel for vni %d does not exist",
Marco Varlese60d48bb2017-11-20 09:20:38 +010045 t->vni_rsvd);
Marco Varleseb598f1d2017-09-19 14:25:28 +020046 }
47 return s;
48}
49
50always_inline u32
51validate_geneve_fib (vlib_buffer_t * b, geneve_tunnel_t * t, u32 is_ip4)
52{
53 u32 fib_index, sw_if_index;
54
55 sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
56
57 if (is_ip4)
58 fib_index = (vnet_buffer (b)->sw_if_index[VLIB_TX] == (u32) ~ 0) ?
59 vec_elt (ip4_main.fib_index_by_sw_if_index, sw_if_index) :
60 vnet_buffer (b)->sw_if_index[VLIB_TX];
61 else
62 fib_index = (vnet_buffer (b)->sw_if_index[VLIB_TX] == (u32) ~ 0) ?
63 vec_elt (ip6_main.fib_index_by_sw_if_index, sw_if_index) :
64 vnet_buffer (b)->sw_if_index[VLIB_TX];
65
66 return (fib_index == t->encap_fib_index);
67}
68
69always_inline uword
70geneve_input (vlib_main_t * vm,
71 vlib_node_runtime_t * node,
72 vlib_frame_t * from_frame, u32 is_ip4)
73{
74 u32 n_left_from, next_index, *from, *to_next;
75 geneve_main_t *vxm = &geneve_main;
76 vnet_main_t *vnm = vxm->vnet_main;
77 vnet_interface_main_t *im = &vnm->interface_main;
78 u32 last_tunnel_index = ~0;
79 geneve4_tunnel_key_t last_key4;
80 geneve6_tunnel_key_t last_key6;
81 u32 pkts_decapsulated = 0;
Damjan Marion067cd622018-07-11 12:47:43 +020082 u32 thread_index = vm->thread_index;
Marco Varleseb598f1d2017-09-19 14:25:28 +020083 u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
Zhiyong Yangd3ebc832019-05-21 01:46:35 -040084 vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
Marco Varleseb598f1d2017-09-19 14:25:28 +020085
86 if (is_ip4)
87 last_key4.as_u64 = ~0;
88 else
Dave Barachb7b92992018-10-17 10:38:51 -040089 clib_memset (&last_key6, 0xff, sizeof (last_key6));
Marco Varleseb598f1d2017-09-19 14:25:28 +020090
91 from = vlib_frame_vector_args (from_frame);
92 n_left_from = from_frame->n_vectors;
Zhiyong Yangd3ebc832019-05-21 01:46:35 -040093 vlib_get_buffers (vm, from, bufs, n_left_from);
Marco Varleseb598f1d2017-09-19 14:25:28 +020094
95 next_index = node->cached_next_index;
96 stats_sw_if_index = node->runtime_data[0];
97 stats_n_packets = stats_n_bytes = 0;
98
99 while (n_left_from > 0)
100 {
101 u32 n_left_to_next;
102
103 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
104 while (n_left_from >= 4 && n_left_to_next >= 2)
105 {
106 u32 bi0, bi1;
107 vlib_buffer_t *b0, *b1;
108 u32 next0, next1;
109 ip4_header_t *ip4_0, *ip4_1;
110 ip6_header_t *ip6_0, *ip6_1;
111 geneve_header_t *geneve0, *geneve1;
112 uword *p0, *p1;
113 u32 tunnel_index0, tunnel_index1;
114 geneve_tunnel_t *t0, *t1, *mt0 = NULL, *mt1 = NULL;
115 geneve4_tunnel_key_t key4_0, key4_1;
116 geneve6_tunnel_key_t key6_0, key6_1;
117 u32 error0, error1;
118 u32 sw_if_index0, sw_if_index1, len0, len1;
119
120 /* Prefetch next iteration. */
121 {
Zhiyong Yangd3ebc832019-05-21 01:46:35 -0400122 vlib_prefetch_buffer_header (b[2], LOAD);
123 vlib_prefetch_buffer_header (b[3], LOAD);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200124
Zhiyong Yangd3ebc832019-05-21 01:46:35 -0400125 CLIB_PREFETCH (b[2]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
126 CLIB_PREFETCH (b[3]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200127 }
128
129 bi0 = from[0];
130 bi1 = from[1];
131 to_next[0] = bi0;
132 to_next[1] = bi1;
133 from += 2;
134 to_next += 2;
135 n_left_to_next -= 2;
136 n_left_from -= 2;
137
Zhiyong Yangd3ebc832019-05-21 01:46:35 -0400138 b0 = b[0];
139 b1 = b[1];
140 b += 2;
Marco Varleseb598f1d2017-09-19 14:25:28 +0200141
142 /* udp leaves current_data pointing at the geneve header */
143 geneve0 = vlib_buffer_get_current (b0);
144 geneve1 = vlib_buffer_get_current (b1);
Marco Varlese60d48bb2017-11-20 09:20:38 +0100145
146 vnet_geneve_hdr_1word_ntoh (geneve0);
147 vnet_geneve_hdr_1word_ntoh (geneve1);
148
Marco Varleseb598f1d2017-09-19 14:25:28 +0200149 if (is_ip4)
150 {
151 vlib_buffer_advance
152 (b0, -(word) (sizeof (udp_header_t) + sizeof (ip4_header_t)));
153 vlib_buffer_advance
154 (b1, -(word) (sizeof (udp_header_t) + sizeof (ip4_header_t)));
155 ip4_0 = vlib_buffer_get_current (b0);
156 ip4_1 = vlib_buffer_get_current (b1);
157 }
158 else
159 {
160 vlib_buffer_advance
161 (b0, -(word) (sizeof (udp_header_t) + sizeof (ip6_header_t)));
162 vlib_buffer_advance
163 (b1, -(word) (sizeof (udp_header_t) + sizeof (ip6_header_t)));
164 ip6_0 = vlib_buffer_get_current (b0);
165 ip6_1 = vlib_buffer_get_current (b1);
166 }
167
168 /* pop (ip, udp, geneve) */
169 if (is_ip4)
170 {
Zhiyong Yang33fa7102019-07-06 05:14:54 -0400171 vlib_buffer_advance (b0,
172 sizeof (*ip4_0) + sizeof (udp_header_t) +
173 GENEVE_BASE_HEADER_LENGTH +
174 vnet_get_geneve_options_len (geneve0));
Marco Varleseb598f1d2017-09-19 14:25:28 +0200175 vlib_buffer_advance (b1,
176 sizeof (*ip4_1) + sizeof (udp_header_t) +
177 GENEVE_BASE_HEADER_LENGTH +
178 vnet_get_geneve_options_len (geneve1));
179 }
180 else
181 {
Marco Varleseb598f1d2017-09-19 14:25:28 +0200182 vlib_buffer_advance (b0,
183 sizeof (*ip6_0) + sizeof (udp_header_t) +
184 GENEVE_BASE_HEADER_LENGTH +
Zhiyong Yang33fa7102019-07-06 05:14:54 -0400185 vnet_get_geneve_options_len (geneve0));
186 vlib_buffer_advance (b1,
187 sizeof (*ip6_1) + sizeof (udp_header_t) +
188 GENEVE_BASE_HEADER_LENGTH +
Marco Varleseb598f1d2017-09-19 14:25:28 +0200189 vnet_get_geneve_options_len (geneve1));
190 }
191
192 tunnel_index0 = ~0;
193 error0 = 0;
194
195 tunnel_index1 = ~0;
196 error1 = 0;
197
Marco Varlese60d48bb2017-11-20 09:20:38 +0100198 if (PREDICT_FALSE
199 (vnet_get_geneve_version (geneve0) != GENEVE_VERSION))
Marco Varleseb598f1d2017-09-19 14:25:28 +0200200 {
201 error0 = GENEVE_ERROR_BAD_FLAGS;
202 next0 = GENEVE_INPUT_NEXT_DROP;
203 goto trace0;
204 }
Marco Varlese60d48bb2017-11-20 09:20:38 +0100205#if SUPPORT_OPTIONS_HEADER==1
Marco Varleseb598f1d2017-09-19 14:25:28 +0200206 if (PREDICT_FALSE (vnet_get_geneve_critical_bit (geneve0) == 1))
207 {
208 error0 = GENEVE_ERROR_BAD_FLAGS;
209 next0 = GENEVE_INPUT_NEXT_DROP;
210 goto trace0;
211 }
212#endif
213 if (is_ip4)
214 {
215 key4_0.remote = ip4_0->src_address.as_u32;
Neale Ranns91fd9102020-04-03 07:46:28 +0000216 key4_0.vni = vnet_get_geneve_vni_network_order (geneve0);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200217
218 /* Make sure GENEVE tunnel exist according to packet SIP and VNI */
219 if (PREDICT_FALSE (key4_0.as_u64 != last_key4.as_u64))
220 {
221 p0 = hash_get (vxm->geneve4_tunnel_by_key, key4_0.as_u64);
222 if (PREDICT_FALSE (p0 == NULL))
223 {
224 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
225 next0 = GENEVE_INPUT_NEXT_DROP;
226 goto trace0;
227 }
228 last_key4.as_u64 = key4_0.as_u64;
229 tunnel_index0 = last_tunnel_index = p0[0];
230 }
231 else
232 tunnel_index0 = last_tunnel_index;
233 t0 = pool_elt_at_index (vxm->tunnels, tunnel_index0);
234
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700235 /* Validate GENEVE tunnel encap-fib index against packet */
Marco Varleseb598f1d2017-09-19 14:25:28 +0200236 if (PREDICT_FALSE (validate_geneve_fib (b0, t0, is_ip4) == 0))
237 {
238 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
239 next0 = GENEVE_INPUT_NEXT_DROP;
240 goto trace0;
241 }
242
243 /* Validate GENEVE tunnel SIP against packet DIP */
244 if (PREDICT_TRUE
245 (ip4_0->dst_address.as_u32 == t0->local.ip4.as_u32))
246 goto next0; /* valid packet */
247 if (PREDICT_FALSE
248 (ip4_address_is_multicast (&ip4_0->dst_address)))
249 {
250 key4_0.remote = ip4_0->dst_address.as_u32;
Neale Ranns91fd9102020-04-03 07:46:28 +0000251 key4_0.vni = vnet_get_geneve_vni_network_order (geneve0);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200252 /* Make sure mcast GENEVE tunnel exist by packet DIP and VNI */
253 p0 = hash_get (vxm->geneve4_tunnel_by_key, key4_0.as_u64);
254 if (PREDICT_TRUE (p0 != NULL))
255 {
256 mt0 = pool_elt_at_index (vxm->tunnels, p0[0]);
257 goto next0; /* valid packet */
258 }
259 }
260 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
261 next0 = GENEVE_INPUT_NEXT_DROP;
262 goto trace0;
263
264 }
265 else /* !is_ip4 */
266 {
267 key6_0.remote.as_u64[0] = ip6_0->src_address.as_u64[0];
268 key6_0.remote.as_u64[1] = ip6_0->src_address.as_u64[1];
Neale Ranns91fd9102020-04-03 07:46:28 +0000269 key6_0.vni = vnet_get_geneve_vni_network_order (geneve0);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200270
271 /* Make sure GENEVE tunnel exist according to packet SIP and VNI */
272 if (PREDICT_FALSE
273 (memcmp (&key6_0, &last_key6, sizeof (last_key6)) != 0))
274 {
275 p0 = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6_0);
276 if (PREDICT_FALSE (p0 == NULL))
277 {
278 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
279 next0 = GENEVE_INPUT_NEXT_DROP;
280 goto trace0;
281 }
Dave Barach178cf492018-11-13 16:34:13 -0500282 clib_memcpy_fast (&last_key6, &key6_0, sizeof (key6_0));
Marco Varleseb598f1d2017-09-19 14:25:28 +0200283 tunnel_index0 = last_tunnel_index = p0[0];
284 }
285 else
286 tunnel_index0 = last_tunnel_index;
287 t0 = pool_elt_at_index (vxm->tunnels, tunnel_index0);
288
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700289 /* Validate GENEVE tunnel encap-fib index against packet */
Marco Varleseb598f1d2017-09-19 14:25:28 +0200290 if (PREDICT_FALSE (validate_geneve_fib (b0, t0, is_ip4) == 0))
291 {
292 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
293 next0 = GENEVE_INPUT_NEXT_DROP;
294 goto trace0;
295 }
296
297 /* Validate GENEVE tunnel SIP against packet DIP */
298 if (PREDICT_TRUE (ip6_address_is_equal (&ip6_0->dst_address,
299 &t0->local.ip6)))
300 goto next0; /* valid packet */
301 if (PREDICT_FALSE
302 (ip6_address_is_multicast (&ip6_0->dst_address)))
303 {
304 key6_0.remote.as_u64[0] = ip6_0->dst_address.as_u64[0];
305 key6_0.remote.as_u64[1] = ip6_0->dst_address.as_u64[1];
Neale Ranns91fd9102020-04-03 07:46:28 +0000306 key6_0.vni = vnet_get_geneve_vni_network_order (geneve0);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200307 p0 = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6_0);
308 if (PREDICT_TRUE (p0 != NULL))
309 {
310 mt0 = pool_elt_at_index (vxm->tunnels, p0[0]);
311 goto next0; /* valid packet */
312 }
313 }
314 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
315 next0 = GENEVE_INPUT_NEXT_DROP;
316 goto trace0;
317 }
318
319 next0:
320 next0 = t0->decap_next_index;
321 sw_if_index0 = t0->sw_if_index;
322 len0 = vlib_buffer_length_in_chain (vm, b0);
323
324 /* Required to make the l2 tag push / pop code work on l2 subifs */
325 if (PREDICT_TRUE (next0 == GENEVE_INPUT_NEXT_L2_INPUT))
326 vnet_update_l2_len (b0);
327
328 /* Set packet input sw_if_index to unicast GENEVE tunnel for learning */
329 vnet_buffer (b0)->sw_if_index[VLIB_RX] = sw_if_index0;
330 sw_if_index0 = (mt0) ? mt0->sw_if_index : sw_if_index0;
331
332 pkts_decapsulated++;
333 stats_n_packets += 1;
334 stats_n_bytes += len0;
335
336 /* Batch stats increment on the same geneve tunnel so counter
337 is not incremented per packet */
338 if (PREDICT_FALSE (sw_if_index0 != stats_sw_if_index))
339 {
340 stats_n_packets -= 1;
341 stats_n_bytes -= len0;
342 if (stats_n_packets)
343 vlib_increment_combined_counter
344 (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX,
345 thread_index, stats_sw_if_index,
346 stats_n_packets, stats_n_bytes);
347 stats_n_packets = 1;
348 stats_n_bytes = len0;
349 stats_sw_if_index = sw_if_index0;
350 }
351
352 trace0:
353 b0->error = error0 ? node->errors[error0] : 0;
354
355 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
356 {
357 geneve_rx_trace_t *tr
358 = vlib_add_trace (vm, node, b0, sizeof (*tr));
359 tr->next_index = next0;
360 tr->error = error0;
361 tr->tunnel_index = tunnel_index0;
Marco Varlese60d48bb2017-11-20 09:20:38 +0100362 tr->vni_rsvd = vnet_get_geneve_vni (geneve0);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200363 }
364
Marco Varlese60d48bb2017-11-20 09:20:38 +0100365 if (PREDICT_FALSE
366 (vnet_get_geneve_version (geneve1) != GENEVE_VERSION))
Marco Varleseb598f1d2017-09-19 14:25:28 +0200367 {
368 error1 = GENEVE_ERROR_BAD_FLAGS;
369 next1 = GENEVE_INPUT_NEXT_DROP;
370 goto trace1;
371 }
Marco Varlese60d48bb2017-11-20 09:20:38 +0100372#if SUPPORT_OPTIONS_HEADER==1
Marco Varleseb598f1d2017-09-19 14:25:28 +0200373 if (PREDICT_FALSE (vnet_get_geneve_critical_bit (geneve1) == 1))
374 {
375 error1 = GENEVE_ERROR_BAD_FLAGS;
376 next1 = GENEVE_INPUT_NEXT_DROP;
377 goto trace1;
378 }
379#endif
380 if (is_ip4)
381 {
382 key4_1.remote = ip4_1->src_address.as_u32;
Neale Ranns91fd9102020-04-03 07:46:28 +0000383 key4_1.vni = vnet_get_geneve_vni_network_order (geneve1);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200384
385 /* Make sure unicast GENEVE tunnel exist by packet SIP and VNI */
386 if (PREDICT_FALSE (key4_1.as_u64 != last_key4.as_u64))
387 {
388 p1 = hash_get (vxm->geneve4_tunnel_by_key, key4_1.as_u64);
389 if (PREDICT_FALSE (p1 == NULL))
390 {
391 error1 = GENEVE_ERROR_NO_SUCH_TUNNEL;
392 next1 = GENEVE_INPUT_NEXT_DROP;
393 goto trace1;
394 }
395 last_key4.as_u64 = key4_1.as_u64;
396 tunnel_index1 = last_tunnel_index = p1[0];
397 }
398 else
399 tunnel_index1 = last_tunnel_index;
400 t1 = pool_elt_at_index (vxm->tunnels, tunnel_index1);
401
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700402 /* Validate GENEVE tunnel encap-fib index against packet */
Marco Varleseb598f1d2017-09-19 14:25:28 +0200403 if (PREDICT_FALSE (validate_geneve_fib (b1, t1, is_ip4) == 0))
404 {
405 error1 = GENEVE_ERROR_NO_SUCH_TUNNEL;
406 next1 = GENEVE_INPUT_NEXT_DROP;
407 goto trace1;
408 }
409
410 /* Validate GENEVE tunnel SIP against packet DIP */
411 if (PREDICT_TRUE
412 (ip4_1->dst_address.as_u32 == t1->local.ip4.as_u32))
413 goto next1; /* valid packet */
414 if (PREDICT_FALSE
415 (ip4_address_is_multicast (&ip4_1->dst_address)))
416 {
417 key4_1.remote = ip4_1->dst_address.as_u32;
Neale Ranns91fd9102020-04-03 07:46:28 +0000418 key4_1.vni = vnet_get_geneve_vni_network_order (geneve1);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200419 /* Make sure mcast GENEVE tunnel exist by packet DIP and VNI */
420 p1 = hash_get (vxm->geneve4_tunnel_by_key, key4_1.as_u64);
421 if (PREDICT_TRUE (p1 != NULL))
422 {
423 mt1 = pool_elt_at_index (vxm->tunnels, p1[0]);
424 goto next1; /* valid packet */
425 }
426 }
427 error1 = GENEVE_ERROR_NO_SUCH_TUNNEL;
428 next1 = GENEVE_INPUT_NEXT_DROP;
429 goto trace1;
430
431 }
432 else /* !is_ip4 */
433 {
434 key6_1.remote.as_u64[0] = ip6_1->src_address.as_u64[0];
435 key6_1.remote.as_u64[1] = ip6_1->src_address.as_u64[1];
Neale Ranns91fd9102020-04-03 07:46:28 +0000436 key6_1.vni = vnet_get_geneve_vni_network_order (geneve1);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200437
438 /* Make sure GENEVE tunnel exist according to packet SIP and VNI */
439 if (PREDICT_FALSE
440 (memcmp (&key6_1, &last_key6, sizeof (last_key6)) != 0))
441 {
442 p1 = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6_1);
443
444 if (PREDICT_FALSE (p1 == NULL))
445 {
446 error1 = GENEVE_ERROR_NO_SUCH_TUNNEL;
447 next1 = GENEVE_INPUT_NEXT_DROP;
448 goto trace1;
449 }
450
Dave Barach178cf492018-11-13 16:34:13 -0500451 clib_memcpy_fast (&last_key6, &key6_1, sizeof (key6_1));
Marco Varleseb598f1d2017-09-19 14:25:28 +0200452 tunnel_index1 = last_tunnel_index = p1[0];
453 }
454 else
455 tunnel_index1 = last_tunnel_index;
456 t1 = pool_elt_at_index (vxm->tunnels, tunnel_index1);
457
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700458 /* Validate GENEVE tunnel encap-fib index against packet */
Marco Varleseb598f1d2017-09-19 14:25:28 +0200459 if (PREDICT_FALSE (validate_geneve_fib (b1, t1, is_ip4) == 0))
460 {
461 error1 = GENEVE_ERROR_NO_SUCH_TUNNEL;
462 next1 = GENEVE_INPUT_NEXT_DROP;
463 goto trace1;
464 }
465
466 /* Validate GENEVE tunnel SIP against packet DIP */
467 if (PREDICT_TRUE (ip6_address_is_equal (&ip6_1->dst_address,
468 &t1->local.ip6)))
469 goto next1; /* valid packet */
470 if (PREDICT_FALSE
471 (ip6_address_is_multicast (&ip6_1->dst_address)))
472 {
473 key6_1.remote.as_u64[0] = ip6_1->dst_address.as_u64[0];
474 key6_1.remote.as_u64[1] = ip6_1->dst_address.as_u64[1];
Neale Ranns91fd9102020-04-03 07:46:28 +0000475 key6_1.vni = vnet_get_geneve_vni_network_order (geneve1);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200476 p1 = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6_1);
477 if (PREDICT_TRUE (p1 != NULL))
478 {
479 mt1 = pool_elt_at_index (vxm->tunnels, p1[0]);
480 goto next1; /* valid packet */
481 }
482 }
483 error1 = GENEVE_ERROR_NO_SUCH_TUNNEL;
484 next1 = GENEVE_INPUT_NEXT_DROP;
485 goto trace1;
486 }
487
488 next1:
489 next1 = t1->decap_next_index;
490 sw_if_index1 = t1->sw_if_index;
491 len1 = vlib_buffer_length_in_chain (vm, b1);
492
493 /* Required to make the l2 tag push / pop code work on l2 subifs */
494 if (PREDICT_TRUE (next1 == GENEVE_INPUT_NEXT_L2_INPUT))
495 vnet_update_l2_len (b1);
496
497 /* Set packet input sw_if_index to unicast GENEVE tunnel for learning */
498 vnet_buffer (b1)->sw_if_index[VLIB_RX] = sw_if_index1;
499 sw_if_index1 = (mt1) ? mt1->sw_if_index : sw_if_index1;
500
501 pkts_decapsulated++;
502 stats_n_packets += 1;
503 stats_n_bytes += len1;
504
505 /* Batch stats increment on the same geneve tunnel so counter
506 is not incremented per packet */
507 if (PREDICT_FALSE (sw_if_index1 != stats_sw_if_index))
508 {
509 stats_n_packets -= 1;
510 stats_n_bytes -= len1;
511 if (stats_n_packets)
512 vlib_increment_combined_counter
513 (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX,
514 thread_index, stats_sw_if_index,
515 stats_n_packets, stats_n_bytes);
516 stats_n_packets = 1;
517 stats_n_bytes = len1;
518 stats_sw_if_index = sw_if_index1;
519 }
520
521 trace1:
522 b1->error = error1 ? node->errors[error1] : 0;
523
524 if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
525 {
526 geneve_rx_trace_t *tr
527 = vlib_add_trace (vm, node, b1, sizeof (*tr));
528 tr->next_index = next1;
529 tr->error = error1;
530 tr->tunnel_index = tunnel_index1;
Marco Varlese60d48bb2017-11-20 09:20:38 +0100531 tr->vni_rsvd = vnet_get_geneve_vni (geneve1);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200532 }
533
534 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
535 to_next, n_left_to_next,
536 bi0, bi1, next0, next1);
537 }
538
539 while (n_left_from > 0 && n_left_to_next > 0)
540 {
541 u32 bi0;
542 vlib_buffer_t *b0;
543 u32 next0;
544 ip4_header_t *ip4_0;
545 ip6_header_t *ip6_0;
546 geneve_header_t *geneve0;
547 uword *p0;
548 u32 tunnel_index0;
549 geneve_tunnel_t *t0, *mt0 = NULL;
550 geneve4_tunnel_key_t key4_0;
551 geneve6_tunnel_key_t key6_0;
552 u32 error0;
553 u32 sw_if_index0, len0;
554
555 bi0 = from[0];
556 to_next[0] = bi0;
557 from += 1;
558 to_next += 1;
559 n_left_from -= 1;
560 n_left_to_next -= 1;
561
Zhiyong Yangd3ebc832019-05-21 01:46:35 -0400562 b0 = b[0];
563 b += 1;
Marco Varleseb598f1d2017-09-19 14:25:28 +0200564
565 /* udp leaves current_data pointing at the geneve header */
566 geneve0 = vlib_buffer_get_current (b0);
Marco Varlese60d48bb2017-11-20 09:20:38 +0100567 vnet_geneve_hdr_1word_ntoh (geneve0);
568
Marco Varleseb598f1d2017-09-19 14:25:28 +0200569 if (is_ip4)
570 {
571 vlib_buffer_advance
572 (b0, -(word) (sizeof (udp_header_t) + sizeof (ip4_header_t)));
573 ip4_0 = vlib_buffer_get_current (b0);
574 }
575 else
576 {
577 vlib_buffer_advance
578 (b0, -(word) (sizeof (udp_header_t) + sizeof (ip6_header_t)));
579 ip6_0 = vlib_buffer_get_current (b0);
580 }
581
582 /* pop (ip, udp, geneve) */
583 if (is_ip4)
584 {
585 vlib_buffer_advance
586 (b0,
587 sizeof (*ip4_0) + sizeof (udp_header_t) +
588 GENEVE_BASE_HEADER_LENGTH +
589 vnet_get_geneve_options_len (geneve0));
590 }
591 else
592 {
593 vlib_buffer_advance
594 (b0,
595 sizeof (*ip6_0) + sizeof (udp_header_t) +
596 GENEVE_BASE_HEADER_LENGTH +
597 vnet_get_geneve_options_len (geneve0));
598 }
599
600 tunnel_index0 = ~0;
601 error0 = 0;
602
Marco Varlese60d48bb2017-11-20 09:20:38 +0100603 if (PREDICT_FALSE
604 (vnet_get_geneve_version (geneve0) != GENEVE_VERSION))
Marco Varleseb598f1d2017-09-19 14:25:28 +0200605 {
606 error0 = GENEVE_ERROR_BAD_FLAGS;
607 next0 = GENEVE_INPUT_NEXT_DROP;
608 goto trace00;
609 }
Marco Varlese60d48bb2017-11-20 09:20:38 +0100610#if SUPPORT_OPTIONS_HEADER==1
Marco Varleseb598f1d2017-09-19 14:25:28 +0200611 if (PREDICT_FALSE (vnet_get_geneve_critical_bit (geneve0) == 1))
612 {
613 error0 = GENEVE_ERROR_BAD_FLAGS;
614 next0 = GENEVE_INPUT_NEXT_DROP;
615 goto trace00;
616 }
617#endif
618 if (is_ip4)
619 {
620 key4_0.remote = ip4_0->src_address.as_u32;
Neale Ranns91fd9102020-04-03 07:46:28 +0000621 key4_0.vni = vnet_get_geneve_vni_network_order (geneve0);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200622
623 /* Make sure unicast GENEVE tunnel exist by packet SIP and VNI */
624 if (PREDICT_FALSE (key4_0.as_u64 != last_key4.as_u64))
625 {
626 p0 = hash_get (vxm->geneve4_tunnel_by_key, key4_0.as_u64);
627 if (PREDICT_FALSE (p0 == NULL))
628 {
629 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
630 next0 = GENEVE_INPUT_NEXT_DROP;
631 goto trace00;
632 }
633 last_key4.as_u64 = key4_0.as_u64;
634 tunnel_index0 = last_tunnel_index = p0[0];
635 }
636 else
637 tunnel_index0 = last_tunnel_index;
638 t0 = pool_elt_at_index (vxm->tunnels, tunnel_index0);
639
640 /* Validate GENEVE tunnel encap-fib index agaist packet */
641 if (PREDICT_FALSE (validate_geneve_fib (b0, t0, is_ip4) == 0))
642 {
643 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
644 next0 = GENEVE_INPUT_NEXT_DROP;
645 goto trace00;
646 }
647
648 /* Validate GENEVE tunnel SIP against packet DIP */
649 if (PREDICT_TRUE
650 (ip4_0->dst_address.as_u32 == t0->local.ip4.as_u32))
651 goto next00; /* valid packet */
652 if (PREDICT_FALSE
653 (ip4_address_is_multicast (&ip4_0->dst_address)))
654 {
655 key4_0.remote = ip4_0->dst_address.as_u32;
Neale Ranns91fd9102020-04-03 07:46:28 +0000656 key4_0.vni = vnet_get_geneve_vni_network_order (geneve0);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200657 /* Make sure mcast GENEVE tunnel exist by packet DIP and VNI */
658 p0 = hash_get (vxm->geneve4_tunnel_by_key, key4_0.as_u64);
659 if (PREDICT_TRUE (p0 != NULL))
660 {
661 mt0 = pool_elt_at_index (vxm->tunnels, p0[0]);
662 goto next00; /* valid packet */
663 }
664 }
665 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
666 next0 = GENEVE_INPUT_NEXT_DROP;
667 goto trace00;
668
669 }
670 else /* !is_ip4 */
671 {
672 key6_0.remote.as_u64[0] = ip6_0->src_address.as_u64[0];
673 key6_0.remote.as_u64[1] = ip6_0->src_address.as_u64[1];
Neale Ranns91fd9102020-04-03 07:46:28 +0000674 key6_0.vni = vnet_get_geneve_vni_network_order (geneve0);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200675
676 /* Make sure GENEVE tunnel exist according to packet SIP and VNI */
677 if (PREDICT_FALSE
678 (memcmp (&key6_0, &last_key6, sizeof (last_key6)) != 0))
679 {
680 p0 = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6_0);
681 if (PREDICT_FALSE (p0 == NULL))
682 {
683 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
684 next0 = GENEVE_INPUT_NEXT_DROP;
685 goto trace00;
686 }
Dave Barach178cf492018-11-13 16:34:13 -0500687 clib_memcpy_fast (&last_key6, &key6_0, sizeof (key6_0));
Marco Varleseb598f1d2017-09-19 14:25:28 +0200688 tunnel_index0 = last_tunnel_index = p0[0];
689 }
690 else
691 tunnel_index0 = last_tunnel_index;
692 t0 = pool_elt_at_index (vxm->tunnels, tunnel_index0);
693
694 /* Validate GENEVE tunnel encap-fib index agaist packet */
695 if (PREDICT_FALSE (validate_geneve_fib (b0, t0, is_ip4) == 0))
696 {
697 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
698 next0 = GENEVE_INPUT_NEXT_DROP;
699 goto trace00;
700 }
701
702 /* Validate GENEVE tunnel SIP against packet DIP */
703 if (PREDICT_TRUE (ip6_address_is_equal (&ip6_0->dst_address,
704 &t0->local.ip6)))
705 goto next00; /* valid packet */
706 if (PREDICT_FALSE
707 (ip6_address_is_multicast (&ip6_0->dst_address)))
708 {
709 key6_0.remote.as_u64[0] = ip6_0->dst_address.as_u64[0];
710 key6_0.remote.as_u64[1] = ip6_0->dst_address.as_u64[1];
Neale Ranns91fd9102020-04-03 07:46:28 +0000711 key6_0.vni = vnet_get_geneve_vni_network_order (geneve0);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200712 p0 = hash_get_mem (vxm->geneve6_tunnel_by_key, &key6_0);
713 if (PREDICT_TRUE (p0 != NULL))
714 {
715 mt0 = pool_elt_at_index (vxm->tunnels, p0[0]);
716 goto next00; /* valid packet */
717 }
718 }
719 error0 = GENEVE_ERROR_NO_SUCH_TUNNEL;
720 next0 = GENEVE_INPUT_NEXT_DROP;
721 goto trace00;
722 }
723
724 next00:
725 next0 = t0->decap_next_index;
726 sw_if_index0 = t0->sw_if_index;
727 len0 = vlib_buffer_length_in_chain (vm, b0);
728
729 /* Required to make the l2 tag push / pop code work on l2 subifs */
730 if (PREDICT_TRUE (next0 == GENEVE_INPUT_NEXT_L2_INPUT))
731 vnet_update_l2_len (b0);
732
733 /* Set packet input sw_if_index to unicast GENEVE tunnel for learning */
734 vnet_buffer (b0)->sw_if_index[VLIB_RX] = sw_if_index0;
735 sw_if_index0 = (mt0) ? mt0->sw_if_index : sw_if_index0;
736
737 pkts_decapsulated++;
738 stats_n_packets += 1;
739 stats_n_bytes += len0;
740
741 /* Batch stats increment on the same geneve tunnel so counter
742 is not incremented per packet */
743 if (PREDICT_FALSE (sw_if_index0 != stats_sw_if_index))
744 {
745 stats_n_packets -= 1;
746 stats_n_bytes -= len0;
747 if (stats_n_packets)
748 vlib_increment_combined_counter
749 (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX,
750 thread_index, stats_sw_if_index,
751 stats_n_packets, stats_n_bytes);
752 stats_n_packets = 1;
753 stats_n_bytes = len0;
754 stats_sw_if_index = sw_if_index0;
755 }
756
757 trace00:
758 b0->error = error0 ? node->errors[error0] : 0;
759
760 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
761 {
762 geneve_rx_trace_t *tr
763 = vlib_add_trace (vm, node, b0, sizeof (*tr));
764 tr->next_index = next0;
765 tr->error = error0;
766 tr->tunnel_index = tunnel_index0;
Marco Varlese60d48bb2017-11-20 09:20:38 +0100767 tr->vni_rsvd = vnet_get_geneve_vni (geneve0);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200768 }
769 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
770 to_next, n_left_to_next,
771 bi0, next0);
772 }
773
774 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
775 }
776 /* Do we still need this now that tunnel tx stats is kept? */
777 vlib_node_increment_counter (vm, is_ip4 ?
778 geneve4_input_node.
779 index : geneve6_input_node.index,
780 GENEVE_ERROR_DECAPSULATED, pkts_decapsulated);
781
782 /* Increment any remaining batch stats */
783 if (stats_n_packets)
784 {
785 vlib_increment_combined_counter
786 (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX,
787 thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
788 node->runtime_data[0] = stats_sw_if_index;
789 }
790
791 return from_frame->n_vectors;
792}
793
Filip Tehlar55333d72019-03-05 00:36:04 -0800794VLIB_NODE_FN (geneve4_input_node) (vlib_main_t * vm,
795 vlib_node_runtime_t * node,
796 vlib_frame_t * from_frame)
Marco Varleseb598f1d2017-09-19 14:25:28 +0200797{
798 return geneve_input (vm, node, from_frame, /* is_ip4 */ 1);
799}
800
Filip Tehlar55333d72019-03-05 00:36:04 -0800801VLIB_NODE_FN (geneve6_input_node) (vlib_main_t * vm,
802 vlib_node_runtime_t * node,
803 vlib_frame_t * from_frame)
Marco Varleseb598f1d2017-09-19 14:25:28 +0200804{
805 return geneve_input (vm, node, from_frame, /* is_ip4 */ 0);
806}
807
808static char *geneve_error_strings[] = {
809#define geneve_error(n,s) s,
810#include <vnet/geneve/geneve_error.def>
811#undef geneve_error
812#undef _
813};
814
815/* *INDENT-OFF* */
816VLIB_REGISTER_NODE (geneve4_input_node) = {
Marco Varleseb598f1d2017-09-19 14:25:28 +0200817 .name = "geneve4-input",
818 /* Takes a vector of packets. */
819 .vector_size = sizeof (u32),
820 .n_errors = GENEVE_N_ERROR,
821 .error_strings = geneve_error_strings,
822 .n_next_nodes = GENEVE_INPUT_N_NEXT,
823 .next_nodes = {
824#define _(s,n) [GENEVE_INPUT_NEXT_##s] = n,
825 foreach_geneve_input_next
826#undef _
827 },
828
829//temp .format_buffer = format_geneve_header,
830 .format_trace = format_geneve_rx_trace,
831 // $$$$ .unformat_buffer = unformat_geneve_header,
832};
833
Marco Varleseb598f1d2017-09-19 14:25:28 +0200834VLIB_REGISTER_NODE (geneve6_input_node) = {
Marco Varleseb598f1d2017-09-19 14:25:28 +0200835 .name = "geneve6-input",
836 /* Takes a vector of packets. */
837 .vector_size = sizeof (u32),
838 .n_errors = GENEVE_N_ERROR,
839 .error_strings = geneve_error_strings,
840 .n_next_nodes = GENEVE_INPUT_N_NEXT,
841 .next_nodes = {
842#define _(s,n) [GENEVE_INPUT_NEXT_##s] = n,
843 foreach_geneve_input_next
844#undef _
845 },
846//temp .format_buffer = format_geneve_header,
847 .format_trace = format_geneve_rx_trace,
848 // $$$$ .unformat_buffer = unformat_geneve_header,
849};
Marco Varleseb598f1d2017-09-19 14:25:28 +0200850/* *INDENT-ON* */
851
852typedef enum
853{
854 IP_GENEVE_BYPASS_NEXT_DROP,
855 IP_GENEVE_BYPASS_NEXT_GENEVE,
856 IP_GENEVE_BYPASS_N_NEXT,
857} ip_vxan_bypass_next_t;
858
859always_inline uword
860ip_geneve_bypass_inline (vlib_main_t * vm,
861 vlib_node_runtime_t * node,
862 vlib_frame_t * frame, u32 is_ip4)
863{
864 geneve_main_t *vxm = &geneve_main;
865 u32 *from, *to_next, n_left_from, n_left_to_next, next_index;
866 vlib_node_runtime_t *error_node =
867 vlib_node_get_runtime (vm, ip4_input_node.index);
Nick Zavaritsky27518c22020-02-27 15:54:58 +0000868 vtep4_key_t last_vtep4; /* last IPv4 address / fib index
869 matching a local VTEP address */
870 vtep6_key_t last_vtep6; /* last IPv6 address / fib index
871 matching a local VTEP address */
Zhiyong Yang5e524172020-07-08 20:28:36 +0000872 vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
873#ifdef CLIB_HAVE_VEC512
874 vtep4_cache_t vtep4_u512;
875 clib_memset (&vtep4_u512, 0, sizeof (vtep4_u512));
876#endif
Marco Varleseb598f1d2017-09-19 14:25:28 +0200877
878 from = vlib_frame_vector_args (frame);
879 n_left_from = frame->n_vectors;
880 next_index = node->cached_next_index;
881
Zhiyong Yang5e524172020-07-08 20:28:36 +0000882 vlib_get_buffers (vm, from, bufs, n_left_from);
883
Marco Varleseb598f1d2017-09-19 14:25:28 +0200884 if (node->flags & VLIB_NODE_FLAG_TRACE)
885 ip4_forward_next_trace (vm, node, frame, VLIB_TX);
886
887 if (is_ip4)
Nick Zavaritsky27518c22020-02-27 15:54:58 +0000888 vtep4_key_init (&last_vtep4);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200889 else
Nick Zavaritsky27518c22020-02-27 15:54:58 +0000890 vtep6_key_init (&last_vtep6);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200891
892 while (n_left_from > 0)
893 {
894 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
895
896 while (n_left_from >= 4 && n_left_to_next >= 2)
897 {
898 vlib_buffer_t *b0, *b1;
899 ip4_header_t *ip40, *ip41;
900 ip6_header_t *ip60, *ip61;
901 udp_header_t *udp0, *udp1;
902 u32 bi0, ip_len0, udp_len0, flags0, next0;
903 u32 bi1, ip_len1, udp_len1, flags1, next1;
904 i32 len_diff0, len_diff1;
905 u8 error0, good_udp0, proto0;
906 u8 error1, good_udp1, proto1;
907
908 /* Prefetch next iteration. */
909 {
Zhiyong Yang5e524172020-07-08 20:28:36 +0000910 vlib_prefetch_buffer_header (b[2], LOAD);
911 vlib_prefetch_buffer_header (b[3], LOAD);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200912
Zhiyong Yang5e524172020-07-08 20:28:36 +0000913 CLIB_PREFETCH (b[2]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
914 CLIB_PREFETCH (b[3]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200915 }
916
917 bi0 = to_next[0] = from[0];
918 bi1 = to_next[1] = from[1];
919 from += 2;
920 n_left_from -= 2;
921 to_next += 2;
922 n_left_to_next -= 2;
923
Zhiyong Yang5e524172020-07-08 20:28:36 +0000924 b0 = b[0];
925 b1 = b[1];
926 b += 2;
Marco Varleseb598f1d2017-09-19 14:25:28 +0200927 if (is_ip4)
928 {
929 ip40 = vlib_buffer_get_current (b0);
930 ip41 = vlib_buffer_get_current (b1);
931 }
932 else
933 {
934 ip60 = vlib_buffer_get_current (b0);
935 ip61 = vlib_buffer_get_current (b1);
936 }
937
938 /* Setup packet for next IP feature */
Damjan Marion7d98a122018-07-19 20:42:08 +0200939 vnet_feature_next (&next0, b0);
940 vnet_feature_next (&next1, b1);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200941
942 if (is_ip4)
943 {
944 /* Treat IP frag packets as "experimental" protocol for now
945 until support of IP frag reassembly is implemented */
946 proto0 = ip4_is_fragment (ip40) ? 0xfe : ip40->protocol;
947 proto1 = ip4_is_fragment (ip41) ? 0xfe : ip41->protocol;
948 }
949 else
950 {
951 proto0 = ip60->protocol;
952 proto1 = ip61->protocol;
953 }
954
955 /* Process packet 0 */
956 if (proto0 != IP_PROTOCOL_UDP)
957 goto exit0; /* not UDP packet */
958
959 if (is_ip4)
960 udp0 = ip4_next_header (ip40);
961 else
962 udp0 = ip6_next_header (ip60);
963
964 if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_geneve))
965 goto exit0; /* not GENEVE packet */
966
967 /* Validate DIP against VTEPs */
968 if (is_ip4)
969 {
Zhiyong Yang5e524172020-07-08 20:28:36 +0000970#ifdef CLIB_HAVE_VEC512
971 if (!vtep4_check_vector
972 (&vxm->vtep_table, b0, ip40, &last_vtep4, &vtep4_u512))
973#else
Nick Zavaritsky27518c22020-02-27 15:54:58 +0000974 if (!vtep4_check (&vxm->vtep_table, b0, ip40, &last_vtep4))
Zhiyong Yang5e524172020-07-08 20:28:36 +0000975#endif
Nick Zavaritsky27518c22020-02-27 15:54:58 +0000976 goto exit0; /* no local VTEP for GENEVE packet */
Marco Varleseb598f1d2017-09-19 14:25:28 +0200977 }
978 else
979 {
Nick Zavaritsky27518c22020-02-27 15:54:58 +0000980 if (!vtep6_check (&vxm->vtep_table, b0, ip60, &last_vtep6))
981 goto exit0; /* no local VTEP for GENEVE packet */
Marco Varleseb598f1d2017-09-19 14:25:28 +0200982 }
983
984 flags0 = b0->flags;
985 good_udp0 = (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
986
987 /* Don't verify UDP checksum for packets with explicit zero checksum. */
988 good_udp0 |= udp0->checksum == 0;
989
990 /* Verify UDP length */
991 if (is_ip4)
992 ip_len0 = clib_net_to_host_u16 (ip40->length);
993 else
994 ip_len0 = clib_net_to_host_u16 (ip60->payload_length);
995 udp_len0 = clib_net_to_host_u16 (udp0->length);
996 len_diff0 = ip_len0 - udp_len0;
997
998 /* Verify UDP checksum */
999 if (PREDICT_FALSE (!good_udp0))
1000 {
1001 if ((flags0 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
1002 {
1003 if (is_ip4)
1004 flags0 = ip4_tcp_udp_validate_checksum (vm, b0);
1005 else
1006 flags0 = ip6_tcp_udp_icmp_validate_checksum (vm, b0);
1007 good_udp0 =
1008 (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1009 }
1010 }
1011
1012 if (is_ip4)
1013 {
1014 error0 = good_udp0 ? 0 : IP4_ERROR_UDP_CHECKSUM;
1015 error0 = (len_diff0 >= 0) ? error0 : IP4_ERROR_UDP_LENGTH;
1016 }
1017 else
1018 {
1019 error0 = good_udp0 ? 0 : IP6_ERROR_UDP_CHECKSUM;
1020 error0 = (len_diff0 >= 0) ? error0 : IP6_ERROR_UDP_LENGTH;
1021 }
1022
1023 next0 = error0 ?
1024 IP_GENEVE_BYPASS_NEXT_DROP : IP_GENEVE_BYPASS_NEXT_GENEVE;
1025 b0->error = error0 ? error_node->errors[error0] : 0;
1026
1027 /* geneve-input node expect current at GENEVE header */
1028 if (is_ip4)
1029 vlib_buffer_advance (b0,
1030 sizeof (ip4_header_t) +
1031 sizeof (udp_header_t));
1032 else
1033 vlib_buffer_advance (b0,
1034 sizeof (ip6_header_t) +
1035 sizeof (udp_header_t));
1036
1037 exit0:
1038 /* Process packet 1 */
1039 if (proto1 != IP_PROTOCOL_UDP)
1040 goto exit1; /* not UDP packet */
1041
1042 if (is_ip4)
1043 udp1 = ip4_next_header (ip41);
1044 else
1045 udp1 = ip6_next_header (ip61);
1046
1047 if (udp1->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_geneve))
1048 goto exit1; /* not GENEVE packet */
1049
1050 /* Validate DIP against VTEPs */
1051 if (is_ip4)
1052 {
Zhiyong Yang5e524172020-07-08 20:28:36 +00001053#ifdef CLIB_HAVE_VEC512
1054 if (!vtep4_check_vector
1055 (&vxm->vtep_table, b1, ip41, &last_vtep4, &vtep4_u512))
1056#else
Nick Zavaritsky27518c22020-02-27 15:54:58 +00001057 if (!vtep4_check (&vxm->vtep_table, b1, ip41, &last_vtep4))
Zhiyong Yang5e524172020-07-08 20:28:36 +00001058#endif
Nick Zavaritsky27518c22020-02-27 15:54:58 +00001059 goto exit1; /* no local VTEP for GENEVE packet */
Marco Varleseb598f1d2017-09-19 14:25:28 +02001060 }
1061 else
1062 {
Nick Zavaritsky27518c22020-02-27 15:54:58 +00001063 if (!vtep6_check (&vxm->vtep_table, b1, ip61, &last_vtep6))
1064 goto exit1; /* no local VTEP for GENEVE packet */
Marco Varleseb598f1d2017-09-19 14:25:28 +02001065 }
1066
1067 flags1 = b1->flags;
1068 good_udp1 = (flags1 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1069
1070 /* Don't verify UDP checksum for packets with explicit zero checksum. */
1071 good_udp1 |= udp1->checksum == 0;
1072
1073 /* Verify UDP length */
1074 if (is_ip4)
1075 ip_len1 = clib_net_to_host_u16 (ip41->length);
1076 else
1077 ip_len1 = clib_net_to_host_u16 (ip61->payload_length);
1078 udp_len1 = clib_net_to_host_u16 (udp1->length);
1079 len_diff1 = ip_len1 - udp_len1;
1080
1081 /* Verify UDP checksum */
1082 if (PREDICT_FALSE (!good_udp1))
1083 {
1084 if ((flags1 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
1085 {
1086 if (is_ip4)
1087 flags1 = ip4_tcp_udp_validate_checksum (vm, b1);
1088 else
1089 flags1 = ip6_tcp_udp_icmp_validate_checksum (vm, b1);
1090 good_udp1 =
1091 (flags1 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1092 }
1093 }
1094
1095 if (is_ip4)
1096 {
1097 error1 = good_udp1 ? 0 : IP4_ERROR_UDP_CHECKSUM;
1098 error1 = (len_diff1 >= 0) ? error1 : IP4_ERROR_UDP_LENGTH;
1099 }
1100 else
1101 {
1102 error1 = good_udp1 ? 0 : IP6_ERROR_UDP_CHECKSUM;
1103 error1 = (len_diff1 >= 0) ? error1 : IP6_ERROR_UDP_LENGTH;
1104 }
1105
1106 next1 = error1 ?
1107 IP_GENEVE_BYPASS_NEXT_DROP : IP_GENEVE_BYPASS_NEXT_GENEVE;
1108 b1->error = error1 ? error_node->errors[error1] : 0;
1109
1110 /* geneve-input node expect current at GENEVE header */
1111 if (is_ip4)
1112 vlib_buffer_advance (b1,
1113 sizeof (ip4_header_t) +
1114 sizeof (udp_header_t));
1115 else
1116 vlib_buffer_advance (b1,
1117 sizeof (ip6_header_t) +
1118 sizeof (udp_header_t));
1119
1120 exit1:
1121 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
1122 to_next, n_left_to_next,
1123 bi0, bi1, next0, next1);
1124 }
1125
1126 while (n_left_from > 0 && n_left_to_next > 0)
1127 {
1128 vlib_buffer_t *b0;
1129 ip4_header_t *ip40;
1130 ip6_header_t *ip60;
1131 udp_header_t *udp0;
1132 u32 bi0, ip_len0, udp_len0, flags0, next0;
1133 i32 len_diff0;
1134 u8 error0, good_udp0, proto0;
1135
1136 bi0 = to_next[0] = from[0];
1137 from += 1;
1138 n_left_from -= 1;
1139 to_next += 1;
1140 n_left_to_next -= 1;
1141
Zhiyong Yang5e524172020-07-08 20:28:36 +00001142 b0 = b[0];
1143 b++;
Marco Varleseb598f1d2017-09-19 14:25:28 +02001144 if (is_ip4)
1145 ip40 = vlib_buffer_get_current (b0);
1146 else
1147 ip60 = vlib_buffer_get_current (b0);
1148
1149 /* Setup packet for next IP feature */
Damjan Marion7d98a122018-07-19 20:42:08 +02001150 vnet_feature_next (&next0, b0);
Marco Varleseb598f1d2017-09-19 14:25:28 +02001151
1152 if (is_ip4)
1153 /* Treat IP4 frag packets as "experimental" protocol for now
1154 until support of IP frag reassembly is implemented */
1155 proto0 = ip4_is_fragment (ip40) ? 0xfe : ip40->protocol;
1156 else
1157 proto0 = ip60->protocol;
1158
1159 if (proto0 != IP_PROTOCOL_UDP)
1160 goto exit; /* not UDP packet */
1161
1162 if (is_ip4)
1163 udp0 = ip4_next_header (ip40);
1164 else
1165 udp0 = ip6_next_header (ip60);
1166
1167 if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_geneve))
1168 goto exit; /* not GENEVE packet */
1169
1170 /* Validate DIP against VTEPs */
1171 if (is_ip4)
1172 {
Zhiyong Yang5e524172020-07-08 20:28:36 +00001173#ifdef CLIB_HAVE_VEC512
1174 if (!vtep4_check_vector
1175 (&vxm->vtep_table, b0, ip40, &last_vtep4, &vtep4_u512))
1176#else
Nick Zavaritsky27518c22020-02-27 15:54:58 +00001177 if (!vtep4_check (&vxm->vtep_table, b0, ip40, &last_vtep4))
Zhiyong Yang5e524172020-07-08 20:28:36 +00001178#endif
Nick Zavaritsky27518c22020-02-27 15:54:58 +00001179 goto exit; /* no local VTEP for GENEVE packet */
Marco Varleseb598f1d2017-09-19 14:25:28 +02001180 }
1181 else
1182 {
Nick Zavaritsky27518c22020-02-27 15:54:58 +00001183 if (!vtep6_check (&vxm->vtep_table, b0, ip60, &last_vtep6))
1184 goto exit; /* no local VTEP for GENEVE packet */
Marco Varleseb598f1d2017-09-19 14:25:28 +02001185 }
1186
1187 flags0 = b0->flags;
1188 good_udp0 = (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1189
1190 /* Don't verify UDP checksum for packets with explicit zero checksum. */
1191 good_udp0 |= udp0->checksum == 0;
1192
1193 /* Verify UDP length */
1194 if (is_ip4)
1195 ip_len0 = clib_net_to_host_u16 (ip40->length);
1196 else
1197 ip_len0 = clib_net_to_host_u16 (ip60->payload_length);
1198 udp_len0 = clib_net_to_host_u16 (udp0->length);
1199 len_diff0 = ip_len0 - udp_len0;
1200
1201 /* Verify UDP checksum */
1202 if (PREDICT_FALSE (!good_udp0))
1203 {
1204 if ((flags0 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
1205 {
1206 if (is_ip4)
1207 flags0 = ip4_tcp_udp_validate_checksum (vm, b0);
1208 else
1209 flags0 = ip6_tcp_udp_icmp_validate_checksum (vm, b0);
1210 good_udp0 =
1211 (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1212 }
1213 }
1214
1215 if (is_ip4)
1216 {
1217 error0 = good_udp0 ? 0 : IP4_ERROR_UDP_CHECKSUM;
1218 error0 = (len_diff0 >= 0) ? error0 : IP4_ERROR_UDP_LENGTH;
1219 }
1220 else
1221 {
1222 error0 = good_udp0 ? 0 : IP6_ERROR_UDP_CHECKSUM;
1223 error0 = (len_diff0 >= 0) ? error0 : IP6_ERROR_UDP_LENGTH;
1224 }
1225
1226 next0 = error0 ?
1227 IP_GENEVE_BYPASS_NEXT_DROP : IP_GENEVE_BYPASS_NEXT_GENEVE;
1228 b0->error = error0 ? error_node->errors[error0] : 0;
1229
1230 /* geneve-input node expect current at GENEVE header */
1231 if (is_ip4)
1232 vlib_buffer_advance (b0,
1233 sizeof (ip4_header_t) +
1234 sizeof (udp_header_t));
1235 else
1236 vlib_buffer_advance (b0,
1237 sizeof (ip6_header_t) +
1238 sizeof (udp_header_t));
1239
1240 exit:
1241 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1242 to_next, n_left_to_next,
1243 bi0, next0);
1244 }
1245
1246 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1247 }
1248
1249 return frame->n_vectors;
1250}
1251
Filip Tehlar55333d72019-03-05 00:36:04 -08001252VLIB_NODE_FN (ip4_geneve_bypass_node) (vlib_main_t * vm,
1253 vlib_node_runtime_t * node,
1254 vlib_frame_t * frame)
Marco Varleseb598f1d2017-09-19 14:25:28 +02001255{
1256 return ip_geneve_bypass_inline (vm, node, frame, /* is_ip4 */ 1);
1257}
1258
1259/* *INDENT-OFF* */
1260VLIB_REGISTER_NODE (ip4_geneve_bypass_node) =
1261{
Neale Ranns91fd9102020-04-03 07:46:28 +00001262 .name = "ip4-geneve-bypass",
1263 .vector_size = sizeof (u32),
1264 .n_next_nodes = IP_GENEVE_BYPASS_N_NEXT,.next_nodes =
Marco Varleseb598f1d2017-09-19 14:25:28 +02001265 {
Neale Ranns91fd9102020-04-03 07:46:28 +00001266 [IP_GENEVE_BYPASS_NEXT_DROP] = "error-drop",
1267 [IP_GENEVE_BYPASS_NEXT_GENEVE] = "geneve4-input",
1268 },
1269 .format_buffer = format_ip4_header,
1270 .format_trace = format_ip4_forward_next_trace,
1271};
Marco Varleseb598f1d2017-09-19 14:25:28 +02001272/* *INDENT-ON* */
1273
Filip Tehlar55333d72019-03-05 00:36:04 -08001274VLIB_NODE_FN (ip6_geneve_bypass_node) (vlib_main_t * vm,
1275 vlib_node_runtime_t * node,
1276 vlib_frame_t * frame)
Marco Varleseb598f1d2017-09-19 14:25:28 +02001277{
1278 return ip_geneve_bypass_inline (vm, node, frame, /* is_ip4 */ 0);
1279}
1280
1281/* *INDENT-OFF* */
1282VLIB_REGISTER_NODE (ip6_geneve_bypass_node) =
1283{
Neale Ranns91fd9102020-04-03 07:46:28 +00001284 .name = "ip6-geneve-bypass",
1285 .vector_size = sizeof (u32),
1286 .n_next_nodes = IP_GENEVE_BYPASS_N_NEXT,
1287 .next_nodes =
Marco Varleseb598f1d2017-09-19 14:25:28 +02001288 {
Neale Ranns91fd9102020-04-03 07:46:28 +00001289 [IP_GENEVE_BYPASS_NEXT_DROP] = "error-drop",
1290 [IP_GENEVE_BYPASS_NEXT_GENEVE] = "geneve6-input",
1291 },
1292 .format_buffer = format_ip6_header,
1293 .format_trace = format_ip6_forward_next_trace,
1294};
Marco Varleseb598f1d2017-09-19 14:25:28 +02001295/* *INDENT-ON* */
1296
Marco Varleseb598f1d2017-09-19 14:25:28 +02001297/*
1298 * fd.io coding-style-patch-verification: ON
1299 *
1300 * Local Variables:
1301 * eval: (c-set-style "gnu")
1302 * End:
1303 */