Line data Source code
1 : /*
2 : * Copyright (c) 2016 Cisco and/or its affiliates.
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 <lb/lb.h>
17 : #include <vnet/fib/ip4_fib.h>
18 :
19 : #include <vnet/gre/packet.h>
20 : #include <lb/lbhash.h>
21 :
22 : #define foreach_lb_error \
23 : _(NONE, "no error") \
24 : _(PROTO_NOT_SUPPORTED, "protocol not supported")
25 :
26 : typedef enum
27 : {
28 : #define _(sym,str) LB_ERROR_##sym,
29 : foreach_lb_error
30 : #undef _
31 : LB_N_ERROR,
32 : } lb_error_t;
33 :
34 : static char *lb_error_strings[] =
35 : {
36 : #define _(sym,string) string,
37 : foreach_lb_error
38 : #undef _
39 : };
40 :
41 : typedef struct
42 : {
43 : u32 vip_index;
44 : u32 as_index;
45 : } lb_trace_t;
46 :
47 : typedef struct
48 : {
49 : u32 vip_index;
50 :
51 : u32 node_port;
52 : } lb_nodeport_trace_t;
53 :
54 : typedef struct
55 : {
56 : u32 vip_index;
57 : u32 as_index;
58 : u32 rx_sw_if_index;
59 : u32 next_index;
60 : } lb_nat_trace_t;
61 :
62 : u8 *
63 1300 : format_lb_trace (u8 * s, va_list * args)
64 : {
65 1300 : lb_main_t *lbm = &lb_main;
66 1300 : CLIB_UNUSED(vlib_main_t * vm)
67 : = va_arg (*args, vlib_main_t *);
68 1300 : CLIB_UNUSED(vlib_node_t * node)
69 : = va_arg (*args, vlib_node_t *);
70 1300 : lb_trace_t *t = va_arg (*args, lb_trace_t *);
71 1300 : if (pool_is_free_index(lbm->vips, t->vip_index))
72 : {
73 0 : s = format (s, "lb vip[%d]: This VIP was freed since capture\n");
74 : }
75 : else
76 : {
77 1300 : s = format (s, "lb vip[%d]: %U\n", t->vip_index, format_lb_vip,
78 1300 : &lbm->vips[t->vip_index]);
79 : }
80 1300 : if (pool_is_free_index(lbm->ass, t->as_index))
81 : {
82 0 : s = format (s, "lb as[%d]: This AS was freed since capture\n");
83 : }
84 : else
85 : {
86 1300 : s = format (s, "lb as[%d]: %U\n", t->as_index, format_lb_as,
87 1300 : &lbm->ass[t->as_index]);
88 : }
89 1300 : return s;
90 : }
91 :
92 : u8 *
93 0 : format_lb_nat_trace (u8 * s, va_list * args)
94 : {
95 0 : lb_main_t *lbm = &lb_main;
96 0 : CLIB_UNUSED(vlib_main_t * vm)
97 : = va_arg (*args, vlib_main_t *);
98 0 : CLIB_UNUSED(vlib_node_t * node)
99 : = va_arg (*args, vlib_node_t *);
100 0 : lb_nat_trace_t *t = va_arg (*args, lb_nat_trace_t *);
101 :
102 0 : if (pool_is_free_index(lbm->vips, t->vip_index))
103 : {
104 0 : s = format (s, "lb vip[%d]: This VIP was freed since capture\n");
105 : }
106 : else
107 : {
108 0 : s = format (s, "lb vip[%d]: %U\n", t->vip_index, format_lb_vip,
109 0 : &lbm->vips[t->vip_index]);
110 : }
111 0 : if (pool_is_free_index(lbm->ass, t->as_index))
112 : {
113 0 : s = format (s, "lb as[%d]: This AS was freed since capture\n");
114 : }
115 : else
116 : {
117 0 : s = format (s, "lb as[%d]: %U\n", t->as_index, format_lb_as,
118 0 : &lbm->ass[t->as_index]);
119 : }
120 0 : s = format (s, "lb nat: rx_sw_if_index = %d, next_index = %d",
121 : t->rx_sw_if_index, t->next_index);
122 :
123 0 : return s;
124 : }
125 :
126 : lb_hash_t *
127 13 : lb_get_sticky_table (u32 thread_index)
128 : {
129 13 : lb_main_t *lbm = &lb_main;
130 13 : lb_hash_t *sticky_ht = lbm->per_cpu[thread_index].sticky_ht;
131 : //Check if size changed
132 13 : if (PREDICT_FALSE(
133 : sticky_ht && (lbm->per_cpu_sticky_buckets != lb_hash_nbuckets(sticky_ht))))
134 : {
135 : //Dereference everything in there
136 : lb_hash_bucket_t *b;
137 : u32 i;
138 0 : lb_hash_foreach_entry(sticky_ht, b, i)
139 : {
140 0 : vlib_refcount_add (&lbm->as_refcount, thread_index, b->value[i], -1);
141 0 : vlib_refcount_add (&lbm->as_refcount, thread_index, 0, 1);
142 : }
143 :
144 0 : lb_hash_free (sticky_ht);
145 0 : sticky_ht = NULL;
146 : }
147 :
148 : //Create if necessary
149 13 : if (PREDICT_FALSE(sticky_ht == NULL))
150 : {
151 13 : lbm->per_cpu[thread_index].sticky_ht = lb_hash_alloc (
152 : lbm->per_cpu_sticky_buckets, lbm->flow_timeout);
153 13 : sticky_ht = lbm->per_cpu[thread_index].sticky_ht;
154 13 : clib_warning("Regenerated sticky table %p", sticky_ht);
155 : }
156 :
157 13 : ASSERT(sticky_ht);
158 :
159 : //Update timeout
160 13 : sticky_ht->timeout = lbm->flow_timeout;
161 13 : return sticky_ht;
162 : }
163 :
164 : u64
165 0 : lb_node_get_other_ports4 (ip4_header_t *ip40)
166 : {
167 0 : return 0;
168 : }
169 :
170 : u64
171 0 : lb_node_get_other_ports6 (ip6_header_t *ip60)
172 : {
173 0 : return 0;
174 : }
175 :
176 : static_always_inline void
177 1300 : lb_node_get_hash (lb_main_t *lbm, vlib_buffer_t *p, u8 is_input_v4, u32 *hash,
178 : u32 *vip_idx, u8 per_port_vip, u8 src_ip_sticky)
179 : {
180 : vip_port_key_t key;
181 : clib_bihash_kv_8_8_t kv, value;
182 :
183 : /* For vip case, retrieve vip index for ip lookup */
184 1300 : *vip_idx = vnet_buffer (p)->ip.adj_index[VLIB_TX];
185 :
186 1300 : if (per_port_vip)
187 : {
188 : /* For per-port-vip case, ip lookup stores placeholder index */
189 800 : key.vip_prefix_index = *vip_idx;
190 : }
191 :
192 1300 : if (is_input_v4)
193 : {
194 : ip4_header_t *ip40;
195 : u64 ports;
196 :
197 800 : ip40 = vlib_buffer_get_current (p);
198 800 : if (PREDICT_TRUE(
199 : ip40->protocol == IP_PROTOCOL_TCP
200 : || ip40->protocol == IP_PROTOCOL_UDP))
201 800 : ports = ((u64) ((udp_header_t *) (ip40 + 1))->src_port << 16)
202 800 : | ((u64) ((udp_header_t *) (ip40 + 1))->dst_port);
203 : else
204 0 : ports = lb_node_get_other_ports4 (ip40);
205 :
206 800 : if (src_ip_sticky)
207 : {
208 100 : *hash = lb_hash_hash (*((u64 *) &ip40->address_pair), 0, 0, 0, 0);
209 : }
210 : else
211 : {
212 700 : *hash =
213 700 : lb_hash_hash (*((u64 *) &ip40->address_pair), ports, 0, 0, 0);
214 : }
215 :
216 800 : if (per_port_vip)
217 : {
218 500 : key.protocol = ip40->protocol;
219 500 : key.port = (u16)(ports & 0xFFFF);
220 : }
221 : }
222 : else
223 : {
224 : ip6_header_t *ip60;
225 500 : ip60 = vlib_buffer_get_current (p);
226 : u64 ports;
227 :
228 500 : if (PREDICT_TRUE(
229 : ip60->protocol == IP_PROTOCOL_TCP
230 : || ip60->protocol == IP_PROTOCOL_UDP))
231 500 : ports = ((u64) ((udp_header_t *) (ip60 + 1))->src_port << 16)
232 500 : | ((u64) ((udp_header_t *) (ip60 + 1))->dst_port);
233 : else
234 0 : ports = lb_node_get_other_ports6 (ip60);
235 :
236 500 : if (src_ip_sticky)
237 : {
238 0 : *hash = lb_hash_hash (
239 : ip60->src_address.as_u64[0], ip60->src_address.as_u64[1],
240 : ip60->dst_address.as_u64[0], ip60->dst_address.as_u64[1], 0);
241 : }
242 : else
243 : {
244 500 : *hash = lb_hash_hash (
245 : ip60->src_address.as_u64[0], ip60->src_address.as_u64[1],
246 : ip60->dst_address.as_u64[0], ip60->dst_address.as_u64[1], ports);
247 : }
248 :
249 500 : if (per_port_vip)
250 : {
251 300 : key.protocol = ip60->protocol;
252 300 : key.port = (u16)(ports & 0xFFFF);
253 : }
254 : }
255 :
256 : /* For per-port-vip case, retrieve vip index for vip_port_filter table */
257 1300 : if (per_port_vip)
258 : {
259 800 : kv.key = key.as_u64;
260 800 : if (clib_bihash_search_8_8(&lbm->vip_index_per_port, &kv, &value) < 0)
261 : {
262 : /* return default vip */
263 0 : *vip_idx = 0;
264 0 : return;
265 : }
266 800 : *vip_idx = value.value;
267 : }
268 : }
269 :
270 : /* clang-format off */
271 : static_always_inline uword
272 13 : lb_node_fn (vlib_main_t * vm,
273 : vlib_node_runtime_t * node,
274 : vlib_frame_t * frame,
275 : u8 is_input_v4, //Compile-time parameter stating that is input is v4 (or v6)
276 : lb_encap_type_t encap_type, //Compile-time parameter is GRE4/GRE6/L3DSR/NAT4/NAT6
277 : u8 per_port_vip, //Compile-time parameter stating that is per_port_vip or not
278 : u8 src_ip_sticky) //Compile-time parameter stating that is source ip based sticky or not
279 : {
280 13 : lb_main_t *lbm = &lb_main;
281 : u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
282 13 : u32 thread_index = vm->thread_index;
283 13 : u32 lb_time = lb_hash_time_now (vm);
284 :
285 13 : lb_hash_t *sticky_ht = lb_get_sticky_table (thread_index);
286 13 : from = vlib_frame_vector_args (frame);
287 13 : n_left_from = frame->n_vectors;
288 13 : next_index = node->cached_next_index;
289 :
290 13 : u32 nexthash0 = 0;
291 13 : u32 next_vip_idx0 = ~0;
292 13 : if (PREDICT_TRUE(n_left_from > 0))
293 : {
294 13 : vlib_buffer_t *p0 = vlib_get_buffer (vm, from[0]);
295 13 : lb_node_get_hash (lbm, p0, is_input_v4, &nexthash0,
296 : &next_vip_idx0, per_port_vip, src_ip_sticky);
297 : }
298 :
299 26 : while (n_left_from > 0)
300 : {
301 13 : vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
302 1313 : while (n_left_from > 0 && n_left_to_next > 0)
303 : {
304 : u32 pi0;
305 : vlib_buffer_t *p0;
306 : lb_vip_t *vip0;
307 1300 : u32 asindex0 = 0;
308 : u16 len0;
309 : u32 available_index0;
310 1300 : u8 counter = 0;
311 1300 : u32 hash0 = nexthash0;
312 1300 : u32 vip_index0 = next_vip_idx0;
313 : u32 next0;
314 :
315 1300 : if (PREDICT_TRUE(n_left_from > 1))
316 : {
317 1287 : vlib_buffer_t *p1 = vlib_get_buffer (vm, from[1]);
318 : //Compute next hash and prefetch bucket
319 1287 : lb_node_get_hash (lbm, p1, is_input_v4,
320 : &nexthash0, &next_vip_idx0,
321 : per_port_vip, src_ip_sticky);
322 1287 : lb_hash_prefetch_bucket (sticky_ht, nexthash0);
323 : //Prefetch for encap, next
324 1287 : CLIB_PREFETCH(vlib_buffer_get_current (p1) - 64, 64, STORE);
325 : }
326 :
327 1300 : if (PREDICT_TRUE(n_left_from > 2))
328 : {
329 : vlib_buffer_t *p2;
330 1274 : p2 = vlib_get_buffer (vm, from[2]);
331 : /* prefetch packet header and data */
332 1274 : vlib_prefetch_buffer_header(p2, STORE);
333 1274 : CLIB_PREFETCH(vlib_buffer_get_current (p2), 64, STORE);
334 : }
335 :
336 1300 : pi0 = to_next[0] = from[0];
337 1300 : from += 1;
338 1300 : n_left_from -= 1;
339 1300 : to_next += 1;
340 1300 : n_left_to_next -= 1;
341 :
342 1300 : p0 = vlib_get_buffer (vm, pi0);
343 :
344 1300 : vip0 = pool_elt_at_index(lbm->vips, vip_index0);
345 :
346 1300 : if (is_input_v4)
347 : {
348 : ip4_header_t *ip40;
349 800 : ip40 = vlib_buffer_get_current (p0);
350 800 : len0 = clib_net_to_host_u16 (ip40->length);
351 : }
352 : else
353 : {
354 : ip6_header_t *ip60;
355 500 : ip60 = vlib_buffer_get_current (p0);
356 500 : len0 = clib_net_to_host_u16 (ip60->payload_length)
357 : + sizeof(ip6_header_t);
358 : }
359 :
360 1300 : lb_hash_get (sticky_ht, hash0,
361 : vip_index0, lb_time,
362 : &available_index0, &asindex0);
363 :
364 1300 : if (PREDICT_TRUE(asindex0 != 0))
365 : {
366 : //Found an existing entry
367 50 : counter = LB_VIP_COUNTER_NEXT_PACKET;
368 : }
369 1250 : else if (PREDICT_TRUE(available_index0 != ~0))
370 : {
371 : //There is an available slot for a new flow
372 1250 : asindex0 =
373 1250 : vip0->new_flow_table[hash0 & vip0->new_flow_table_mask].as_index;
374 1250 : counter = LB_VIP_COUNTER_FIRST_PACKET;
375 1250 : counter = (asindex0 == 0) ? LB_VIP_COUNTER_NO_SERVER : counter;
376 :
377 : //TODO: There are race conditions with as0 and vip0 manipulation.
378 : //Configuration may be changed, vectors resized, etc...
379 :
380 : //Dereference previously used
381 1250 : vlib_refcount_add (
382 : &lbm->as_refcount, thread_index,
383 : lb_hash_available_value (sticky_ht, hash0, available_index0),
384 : -1);
385 1250 : vlib_refcount_add (&lbm->as_refcount, thread_index, asindex0, 1);
386 :
387 : //Add sticky entry
388 : //Note that when there is no AS configured, an entry is configured anyway.
389 : //But no configured AS is not something that should happen
390 1250 : lb_hash_put (sticky_ht, hash0, asindex0,
391 : vip_index0,
392 : available_index0, lb_time);
393 : }
394 : else
395 : {
396 : //Could not store new entry in the table
397 0 : asindex0 =
398 0 : vip0->new_flow_table[hash0 & vip0->new_flow_table_mask].as_index;
399 0 : counter = LB_VIP_COUNTER_UNTRACKED_PACKET;
400 : }
401 :
402 1300 : vlib_increment_simple_counter (
403 1300 : &lbm->vip_counters[counter], thread_index,
404 : vip_index0,
405 : 1);
406 :
407 : //Now let's encap
408 1300 : if ((encap_type == LB_ENCAP_TYPE_GRE4)
409 900 : || (encap_type == LB_ENCAP_TYPE_GRE6))
410 800 : {
411 : gre_header_t *gre0;
412 800 : if (encap_type == LB_ENCAP_TYPE_GRE4) /* encap GRE4*/
413 : {
414 : ip4_header_t *ip40;
415 400 : vlib_buffer_advance (
416 : p0, -sizeof(ip4_header_t) - sizeof(gre_header_t));
417 400 : ip40 = vlib_buffer_get_current (p0);
418 400 : gre0 = (gre_header_t *) (ip40 + 1);
419 400 : ip40->src_address = lbm->ip4_src_address;
420 400 : ip40->dst_address = lbm->ass[asindex0].address.ip4;
421 400 : ip40->ip_version_and_header_length = 0x45;
422 400 : ip40->ttl = 128;
423 400 : ip40->fragment_id = 0;
424 400 : ip40->flags_and_fragment_offset = 0;
425 800 : ip40->length = clib_host_to_net_u16 (
426 400 : len0 + sizeof(gre_header_t) + sizeof(ip4_header_t));
427 400 : ip40->protocol = IP_PROTOCOL_GRE;
428 400 : ip40->checksum = ip4_header_checksum (ip40);
429 : }
430 : else /* encap GRE6*/
431 : {
432 : ip6_header_t *ip60;
433 400 : vlib_buffer_advance (
434 : p0, -sizeof(ip6_header_t) - sizeof(gre_header_t));
435 400 : ip60 = vlib_buffer_get_current (p0);
436 400 : gre0 = (gre_header_t *) (ip60 + 1);
437 400 : ip60->dst_address = lbm->ass[asindex0].address.ip6;
438 400 : ip60->src_address = lbm->ip6_src_address;
439 400 : ip60->hop_limit = 128;
440 400 : ip60->ip_version_traffic_class_and_flow_label =
441 400 : clib_host_to_net_u32 (0x6 << 28);
442 800 : ip60->payload_length = clib_host_to_net_u16 (
443 400 : len0 + sizeof(gre_header_t));
444 400 : ip60->protocol = IP_PROTOCOL_GRE;
445 : }
446 :
447 800 : gre0->flags_and_version = 0;
448 1600 : gre0->protocol =
449 : (is_input_v4) ?
450 400 : clib_host_to_net_u16 (0x0800) :
451 400 : clib_host_to_net_u16 (0x86DD);
452 : }
453 500 : else if (encap_type == LB_ENCAP_TYPE_L3DSR) /* encap L3DSR*/
454 : {
455 : ip4_header_t *ip40;
456 : ip_csum_t csum;
457 : u32 old_dst, new_dst;
458 : u8 old_tos, new_tos;
459 :
460 300 : ip40 = vlib_buffer_get_current (p0);
461 300 : old_dst = ip40->dst_address.as_u32;
462 300 : new_dst = lbm->ass[asindex0].address.ip4.as_u32;
463 300 : ip40->dst_address.as_u32 = lbm->ass[asindex0].address.ip4.as_u32;
464 : /* Get and rewrite DSCP bit */
465 300 : old_tos = ip40->tos;
466 300 : new_tos = (u8) ((vip0->encap_args.dscp & 0x3F) << 2);
467 300 : ip40->tos = (u8) ((vip0->encap_args.dscp & 0x3F) << 2);
468 :
469 300 : csum = ip40->checksum;
470 300 : csum = ip_csum_update (csum, old_tos, new_tos,
471 : ip4_header_t,
472 : tos /* changed member */);
473 300 : csum = ip_csum_update (csum, old_dst, new_dst,
474 : ip4_header_t,
475 : dst_address /* changed member */);
476 300 : ip40->checksum = ip_csum_fold (csum);
477 :
478 : /* Recomputing L4 checksum after dst-IP modifying */
479 300 : if (ip40->protocol == IP_PROTOCOL_TCP)
480 : {
481 : tcp_header_t *th0;
482 0 : th0 = ip4_next_header (ip40);
483 0 : th0->checksum = 0;
484 0 : th0->checksum = ip4_tcp_udp_compute_checksum (vm, p0, ip40);
485 : }
486 300 : else if (ip40->protocol == IP_PROTOCOL_UDP)
487 : {
488 : udp_header_t *uh0;
489 300 : uh0 = ip4_next_header (ip40);
490 300 : uh0->checksum = 0;
491 300 : uh0->checksum = ip4_tcp_udp_compute_checksum (vm, p0, ip40);
492 : }
493 : }
494 200 : else if ((encap_type == LB_ENCAP_TYPE_NAT4)
495 100 : || (encap_type == LB_ENCAP_TYPE_NAT6))
496 : {
497 : ip_csum_t csum;
498 : udp_header_t *uh;
499 :
500 : /* do NAT */
501 200 : if ((is_input_v4 == 1) && (encap_type == LB_ENCAP_TYPE_NAT4))
502 100 : {
503 : /* NAT44 */
504 : ip4_header_t *ip40;
505 : u32 old_dst;
506 100 : ip40 = vlib_buffer_get_current (p0);
507 100 : uh = (udp_header_t *) (ip40 + 1);
508 100 : old_dst = ip40->dst_address.as_u32;
509 100 : ip40->dst_address = lbm->ass[asindex0].address.ip4;
510 :
511 100 : csum = ip40->checksum;
512 100 : csum = ip_csum_sub_even (csum, old_dst);
513 100 : csum = ip_csum_add_even (
514 100 : csum, lbm->ass[asindex0].address.ip4.as_u32);
515 100 : ip40->checksum = ip_csum_fold (csum);
516 :
517 100 : if (ip40->protocol == IP_PROTOCOL_UDP)
518 : {
519 100 : uh->dst_port = vip0->encap_args.target_port;
520 100 : csum = uh->checksum;
521 100 : csum = ip_csum_sub_even (csum, old_dst);
522 100 : csum = ip_csum_add_even (
523 100 : csum, lbm->ass[asindex0].address.ip4.as_u32);
524 100 : uh->checksum = ip_csum_fold (csum);
525 : }
526 : else
527 : {
528 0 : asindex0 = 0;
529 : }
530 : }
531 100 : else if ((is_input_v4 == 0) && (encap_type == LB_ENCAP_TYPE_NAT6))
532 : {
533 : /* NAT66 */
534 : ip6_header_t *ip60;
535 : ip6_address_t old_dst;
536 :
537 100 : ip60 = vlib_buffer_get_current (p0);
538 100 : uh = (udp_header_t *) (ip60 + 1);
539 :
540 100 : old_dst.as_u64[0] = ip60->dst_address.as_u64[0];
541 100 : old_dst.as_u64[1] = ip60->dst_address.as_u64[1];
542 100 : ip60->dst_address.as_u64[0] =
543 100 : lbm->ass[asindex0].address.ip6.as_u64[0];
544 100 : ip60->dst_address.as_u64[1] =
545 100 : lbm->ass[asindex0].address.ip6.as_u64[1];
546 :
547 100 : if (PREDICT_TRUE(ip60->protocol == IP_PROTOCOL_UDP))
548 : {
549 100 : uh->dst_port = vip0->encap_args.target_port;
550 100 : csum = uh->checksum;
551 100 : csum = ip_csum_sub_even (csum, old_dst.as_u64[0]);
552 100 : csum = ip_csum_sub_even (csum, old_dst.as_u64[1]);
553 100 : csum = ip_csum_add_even (
554 100 : csum, lbm->ass[asindex0].address.ip6.as_u64[0]);
555 100 : csum = ip_csum_add_even (
556 100 : csum, lbm->ass[asindex0].address.ip6.as_u64[1]);
557 100 : uh->checksum = ip_csum_fold (csum);
558 : }
559 : else
560 : {
561 0 : asindex0 = 0;
562 : }
563 : }
564 : }
565 1300 : next0 = lbm->ass[asindex0].dpo.dpoi_next_node;
566 : //Note that this is going to error if asindex0 == 0
567 1300 : vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
568 1300 : lbm->ass[asindex0].dpo.dpoi_index;
569 :
570 1300 : if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
571 : {
572 1300 : lb_trace_t *tr = vlib_add_trace (vm, node, p0, sizeof(*tr));
573 1300 : tr->as_index = asindex0;
574 1300 : tr->vip_index = vip_index0;
575 : }
576 :
577 : //Enqueue to next
578 1300 : vlib_validate_buffer_enqueue_x1(
579 : vm, node, next_index, to_next, n_left_to_next, pi0, next0);
580 : }
581 13 : vlib_put_next_frame (vm, node, next_index, n_left_to_next);
582 : }
583 :
584 13 : return frame->n_vectors;
585 : }
586 : /* clang-format on */
587 :
588 : u8 *
589 0 : format_nodeport_lb_trace (u8 * s, va_list * args)
590 : {
591 0 : lb_main_t *lbm = &lb_main;
592 0 : CLIB_UNUSED(vlib_main_t * vm)
593 : = va_arg (*args, vlib_main_t *);
594 0 : CLIB_UNUSED(vlib_node_t * node)
595 : = va_arg (*args, vlib_node_t *);
596 0 : lb_nodeport_trace_t *t = va_arg (*args, lb_nodeport_trace_t *);
597 0 : if (pool_is_free_index(lbm->vips, t->vip_index))
598 : {
599 0 : s = format (s, "lb vip[%d]: This VIP was freed since capture\n");
600 : }
601 : else
602 : {
603 0 : s = format (s, "lb vip[%d]: %U\n", t->vip_index, format_lb_vip,
604 0 : &lbm->vips[t->vip_index]);
605 : }
606 :
607 0 : s = format (s, " lb node_port: %d", t->node_port);
608 :
609 0 : return s;
610 : }
611 :
612 : static uword
613 0 : lb_nodeport_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
614 : vlib_frame_t * frame, u8 is_input_v4)
615 : {
616 0 : lb_main_t *lbm = &lb_main;
617 : u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
618 :
619 0 : from = vlib_frame_vector_args (frame);
620 0 : n_left_from = frame->n_vectors;
621 0 : next_index = node->cached_next_index;
622 :
623 0 : while (n_left_from > 0)
624 : {
625 0 : vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
626 :
627 0 : while (n_left_from > 0 && n_left_to_next > 0)
628 : {
629 : u32 pi0;
630 : vlib_buffer_t *p0;
631 : udp_header_t * udp_0;
632 : uword * entry0;
633 :
634 0 : if (PREDICT_TRUE(n_left_from > 1))
635 : {
636 0 : vlib_buffer_t *p1 = vlib_get_buffer (vm, from[1]);
637 : //Prefetch for encap, next
638 0 : CLIB_PREFETCH(vlib_buffer_get_current (p1) - 64, 64, STORE);
639 : }
640 :
641 0 : if (PREDICT_TRUE(n_left_from > 2))
642 : {
643 : vlib_buffer_t *p2;
644 0 : p2 = vlib_get_buffer (vm, from[2]);
645 : /* prefetch packet header and data */
646 0 : vlib_prefetch_buffer_header(p2, STORE);
647 0 : CLIB_PREFETCH(vlib_buffer_get_current (p2), 64, STORE);
648 : }
649 :
650 0 : pi0 = to_next[0] = from[0];
651 0 : from += 1;
652 0 : n_left_from -= 1;
653 0 : to_next += 1;
654 0 : n_left_to_next -= 1;
655 :
656 0 : p0 = vlib_get_buffer (vm, pi0);
657 :
658 0 : if (is_input_v4)
659 : {
660 : ip4_header_t *ip40;
661 0 : vlib_buffer_advance (
662 : p0, -(word) (sizeof(udp_header_t) + sizeof(ip4_header_t)));
663 0 : ip40 = vlib_buffer_get_current (p0);
664 0 : udp_0 = (udp_header_t *) (ip40 + 1);
665 : }
666 : else
667 : {
668 : ip6_header_t *ip60;
669 0 : vlib_buffer_advance (
670 : p0, -(word) (sizeof(udp_header_t) + sizeof(ip6_header_t)));
671 0 : ip60 = vlib_buffer_get_current (p0);
672 0 : udp_0 = (udp_header_t *) (ip60 + 1);
673 : }
674 :
675 0 : entry0 = hash_get_mem(lbm->vip_index_by_nodeport, &(udp_0->dst_port));
676 :
677 : //Enqueue to next
678 0 : vnet_buffer(p0)->ip.adj_index[VLIB_TX] = entry0 ? entry0[0]
679 : : ADJ_INDEX_INVALID;
680 :
681 0 : if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
682 : {
683 0 : lb_nodeport_trace_t *tr = vlib_add_trace (vm, node, p0,
684 : sizeof(*tr));
685 0 : tr->vip_index = entry0 ? entry0[0] : ADJ_INDEX_INVALID;
686 0 : tr->node_port = (u32) clib_net_to_host_u16 (udp_0->dst_port);
687 : }
688 :
689 0 : vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
690 : n_left_to_next, pi0,
691 : is_input_v4 ?
692 : LB4_NODEPORT_NEXT_IP4_NAT4 : LB6_NODEPORT_NEXT_IP6_NAT6);
693 : }
694 0 : vlib_put_next_frame (vm, node, next_index, n_left_to_next);
695 : }
696 :
697 0 : return frame->n_vectors;
698 :
699 : }
700 :
701 : /**
702 : * @brief Match NAT44 static mapping.
703 : *
704 : * @param sm NAT main.
705 : * @param match Address and port to match.
706 : * @param index index to the pool.
707 : *
708 : * @returns 0 if match found, otherwise -1.
709 : */
710 : int
711 0 : lb_nat44_mapping_match (lb_main_t *lbm, lb_snat4_key_t * match, u32 *index)
712 : {
713 : clib_bihash_kv_8_8_t kv4, value;
714 0 : clib_bihash_8_8_t *mapping_hash = &lbm->mapping_by_as4;
715 :
716 0 : kv4.key = match->as_u64;
717 0 : kv4.value = 0;
718 0 : if (clib_bihash_search_8_8 (mapping_hash, &kv4, &value))
719 : {
720 0 : return 1;
721 : }
722 :
723 0 : *index = value.value;
724 0 : return 0;
725 : }
726 :
727 : /**
728 : * @brief Match NAT66 static mapping.
729 : *
730 : * @param sm NAT main.
731 : * @param match Address and port to match.
732 : * @param mapping External or local address and port of the matched mapping.
733 : *
734 : * @returns 0 if match found otherwise 1.
735 : */
736 : int
737 0 : lb_nat66_mapping_match (lb_main_t *lbm, lb_snat6_key_t * match, u32 *index)
738 : {
739 : clib_bihash_kv_24_8_t kv6, value;
740 : lb_snat6_key_t m_key6;
741 0 : clib_bihash_24_8_t *mapping_hash = &lbm->mapping_by_as6;
742 :
743 0 : m_key6.addr.as_u64[0] = match->addr.as_u64[0];
744 0 : m_key6.addr.as_u64[1] = match->addr.as_u64[1];
745 0 : m_key6.port = match->port;
746 0 : m_key6.protocol = 0;
747 0 : m_key6.fib_index = 0;
748 :
749 0 : kv6.key[0] = m_key6.as_u64[0];
750 0 : kv6.key[1] = m_key6.as_u64[1];
751 0 : kv6.key[2] = m_key6.as_u64[2];
752 0 : kv6.value = 0;
753 0 : if (clib_bihash_search_24_8 (mapping_hash, &kv6, &value))
754 : {
755 0 : return 1;
756 : }
757 :
758 0 : *index = value.value;
759 0 : return 0;
760 : }
761 :
762 : static uword
763 0 : lb_nat_in2out_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
764 : vlib_frame_t * frame, u32 is_nat4)
765 : {
766 : u32 n_left_from, *from, *to_next;
767 : u32 next_index;
768 0 : u32 pkts_processed = 0;
769 0 : lb_main_t *lbm = &lb_main;
770 : u32 stats_node_index;
771 :
772 0 : stats_node_index =
773 0 : is_nat4 ? lb_nat4_in2out_node.index : lb_nat6_in2out_node.index;
774 :
775 0 : from = vlib_frame_vector_args (frame);
776 0 : n_left_from = frame->n_vectors;
777 0 : next_index = node->cached_next_index;
778 :
779 0 : while (n_left_from > 0)
780 : {
781 : u32 n_left_to_next;
782 :
783 0 : vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
784 :
785 0 : while (n_left_from > 0 && n_left_to_next > 0)
786 : {
787 : u32 bi0;
788 : vlib_buffer_t * b0;
789 : u32 next0;
790 : u32 sw_if_index0;
791 : ip_csum_t csum;
792 : u16 old_port0, new_port0;
793 : udp_header_t * udp0;
794 : tcp_header_t * tcp0;
795 :
796 : u32 proto0;
797 : u32 rx_fib_index0;
798 :
799 : /* speculatively enqueue b0 to the current next frame */
800 0 : bi0 = from[0];
801 0 : to_next[0] = bi0;
802 0 : from += 1;
803 0 : to_next += 1;
804 0 : n_left_from -= 1;
805 0 : n_left_to_next -= 1;
806 :
807 0 : b0 = vlib_get_buffer (vm, bi0);
808 0 : next0 = LB_NAT4_IN2OUT_NEXT_LOOKUP;
809 0 : sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
810 0 : rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (
811 : sw_if_index0);
812 :
813 0 : if (is_nat4)
814 : {
815 : ip4_header_t * ip40;
816 : u32 old_addr0, new_addr0;
817 : lb_snat4_key_t key40;
818 : lb_snat_mapping_t *sm40;
819 : u32 index40;
820 :
821 0 : ip40 = vlib_buffer_get_current (b0);
822 0 : udp0 = ip4_next_header (ip40);
823 0 : tcp0 = (tcp_header_t *) udp0;
824 0 : proto0 = lb_ip_proto_to_nat_proto (ip40->protocol);
825 :
826 0 : key40.addr = ip40->src_address;
827 0 : key40.protocol = proto0;
828 0 : key40.port = udp0->src_port;
829 0 : key40.fib_index = rx_fib_index0;
830 :
831 0 : if (lb_nat44_mapping_match (lbm, &key40, &index40))
832 : {
833 0 : next0 = LB_NAT4_IN2OUT_NEXT_DROP;
834 0 : goto trace0;
835 : }
836 :
837 0 : sm40 = pool_elt_at_index(lbm->snat_mappings, index40);
838 0 : new_addr0 = sm40->src_ip.ip4.as_u32;
839 0 : new_port0 = sm40->src_port;
840 0 : vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm40->fib_index;
841 0 : old_addr0 = ip40->src_address.as_u32;
842 0 : ip40->src_address.as_u32 = new_addr0;
843 :
844 0 : csum = ip40->checksum;
845 0 : csum = ip_csum_sub_even (csum, old_addr0);
846 0 : csum = ip_csum_add_even (csum, new_addr0);
847 0 : ip40->checksum = ip_csum_fold (csum);
848 :
849 0 : if (PREDICT_TRUE(proto0 == LB_NAT_PROTOCOL_TCP))
850 : {
851 0 : old_port0 = tcp0->src_port;
852 0 : tcp0->src_port = new_port0;
853 :
854 0 : csum = tcp0->checksum;
855 0 : csum = ip_csum_sub_even (csum, old_addr0);
856 0 : csum = ip_csum_sub_even (csum, old_port0);
857 0 : csum = ip_csum_add_even (csum, new_addr0);
858 0 : csum = ip_csum_add_even (csum, new_port0);
859 0 : tcp0->checksum = ip_csum_fold (csum);
860 : }
861 0 : else if (PREDICT_TRUE(proto0 == LB_NAT_PROTOCOL_UDP))
862 : {
863 0 : old_port0 = udp0->src_port;
864 0 : udp0->src_port = new_port0;
865 :
866 0 : csum = udp0->checksum;
867 0 : csum = ip_csum_sub_even (csum, old_addr0);
868 0 : csum = ip_csum_sub_even (csum, old_port0);
869 0 : csum = ip_csum_add_even (csum, new_addr0);
870 0 : csum = ip_csum_add_even (csum, new_port0);
871 0 : udp0->checksum = ip_csum_fold (csum);
872 : }
873 :
874 0 : pkts_processed += next0 != LB_NAT4_IN2OUT_NEXT_DROP;
875 : }
876 : else
877 : {
878 : ip6_header_t * ip60;
879 : ip6_address_t old_addr0, new_addr0;
880 : lb_snat6_key_t key60;
881 : lb_snat_mapping_t *sm60;
882 : u32 index60;
883 :
884 0 : ip60 = vlib_buffer_get_current (b0);
885 0 : udp0 = ip6_next_header (ip60);
886 0 : tcp0 = (tcp_header_t *) udp0;
887 0 : proto0 = lb_ip_proto_to_nat_proto (ip60->protocol);
888 :
889 0 : key60.addr.as_u64[0] = ip60->src_address.as_u64[0];
890 0 : key60.addr.as_u64[1] = ip60->src_address.as_u64[1];
891 0 : key60.protocol = proto0;
892 0 : key60.port = udp0->src_port;
893 0 : key60.fib_index = rx_fib_index0;
894 :
895 0 : if (lb_nat66_mapping_match (lbm, &key60, &index60))
896 : {
897 0 : next0 = LB_NAT6_IN2OUT_NEXT_DROP;
898 0 : goto trace0;
899 : }
900 :
901 0 : sm60 = pool_elt_at_index(lbm->snat_mappings, index60);
902 0 : new_addr0.as_u64[0] = sm60->src_ip.as_u64[0];
903 0 : new_addr0.as_u64[1] = sm60->src_ip.as_u64[1];
904 0 : new_port0 = sm60->src_port;
905 0 : vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm60->fib_index;
906 0 : old_addr0.as_u64[0] = ip60->src_address.as_u64[0];
907 0 : old_addr0.as_u64[1] = ip60->src_address.as_u64[1];
908 0 : ip60->src_address.as_u64[0] = new_addr0.as_u64[0];
909 0 : ip60->src_address.as_u64[1] = new_addr0.as_u64[1];
910 :
911 0 : if (PREDICT_TRUE(proto0 == LB_NAT_PROTOCOL_TCP))
912 : {
913 0 : old_port0 = tcp0->src_port;
914 0 : tcp0->src_port = new_port0;
915 :
916 0 : csum = tcp0->checksum;
917 0 : csum = ip_csum_sub_even (csum, old_addr0.as_u64[0]);
918 0 : csum = ip_csum_sub_even (csum, old_addr0.as_u64[1]);
919 0 : csum = ip_csum_add_even (csum, new_addr0.as_u64[0]);
920 0 : csum = ip_csum_add_even (csum, new_addr0.as_u64[1]);
921 0 : csum = ip_csum_sub_even (csum, old_port0);
922 0 : csum = ip_csum_add_even (csum, new_port0);
923 0 : tcp0->checksum = ip_csum_fold (csum);
924 : }
925 0 : else if (PREDICT_TRUE(proto0 == LB_NAT_PROTOCOL_UDP))
926 : {
927 0 : old_port0 = udp0->src_port;
928 0 : udp0->src_port = new_port0;
929 :
930 0 : csum = udp0->checksum;
931 0 : csum = ip_csum_sub_even (csum, old_addr0.as_u64[0]);
932 0 : csum = ip_csum_sub_even (csum, old_addr0.as_u64[1]);
933 0 : csum = ip_csum_add_even (csum, new_addr0.as_u64[0]);
934 0 : csum = ip_csum_add_even (csum, new_addr0.as_u64[1]);
935 0 : csum = ip_csum_sub_even (csum, old_port0);
936 0 : csum = ip_csum_add_even (csum, new_port0);
937 0 : udp0->checksum = ip_csum_fold (csum);
938 : }
939 :
940 0 : pkts_processed += next0 != LB_NAT4_IN2OUT_NEXT_DROP;
941 : }
942 :
943 0 : trace0: if (PREDICT_FALSE(
944 : (node->flags & VLIB_NODE_FLAG_TRACE) && (b0->flags & VLIB_BUFFER_IS_TRACED)))
945 : {
946 0 : lb_nat_trace_t *t = vlib_add_trace (vm, node, b0, sizeof(*t));
947 0 : t->rx_sw_if_index = sw_if_index0;
948 0 : t->next_index = next0;
949 : }
950 :
951 : /* verify speculative enqueue, maybe switch current next frame */
952 0 : vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
953 : n_left_to_next, bi0, next0);
954 : }
955 :
956 0 : vlib_put_next_frame (vm, node, next_index, n_left_to_next);
957 : }
958 :
959 0 : vlib_node_increment_counter (vm, stats_node_index,
960 : LB_NAT_IN2OUT_ERROR_IN2OUT_PACKETS,
961 : pkts_processed);
962 0 : return frame->n_vectors;
963 : }
964 :
965 : static uword
966 1 : lb6_gre6_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
967 : vlib_frame_t * frame)
968 : {
969 1 : return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 0, 0);
970 : }
971 :
972 : static uword
973 1 : lb6_gre4_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
974 : vlib_frame_t * frame)
975 : {
976 1 : return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 0, 0);
977 : }
978 :
979 : static uword
980 1 : lb4_gre6_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
981 : vlib_frame_t * frame)
982 : {
983 1 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 0, 0);
984 : }
985 :
986 : static uword
987 1 : lb4_gre4_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
988 : vlib_frame_t * frame)
989 : {
990 1 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 0, 0);
991 : }
992 :
993 : static uword
994 1 : lb6_gre6_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
995 : vlib_frame_t * frame)
996 : {
997 1 : return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 1, 0);
998 : }
999 :
1000 : static uword
1001 1 : lb6_gre4_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1002 : vlib_frame_t * frame)
1003 : {
1004 1 : return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 1, 0);
1005 : }
1006 :
1007 : static uword
1008 1 : lb4_gre6_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1009 : vlib_frame_t * frame)
1010 : {
1011 1 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 1, 0);
1012 : }
1013 :
1014 : static uword
1015 1 : lb4_gre4_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1016 : vlib_frame_t * frame)
1017 : {
1018 1 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 1, 0);
1019 : }
1020 :
1021 : static uword
1022 1 : lb4_l3dsr_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1023 : vlib_frame_t * frame)
1024 : {
1025 1 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 0, 0);
1026 : }
1027 :
1028 : static uword
1029 1 : lb4_l3dsr_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1030 : vlib_frame_t * frame)
1031 : {
1032 1 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 1, 0);
1033 : }
1034 :
1035 : static uword
1036 1 : lb6_nat6_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1037 : vlib_frame_t * frame)
1038 : {
1039 1 : return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_NAT6, 1, 0);
1040 : }
1041 :
1042 : static uword
1043 1 : lb4_nat4_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1044 : vlib_frame_t * frame)
1045 : {
1046 1 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_NAT4, 1, 0);
1047 : }
1048 :
1049 : static uword
1050 0 : lb6_gre6_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1051 : vlib_frame_t *frame)
1052 : {
1053 0 : return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 0, 1);
1054 : }
1055 :
1056 : static uword
1057 0 : lb6_gre4_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1058 : vlib_frame_t *frame)
1059 : {
1060 0 : return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 0, 1);
1061 : }
1062 :
1063 : static uword
1064 0 : lb4_gre6_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1065 : vlib_frame_t *frame)
1066 : {
1067 0 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 0, 1);
1068 : }
1069 :
1070 : static uword
1071 0 : lb4_gre4_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1072 : vlib_frame_t *frame)
1073 : {
1074 0 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 0, 1);
1075 : }
1076 :
1077 : static uword
1078 0 : lb6_gre6_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1079 : vlib_frame_t *frame)
1080 : {
1081 0 : return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 1, 1);
1082 : }
1083 :
1084 : static uword
1085 0 : lb6_gre4_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1086 : vlib_frame_t *frame)
1087 : {
1088 0 : return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 1, 1);
1089 : }
1090 :
1091 : static uword
1092 0 : lb4_gre6_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1093 : vlib_frame_t *frame)
1094 : {
1095 0 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 1, 1);
1096 : }
1097 :
1098 : static uword
1099 0 : lb4_gre4_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1100 : vlib_frame_t *frame)
1101 : {
1102 0 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 1, 1);
1103 : }
1104 :
1105 : static uword
1106 0 : lb4_l3dsr_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1107 : vlib_frame_t *frame)
1108 : {
1109 0 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 0, 1);
1110 : }
1111 :
1112 : static uword
1113 1 : lb4_l3dsr_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1114 : vlib_frame_t *frame)
1115 : {
1116 1 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 1, 1);
1117 : }
1118 :
1119 : static uword
1120 0 : lb6_nat6_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1121 : vlib_frame_t *frame)
1122 : {
1123 0 : return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_NAT6, 1, 1);
1124 : }
1125 :
1126 : static uword
1127 0 : lb4_nat4_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
1128 : vlib_frame_t *frame)
1129 : {
1130 0 : return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_NAT4, 1, 1);
1131 : }
1132 :
1133 : static uword
1134 0 : lb_nat4_in2out_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1135 : vlib_frame_t * frame)
1136 : {
1137 0 : return lb_nat_in2out_node_fn (vm, node, frame, 1);
1138 : }
1139 :
1140 : static uword
1141 0 : lb_nat6_in2out_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1142 : vlib_frame_t * frame)
1143 : {
1144 0 : return lb_nat_in2out_node_fn (vm, node, frame, 0);
1145 : }
1146 :
1147 91880 : VLIB_REGISTER_NODE (lb6_gre6_node) =
1148 : {
1149 : .function = lb6_gre6_node_fn,
1150 : .name = "lb6-gre6",
1151 : .vector_size = sizeof(u32),
1152 : .format_trace = format_lb_trace,
1153 : .n_errors = LB_N_ERROR,
1154 : .error_strings = lb_error_strings,
1155 : .n_next_nodes = LB_N_NEXT,
1156 : .next_nodes =
1157 : { [LB_NEXT_DROP] = "error-drop" },
1158 : };
1159 :
1160 91880 : VLIB_REGISTER_NODE (lb6_gre4_node) =
1161 : {
1162 : .function = lb6_gre4_node_fn,
1163 : .name = "lb6-gre4",
1164 : .vector_size = sizeof(u32),
1165 : .format_trace = format_lb_trace,
1166 : .n_errors = LB_N_ERROR,
1167 : .error_strings = lb_error_strings,
1168 : .n_next_nodes = LB_N_NEXT,
1169 : .next_nodes =
1170 : { [LB_NEXT_DROP] = "error-drop" },
1171 : };
1172 :
1173 91880 : VLIB_REGISTER_NODE (lb4_gre6_node) =
1174 : {
1175 : .function = lb4_gre6_node_fn,
1176 : .name = "lb4-gre6",
1177 : .vector_size = sizeof(u32),
1178 : .format_trace = format_lb_trace,
1179 : .n_errors = LB_N_ERROR,
1180 : .error_strings = lb_error_strings,
1181 : .n_next_nodes = LB_N_NEXT,
1182 : .next_nodes =
1183 : { [LB_NEXT_DROP] = "error-drop" },
1184 : };
1185 :
1186 91880 : VLIB_REGISTER_NODE (lb4_gre4_node) =
1187 : {
1188 : .function = lb4_gre4_node_fn,
1189 : .name = "lb4-gre4",
1190 : .vector_size = sizeof(u32),
1191 : .format_trace = format_lb_trace,
1192 : .n_errors = LB_N_ERROR,
1193 : .error_strings = lb_error_strings,
1194 : .n_next_nodes = LB_N_NEXT,
1195 : .next_nodes =
1196 : { [LB_NEXT_DROP] = "error-drop" },
1197 : };
1198 :
1199 91880 : VLIB_REGISTER_NODE (lb6_gre6_port_node) =
1200 : {
1201 : .function = lb6_gre6_port_node_fn,
1202 : .name = "lb6-gre6-port",
1203 : .vector_size = sizeof(u32),
1204 : .format_trace = format_lb_trace,
1205 : .n_errors = LB_N_ERROR,
1206 : .error_strings = lb_error_strings,
1207 : .n_next_nodes = LB_N_NEXT,
1208 : .next_nodes =
1209 : { [LB_NEXT_DROP] = "error-drop" },
1210 : };
1211 :
1212 91880 : VLIB_REGISTER_NODE (lb6_gre4_port_node) =
1213 : {
1214 : .function = lb6_gre4_port_node_fn,
1215 : .name = "lb6-gre4-port",
1216 : .vector_size = sizeof(u32),
1217 : .format_trace = format_lb_trace,
1218 : .n_errors = LB_N_ERROR,
1219 : .error_strings = lb_error_strings,
1220 : .n_next_nodes = LB_N_NEXT,
1221 : .next_nodes =
1222 : { [LB_NEXT_DROP] = "error-drop" },
1223 : };
1224 :
1225 91880 : VLIB_REGISTER_NODE (lb4_gre6_port_node) =
1226 : {
1227 : .function = lb4_gre6_port_node_fn,
1228 : .name = "lb4-gre6-port",
1229 : .vector_size = sizeof(u32),
1230 : .format_trace = format_lb_trace,
1231 : .n_errors = LB_N_ERROR,
1232 : .error_strings = lb_error_strings,
1233 : .n_next_nodes = LB_N_NEXT,
1234 : .next_nodes =
1235 : { [LB_NEXT_DROP] = "error-drop" },
1236 : };
1237 :
1238 91880 : VLIB_REGISTER_NODE (lb4_gre4_port_node) =
1239 : {
1240 : .function = lb4_gre4_port_node_fn,
1241 : .name = "lb4-gre4-port",
1242 : .vector_size = sizeof(u32),
1243 : .format_trace = format_lb_trace,
1244 : .n_errors = LB_N_ERROR,
1245 : .error_strings = lb_error_strings,
1246 : .n_next_nodes = LB_N_NEXT,
1247 : .next_nodes =
1248 : { [LB_NEXT_DROP] = "error-drop" },
1249 : };
1250 :
1251 91880 : VLIB_REGISTER_NODE (lb4_l3dsr_port_node) =
1252 : {
1253 : .function = lb4_l3dsr_port_node_fn,
1254 : .name = "lb4-l3dsr-port",
1255 : .vector_size = sizeof(u32),
1256 : .format_trace = format_lb_trace,
1257 : .n_errors = LB_N_ERROR,
1258 : .error_strings = lb_error_strings,
1259 : .n_next_nodes = LB_N_NEXT,
1260 : .next_nodes =
1261 : { [LB_NEXT_DROP] = "error-drop" },
1262 : };
1263 :
1264 91880 : VLIB_REGISTER_NODE (lb4_l3dsr_node) =
1265 : {
1266 : .function = lb4_l3dsr_node_fn,
1267 : .name = "lb4-l3dsr",
1268 : .vector_size = sizeof(u32),
1269 : .format_trace = format_lb_trace,
1270 : .n_errors = LB_N_ERROR,
1271 : .error_strings = lb_error_strings,
1272 : .n_next_nodes = LB_N_NEXT,
1273 : .next_nodes =
1274 : { [LB_NEXT_DROP] = "error-drop" },
1275 : };
1276 :
1277 91880 : VLIB_REGISTER_NODE (lb6_nat6_port_node) =
1278 : {
1279 : .function = lb6_nat6_port_node_fn,
1280 : .name = "lb6-nat6-port",
1281 : .vector_size = sizeof(u32),
1282 : .format_trace = format_lb_trace,
1283 : .n_errors = LB_N_ERROR,
1284 : .error_strings = lb_error_strings,
1285 : .n_next_nodes = LB_N_NEXT,
1286 : .next_nodes =
1287 : { [LB_NEXT_DROP] = "error-drop" },
1288 : };
1289 :
1290 91880 : VLIB_REGISTER_NODE (lb4_nat4_port_node) =
1291 : {
1292 : .function = lb4_nat4_port_node_fn,
1293 : .name = "lb4-nat4-port",
1294 : .vector_size = sizeof(u32),
1295 : .format_trace = format_lb_trace,
1296 : .n_errors = LB_N_ERROR,
1297 : .error_strings = lb_error_strings,
1298 : .n_next_nodes = LB_N_NEXT,
1299 : .next_nodes =
1300 : { [LB_NEXT_DROP] = "error-drop" },
1301 : };
1302 :
1303 91880 : VLIB_REGISTER_NODE (lb6_gre6_sticky_node) = {
1304 : .function = lb6_gre6_sticky_node_fn,
1305 : .name = "lb6-gre6-sticky",
1306 : .vector_size = sizeof (u32),
1307 : .format_trace = format_lb_trace,
1308 : .n_errors = LB_N_ERROR,
1309 : .error_strings = lb_error_strings,
1310 : .n_next_nodes = LB_N_NEXT,
1311 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1312 : };
1313 :
1314 91880 : VLIB_REGISTER_NODE (lb6_gre4_sticky_node) = {
1315 : .function = lb6_gre4_sticky_node_fn,
1316 : .name = "lb6-gre4-sticky",
1317 : .vector_size = sizeof (u32),
1318 : .format_trace = format_lb_trace,
1319 : .n_errors = LB_N_ERROR,
1320 : .error_strings = lb_error_strings,
1321 : .n_next_nodes = LB_N_NEXT,
1322 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1323 : };
1324 :
1325 91880 : VLIB_REGISTER_NODE (lb4_gre6_sticky_node) = {
1326 : .function = lb4_gre6_sticky_node_fn,
1327 : .name = "lb4-gre6-sticky",
1328 : .vector_size = sizeof (u32),
1329 : .format_trace = format_lb_trace,
1330 : .n_errors = LB_N_ERROR,
1331 : .error_strings = lb_error_strings,
1332 : .n_next_nodes = LB_N_NEXT,
1333 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1334 : };
1335 :
1336 91880 : VLIB_REGISTER_NODE (lb4_gre4_sticky_node) = {
1337 : .function = lb4_gre4_sticky_node_fn,
1338 : .name = "lb4-gre4-sticky",
1339 : .vector_size = sizeof (u32),
1340 : .format_trace = format_lb_trace,
1341 : .n_errors = LB_N_ERROR,
1342 : .error_strings = lb_error_strings,
1343 : .n_next_nodes = LB_N_NEXT,
1344 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1345 : };
1346 :
1347 91880 : VLIB_REGISTER_NODE (lb6_gre6_port_sticky_node) = {
1348 : .function = lb6_gre6_port_sticky_node_fn,
1349 : .name = "lb6-gre6-port-sticky",
1350 : .vector_size = sizeof (u32),
1351 : .format_trace = format_lb_trace,
1352 : .n_errors = LB_N_ERROR,
1353 : .error_strings = lb_error_strings,
1354 : .n_next_nodes = LB_N_NEXT,
1355 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1356 : };
1357 :
1358 91880 : VLIB_REGISTER_NODE (lb6_gre4_port_sticky_node) = {
1359 : .function = lb6_gre4_port_sticky_node_fn,
1360 : .name = "lb6-gre4-port-sticky",
1361 : .vector_size = sizeof (u32),
1362 : .format_trace = format_lb_trace,
1363 : .n_errors = LB_N_ERROR,
1364 : .error_strings = lb_error_strings,
1365 : .n_next_nodes = LB_N_NEXT,
1366 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1367 : };
1368 :
1369 91880 : VLIB_REGISTER_NODE (lb4_gre6_port_sticky_node) = {
1370 : .function = lb4_gre6_port_sticky_node_fn,
1371 : .name = "lb4-gre6-port-sticky",
1372 : .vector_size = sizeof (u32),
1373 : .format_trace = format_lb_trace,
1374 : .n_errors = LB_N_ERROR,
1375 : .error_strings = lb_error_strings,
1376 : .n_next_nodes = LB_N_NEXT,
1377 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1378 : };
1379 :
1380 91880 : VLIB_REGISTER_NODE (lb4_gre4_port_sticky_node) = {
1381 : .function = lb4_gre4_port_sticky_node_fn,
1382 : .name = "lb4-gre4-port-sticky",
1383 : .vector_size = sizeof (u32),
1384 : .format_trace = format_lb_trace,
1385 : .n_errors = LB_N_ERROR,
1386 : .error_strings = lb_error_strings,
1387 : .n_next_nodes = LB_N_NEXT,
1388 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1389 : };
1390 :
1391 91880 : VLIB_REGISTER_NODE (lb4_l3dsr_port_sticky_node) = {
1392 : .function = lb4_l3dsr_port_sticky_node_fn,
1393 : .name = "lb4-l3dsr-port-sticky",
1394 : .vector_size = sizeof (u32),
1395 : .format_trace = format_lb_trace,
1396 : .n_errors = LB_N_ERROR,
1397 : .error_strings = lb_error_strings,
1398 : .n_next_nodes = LB_N_NEXT,
1399 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1400 : };
1401 :
1402 91880 : VLIB_REGISTER_NODE (lb4_l3dsr_sticky_node) = {
1403 : .function = lb4_l3dsr_sticky_node_fn,
1404 : .name = "lb4-l3dsr-sticky",
1405 : .vector_size = sizeof (u32),
1406 : .format_trace = format_lb_trace,
1407 : .n_errors = LB_N_ERROR,
1408 : .error_strings = lb_error_strings,
1409 : .n_next_nodes = LB_N_NEXT,
1410 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1411 : };
1412 :
1413 91880 : VLIB_REGISTER_NODE (lb6_nat6_port_sticky_node) = {
1414 : .function = lb6_nat6_port_sticky_node_fn,
1415 : .name = "lb6-nat6-port-sticky",
1416 : .vector_size = sizeof (u32),
1417 : .format_trace = format_lb_trace,
1418 : .n_errors = LB_N_ERROR,
1419 : .error_strings = lb_error_strings,
1420 : .n_next_nodes = LB_N_NEXT,
1421 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1422 : };
1423 :
1424 91880 : VLIB_REGISTER_NODE (lb4_nat4_port_sticky_node) = {
1425 : .function = lb4_nat4_port_sticky_node_fn,
1426 : .name = "lb4-nat4-port-sticky",
1427 : .vector_size = sizeof (u32),
1428 : .format_trace = format_lb_trace,
1429 : .n_errors = LB_N_ERROR,
1430 : .error_strings = lb_error_strings,
1431 : .n_next_nodes = LB_N_NEXT,
1432 : .next_nodes = { [LB_NEXT_DROP] = "error-drop" },
1433 : };
1434 :
1435 : static uword
1436 0 : lb4_nodeport_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1437 : vlib_frame_t * frame)
1438 : {
1439 0 : return lb_nodeport_node_fn (vm, node, frame, 1);
1440 : }
1441 :
1442 : static uword
1443 0 : lb6_nodeport_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1444 : vlib_frame_t * frame)
1445 : {
1446 0 : return lb_nodeport_node_fn (vm, node, frame, 0);
1447 : }
1448 :
1449 91880 : VLIB_REGISTER_NODE (lb4_nodeport_node) =
1450 : {
1451 : .function = lb4_nodeport_node_fn,
1452 : .name = "lb4-nodeport",
1453 : .vector_size = sizeof(u32),
1454 : .format_trace = format_nodeport_lb_trace,
1455 : .n_errors = LB_N_ERROR,
1456 : .error_strings = lb_error_strings,
1457 : .n_next_nodes = LB4_NODEPORT_N_NEXT,
1458 : .next_nodes =
1459 : {
1460 : [LB4_NODEPORT_NEXT_IP4_NAT4] = "lb4-nat4-port",
1461 : [LB4_NODEPORT_NEXT_DROP] = "error-drop",
1462 : },
1463 : };
1464 :
1465 91880 : VLIB_REGISTER_NODE (lb6_nodeport_node) =
1466 : {
1467 : .function = lb6_nodeport_node_fn,
1468 : .name = "lb6-nodeport",
1469 : .vector_size = sizeof(u32),
1470 : .format_trace = format_nodeport_lb_trace,
1471 : .n_errors = LB_N_ERROR,
1472 : .error_strings = lb_error_strings,
1473 : .n_next_nodes = LB6_NODEPORT_N_NEXT,
1474 : .next_nodes =
1475 : {
1476 : [LB6_NODEPORT_NEXT_IP6_NAT6] = "lb6-nat6-port",
1477 : [LB6_NODEPORT_NEXT_DROP] = "error-drop",
1478 : },
1479 : };
1480 :
1481 44823 : VNET_FEATURE_INIT (lb_nat4_in2out_node_fn, static) =
1482 : {
1483 : .arc_name = "ip4-unicast",
1484 : .node_name = "lb-nat4-in2out",
1485 : .runs_before = VNET_FEATURES("ip4-lookup"),
1486 : };
1487 :
1488 91880 : VLIB_REGISTER_NODE (lb_nat4_in2out_node) =
1489 : {
1490 : .function = lb_nat4_in2out_node_fn,
1491 : .name = "lb-nat4-in2out",
1492 : .vector_size = sizeof(u32),
1493 : .format_trace = format_lb_nat_trace,
1494 : .n_errors = LB_N_ERROR,
1495 : .error_strings = lb_error_strings,
1496 : .n_next_nodes = LB_NAT4_IN2OUT_N_NEXT,
1497 : .next_nodes =
1498 : {
1499 : [LB_NAT4_IN2OUT_NEXT_DROP] = "error-drop",
1500 : [LB_NAT4_IN2OUT_NEXT_LOOKUP] = "ip4-lookup",
1501 : },
1502 : };
1503 :
1504 44823 : VNET_FEATURE_INIT (lb_nat6_in2out_node_fn, static) =
1505 : {
1506 : .arc_name = "ip6-unicast",
1507 : .node_name = "lb-nat6-in2out",
1508 : .runs_before = VNET_FEATURES("ip6-lookup"),
1509 : };
1510 :
1511 91880 : VLIB_REGISTER_NODE (lb_nat6_in2out_node) =
1512 : {
1513 : .function = lb_nat6_in2out_node_fn,
1514 : .name = "lb-nat6-in2out",
1515 : .vector_size = sizeof(u32),
1516 : .format_trace = format_lb_nat_trace,
1517 : .n_errors = LB_N_ERROR,
1518 : .error_strings = lb_error_strings,
1519 : .n_next_nodes = LB_NAT6_IN2OUT_N_NEXT,
1520 : .next_nodes =
1521 : {
1522 : [LB_NAT6_IN2OUT_NEXT_DROP] = "error-drop",
1523 : [LB_NAT6_IN2OUT_NEXT_LOOKUP] = "ip6-lookup",
1524 : },
1525 : };
|