blob: e30a56c03277f3280b83f0ef5f55dc2043b05097 [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;
Marco Varlese60d48bb2017-11-20 09:20:38 +0100216 key4_0.vni = vnet_get_geneve_vni_bigendian (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;
Marco Varlese60d48bb2017-11-20 09:20:38 +0100251 key4_0.vni = vnet_get_geneve_vni_bigendian (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];
Marco Varlese60d48bb2017-11-20 09:20:38 +0100269 key6_0.vni = vnet_get_geneve_vni_bigendian (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];
Marco Varlese60d48bb2017-11-20 09:20:38 +0100306 key6_0.vni = vnet_get_geneve_vni_bigendian (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;
Marco Varlese60d48bb2017-11-20 09:20:38 +0100383 key4_1.vni = vnet_get_geneve_vni_bigendian (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;
Marco Varlese60d48bb2017-11-20 09:20:38 +0100418 key4_1.vni = vnet_get_geneve_vni_bigendian (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];
Marco Varlese60d48bb2017-11-20 09:20:38 +0100436 key6_1.vni = vnet_get_geneve_vni_bigendian (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];
Marco Varlese60d48bb2017-11-20 09:20:38 +0100475 key6_1.vni = vnet_get_geneve_vni_bigendian (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;
Marco Varlese60d48bb2017-11-20 09:20:38 +0100621 key4_0.vni = vnet_get_geneve_vni_bigendian (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;
Marco Varlese60d48bb2017-11-20 09:20:38 +0100656 key4_0.vni = vnet_get_geneve_vni_bigendian (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];
Marco Varlese60d48bb2017-11-20 09:20:38 +0100674 key6_0.vni = vnet_get_geneve_vni_bigendian (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];
Marco Varlese60d48bb2017-11-20 09:20:38 +0100711 key6_0.vni = vnet_get_geneve_vni_bigendian (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);
868 ip4_address_t addr4; /* last IPv4 address matching a local VTEP address */
869 ip6_address_t addr6; /* last IPv6 address matching a local VTEP address */
870
871 from = vlib_frame_vector_args (frame);
872 n_left_from = frame->n_vectors;
873 next_index = node->cached_next_index;
874
875 if (node->flags & VLIB_NODE_FLAG_TRACE)
876 ip4_forward_next_trace (vm, node, frame, VLIB_TX);
877
878 if (is_ip4)
879 addr4.data_u32 = ~0;
880 else
881 ip6_address_set_zero (&addr6);
882
883 while (n_left_from > 0)
884 {
885 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
886
887 while (n_left_from >= 4 && n_left_to_next >= 2)
888 {
889 vlib_buffer_t *b0, *b1;
890 ip4_header_t *ip40, *ip41;
891 ip6_header_t *ip60, *ip61;
892 udp_header_t *udp0, *udp1;
893 u32 bi0, ip_len0, udp_len0, flags0, next0;
894 u32 bi1, ip_len1, udp_len1, flags1, next1;
895 i32 len_diff0, len_diff1;
896 u8 error0, good_udp0, proto0;
897 u8 error1, good_udp1, proto1;
898
899 /* Prefetch next iteration. */
900 {
901 vlib_buffer_t *p2, *p3;
902
903 p2 = vlib_get_buffer (vm, from[2]);
904 p3 = vlib_get_buffer (vm, from[3]);
905
906 vlib_prefetch_buffer_header (p2, LOAD);
907 vlib_prefetch_buffer_header (p3, LOAD);
908
909 CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
910 CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
911 }
912
913 bi0 = to_next[0] = from[0];
914 bi1 = to_next[1] = from[1];
915 from += 2;
916 n_left_from -= 2;
917 to_next += 2;
918 n_left_to_next -= 2;
919
920 b0 = vlib_get_buffer (vm, bi0);
921 b1 = vlib_get_buffer (vm, bi1);
922 if (is_ip4)
923 {
924 ip40 = vlib_buffer_get_current (b0);
925 ip41 = vlib_buffer_get_current (b1);
926 }
927 else
928 {
929 ip60 = vlib_buffer_get_current (b0);
930 ip61 = vlib_buffer_get_current (b1);
931 }
932
933 /* Setup packet for next IP feature */
Damjan Marion7d98a122018-07-19 20:42:08 +0200934 vnet_feature_next (&next0, b0);
935 vnet_feature_next (&next1, b1);
Marco Varleseb598f1d2017-09-19 14:25:28 +0200936
937 if (is_ip4)
938 {
939 /* Treat IP frag packets as "experimental" protocol for now
940 until support of IP frag reassembly is implemented */
941 proto0 = ip4_is_fragment (ip40) ? 0xfe : ip40->protocol;
942 proto1 = ip4_is_fragment (ip41) ? 0xfe : ip41->protocol;
943 }
944 else
945 {
946 proto0 = ip60->protocol;
947 proto1 = ip61->protocol;
948 }
949
950 /* Process packet 0 */
951 if (proto0 != IP_PROTOCOL_UDP)
952 goto exit0; /* not UDP packet */
953
954 if (is_ip4)
955 udp0 = ip4_next_header (ip40);
956 else
957 udp0 = ip6_next_header (ip60);
958
959 if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_geneve))
960 goto exit0; /* not GENEVE packet */
961
962 /* Validate DIP against VTEPs */
963 if (is_ip4)
964 {
965 if (addr4.as_u32 != ip40->dst_address.as_u32)
966 {
967 if (!hash_get (vxm->vtep4, ip40->dst_address.as_u32))
968 goto exit0; /* no local VTEP for GENEVE packet */
969 addr4 = ip40->dst_address;
970 }
971 }
972 else
973 {
974 if (!ip6_address_is_equal (&addr6, &ip60->dst_address))
975 {
976 if (!hash_get_mem (vxm->vtep6, &ip60->dst_address))
977 goto exit0; /* no local VTEP for GENEVE packet */
978 addr6 = ip60->dst_address;
979 }
980 }
981
982 flags0 = b0->flags;
983 good_udp0 = (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
984
985 /* Don't verify UDP checksum for packets with explicit zero checksum. */
986 good_udp0 |= udp0->checksum == 0;
987
988 /* Verify UDP length */
989 if (is_ip4)
990 ip_len0 = clib_net_to_host_u16 (ip40->length);
991 else
992 ip_len0 = clib_net_to_host_u16 (ip60->payload_length);
993 udp_len0 = clib_net_to_host_u16 (udp0->length);
994 len_diff0 = ip_len0 - udp_len0;
995
996 /* Verify UDP checksum */
997 if (PREDICT_FALSE (!good_udp0))
998 {
999 if ((flags0 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
1000 {
1001 if (is_ip4)
1002 flags0 = ip4_tcp_udp_validate_checksum (vm, b0);
1003 else
1004 flags0 = ip6_tcp_udp_icmp_validate_checksum (vm, b0);
1005 good_udp0 =
1006 (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1007 }
1008 }
1009
1010 if (is_ip4)
1011 {
1012 error0 = good_udp0 ? 0 : IP4_ERROR_UDP_CHECKSUM;
1013 error0 = (len_diff0 >= 0) ? error0 : IP4_ERROR_UDP_LENGTH;
1014 }
1015 else
1016 {
1017 error0 = good_udp0 ? 0 : IP6_ERROR_UDP_CHECKSUM;
1018 error0 = (len_diff0 >= 0) ? error0 : IP6_ERROR_UDP_LENGTH;
1019 }
1020
1021 next0 = error0 ?
1022 IP_GENEVE_BYPASS_NEXT_DROP : IP_GENEVE_BYPASS_NEXT_GENEVE;
1023 b0->error = error0 ? error_node->errors[error0] : 0;
1024
1025 /* geneve-input node expect current at GENEVE header */
1026 if (is_ip4)
1027 vlib_buffer_advance (b0,
1028 sizeof (ip4_header_t) +
1029 sizeof (udp_header_t));
1030 else
1031 vlib_buffer_advance (b0,
1032 sizeof (ip6_header_t) +
1033 sizeof (udp_header_t));
1034
1035 exit0:
1036 /* Process packet 1 */
1037 if (proto1 != IP_PROTOCOL_UDP)
1038 goto exit1; /* not UDP packet */
1039
1040 if (is_ip4)
1041 udp1 = ip4_next_header (ip41);
1042 else
1043 udp1 = ip6_next_header (ip61);
1044
1045 if (udp1->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_geneve))
1046 goto exit1; /* not GENEVE packet */
1047
1048 /* Validate DIP against VTEPs */
1049 if (is_ip4)
1050 {
1051 if (addr4.as_u32 != ip41->dst_address.as_u32)
1052 {
1053 if (!hash_get (vxm->vtep4, ip41->dst_address.as_u32))
1054 goto exit1; /* no local VTEP for GENEVE packet */
1055 addr4 = ip41->dst_address;
1056 }
1057 }
1058 else
1059 {
1060 if (!ip6_address_is_equal (&addr6, &ip61->dst_address))
1061 {
1062 if (!hash_get_mem (vxm->vtep6, &ip61->dst_address))
1063 goto exit1; /* no local VTEP for GENEVE packet */
1064 addr6 = ip61->dst_address;
1065 }
1066 }
1067
1068 flags1 = b1->flags;
1069 good_udp1 = (flags1 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1070
1071 /* Don't verify UDP checksum for packets with explicit zero checksum. */
1072 good_udp1 |= udp1->checksum == 0;
1073
1074 /* Verify UDP length */
1075 if (is_ip4)
1076 ip_len1 = clib_net_to_host_u16 (ip41->length);
1077 else
1078 ip_len1 = clib_net_to_host_u16 (ip61->payload_length);
1079 udp_len1 = clib_net_to_host_u16 (udp1->length);
1080 len_diff1 = ip_len1 - udp_len1;
1081
1082 /* Verify UDP checksum */
1083 if (PREDICT_FALSE (!good_udp1))
1084 {
1085 if ((flags1 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
1086 {
1087 if (is_ip4)
1088 flags1 = ip4_tcp_udp_validate_checksum (vm, b1);
1089 else
1090 flags1 = ip6_tcp_udp_icmp_validate_checksum (vm, b1);
1091 good_udp1 =
1092 (flags1 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1093 }
1094 }
1095
1096 if (is_ip4)
1097 {
1098 error1 = good_udp1 ? 0 : IP4_ERROR_UDP_CHECKSUM;
1099 error1 = (len_diff1 >= 0) ? error1 : IP4_ERROR_UDP_LENGTH;
1100 }
1101 else
1102 {
1103 error1 = good_udp1 ? 0 : IP6_ERROR_UDP_CHECKSUM;
1104 error1 = (len_diff1 >= 0) ? error1 : IP6_ERROR_UDP_LENGTH;
1105 }
1106
1107 next1 = error1 ?
1108 IP_GENEVE_BYPASS_NEXT_DROP : IP_GENEVE_BYPASS_NEXT_GENEVE;
1109 b1->error = error1 ? error_node->errors[error1] : 0;
1110
1111 /* geneve-input node expect current at GENEVE header */
1112 if (is_ip4)
1113 vlib_buffer_advance (b1,
1114 sizeof (ip4_header_t) +
1115 sizeof (udp_header_t));
1116 else
1117 vlib_buffer_advance (b1,
1118 sizeof (ip6_header_t) +
1119 sizeof (udp_header_t));
1120
1121 exit1:
1122 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
1123 to_next, n_left_to_next,
1124 bi0, bi1, next0, next1);
1125 }
1126
1127 while (n_left_from > 0 && n_left_to_next > 0)
1128 {
1129 vlib_buffer_t *b0;
1130 ip4_header_t *ip40;
1131 ip6_header_t *ip60;
1132 udp_header_t *udp0;
1133 u32 bi0, ip_len0, udp_len0, flags0, next0;
1134 i32 len_diff0;
1135 u8 error0, good_udp0, proto0;
1136
1137 bi0 = to_next[0] = from[0];
1138 from += 1;
1139 n_left_from -= 1;
1140 to_next += 1;
1141 n_left_to_next -= 1;
1142
1143 b0 = vlib_get_buffer (vm, bi0);
1144 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 {
1173 if (addr4.as_u32 != ip40->dst_address.as_u32)
1174 {
1175 if (!hash_get (vxm->vtep4, ip40->dst_address.as_u32))
1176 goto exit; /* no local VTEP for GENEVE packet */
1177 addr4 = ip40->dst_address;
1178 }
1179 }
1180 else
1181 {
1182 if (!ip6_address_is_equal (&addr6, &ip60->dst_address))
1183 {
1184 if (!hash_get_mem (vxm->vtep6, &ip60->dst_address))
1185 goto exit; /* no local VTEP for GENEVE packet */
1186 addr6 = ip60->dst_address;
1187 }
1188 }
1189
1190 flags0 = b0->flags;
1191 good_udp0 = (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1192
1193 /* Don't verify UDP checksum for packets with explicit zero checksum. */
1194 good_udp0 |= udp0->checksum == 0;
1195
1196 /* Verify UDP length */
1197 if (is_ip4)
1198 ip_len0 = clib_net_to_host_u16 (ip40->length);
1199 else
1200 ip_len0 = clib_net_to_host_u16 (ip60->payload_length);
1201 udp_len0 = clib_net_to_host_u16 (udp0->length);
1202 len_diff0 = ip_len0 - udp_len0;
1203
1204 /* Verify UDP checksum */
1205 if (PREDICT_FALSE (!good_udp0))
1206 {
1207 if ((flags0 & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED) == 0)
1208 {
1209 if (is_ip4)
1210 flags0 = ip4_tcp_udp_validate_checksum (vm, b0);
1211 else
1212 flags0 = ip6_tcp_udp_icmp_validate_checksum (vm, b0);
1213 good_udp0 =
1214 (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1215 }
1216 }
1217
1218 if (is_ip4)
1219 {
1220 error0 = good_udp0 ? 0 : IP4_ERROR_UDP_CHECKSUM;
1221 error0 = (len_diff0 >= 0) ? error0 : IP4_ERROR_UDP_LENGTH;
1222 }
1223 else
1224 {
1225 error0 = good_udp0 ? 0 : IP6_ERROR_UDP_CHECKSUM;
1226 error0 = (len_diff0 >= 0) ? error0 : IP6_ERROR_UDP_LENGTH;
1227 }
1228
1229 next0 = error0 ?
1230 IP_GENEVE_BYPASS_NEXT_DROP : IP_GENEVE_BYPASS_NEXT_GENEVE;
1231 b0->error = error0 ? error_node->errors[error0] : 0;
1232
1233 /* geneve-input node expect current at GENEVE header */
1234 if (is_ip4)
1235 vlib_buffer_advance (b0,
1236 sizeof (ip4_header_t) +
1237 sizeof (udp_header_t));
1238 else
1239 vlib_buffer_advance (b0,
1240 sizeof (ip6_header_t) +
1241 sizeof (udp_header_t));
1242
1243 exit:
1244 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1245 to_next, n_left_to_next,
1246 bi0, next0);
1247 }
1248
1249 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1250 }
1251
1252 return frame->n_vectors;
1253}
1254
Filip Tehlar55333d72019-03-05 00:36:04 -08001255VLIB_NODE_FN (ip4_geneve_bypass_node) (vlib_main_t * vm,
1256 vlib_node_runtime_t * node,
1257 vlib_frame_t * frame)
Marco Varleseb598f1d2017-09-19 14:25:28 +02001258{
1259 return ip_geneve_bypass_inline (vm, node, frame, /* is_ip4 */ 1);
1260}
1261
1262/* *INDENT-OFF* */
1263VLIB_REGISTER_NODE (ip4_geneve_bypass_node) =
1264{
Filip Tehlar55333d72019-03-05 00:36:04 -08001265 .name = "ip4-geneve-bypass",.vector_size =
Marco Varleseb598f1d2017-09-19 14:25:28 +02001266 sizeof (u32),.n_next_nodes = IP_GENEVE_BYPASS_N_NEXT,.next_nodes =
1267 {
1268 [IP_GENEVE_BYPASS_NEXT_DROP] = "error-drop",
1269 [IP_GENEVE_BYPASS_NEXT_GENEVE] = "geneve4-input",}
1270,.format_buffer = format_ip4_header,.format_trace =
1271 format_ip4_forward_next_trace,};
1272
Filip Tehlar55333d72019-03-05 00:36:04 -08001273#ifndef CLIB_MARCH_VARIANT
Marco Varleseb598f1d2017-09-19 14:25:28 +02001274/* Dummy init function to get us linked in. */
1275 clib_error_t *ip4_geneve_bypass_init (vlib_main_t * vm)
1276{
1277 return 0;
1278}
1279
1280VLIB_INIT_FUNCTION (ip4_geneve_bypass_init);
1281/* *INDENT-ON* */
Filip Tehlar55333d72019-03-05 00:36:04 -08001282#endif /* CLIB_MARCH_VARIANT */
Marco Varleseb598f1d2017-09-19 14:25:28 +02001283
Filip Tehlar55333d72019-03-05 00:36:04 -08001284VLIB_NODE_FN (ip6_geneve_bypass_node) (vlib_main_t * vm,
1285 vlib_node_runtime_t * node,
1286 vlib_frame_t * frame)
Marco Varleseb598f1d2017-09-19 14:25:28 +02001287{
1288 return ip_geneve_bypass_inline (vm, node, frame, /* is_ip4 */ 0);
1289}
1290
1291/* *INDENT-OFF* */
1292VLIB_REGISTER_NODE (ip6_geneve_bypass_node) =
1293{
Filip Tehlar55333d72019-03-05 00:36:04 -08001294 .name = "ip6-geneve-bypass",.vector_size =
Marco Varleseb598f1d2017-09-19 14:25:28 +02001295 sizeof (u32),.n_next_nodes = IP_GENEVE_BYPASS_N_NEXT,.next_nodes =
1296 {
1297 [IP_GENEVE_BYPASS_NEXT_DROP] = "error-drop",
1298 [IP_GENEVE_BYPASS_NEXT_GENEVE] = "geneve6-input",}
1299,.format_buffer = format_ip6_header,.format_trace =
1300 format_ip6_forward_next_trace,};
1301/* *INDENT-ON* */
1302
Filip Tehlar55333d72019-03-05 00:36:04 -08001303#ifndef CLIB_MARCH_VARIANT
Marco Varleseb598f1d2017-09-19 14:25:28 +02001304/* Dummy init function to get us linked in. */
Filip Tehlar55333d72019-03-05 00:36:04 -08001305clib_error_t *
1306ip6_geneve_bypass_init (vlib_main_t * vm)
Marco Varleseb598f1d2017-09-19 14:25:28 +02001307{
1308 return 0;
1309}
1310
1311VLIB_INIT_FUNCTION (ip6_geneve_bypass_init);
Filip Tehlar55333d72019-03-05 00:36:04 -08001312#endif /* CLIB_MARCH_VARIANT */
Marco Varleseb598f1d2017-09-19 14:25:28 +02001313
1314/*
1315 * fd.io coding-style-patch-verification: ON
1316 *
1317 * Local Variables:
1318 * eval: (c-set-style "gnu")
1319 * End:
1320 */