Line data Source code
1 : /*
2 : * Copyright (c) 2018 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 : * @file
17 : * @brief NAT44 endpoint-dependent inside to outside network translation
18 : */
19 :
20 : #include <vlib/vlib.h>
21 : #include <vnet/vnet.h>
22 : #include <vnet/ip/ip.h>
23 : #include <vnet/ethernet/ethernet.h>
24 : #include <vnet/fib/ip4_fib.h>
25 : #include <vnet/udp/udp_local.h>
26 : #include <vppinfra/error.h>
27 :
28 : #include <nat/lib/nat_inlines.h>
29 : #include <nat/lib/ipfix_logging.h>
30 :
31 : #include <nat/nat44-ed/nat44_ed.h>
32 : #include <nat/nat44-ed/nat44_ed_inlines.h>
33 :
34 : static char *nat_in2out_ed_error_strings[] = {
35 : #define _(sym,string) string,
36 : foreach_nat_in2out_ed_error
37 : #undef _
38 : };
39 :
40 : typedef struct
41 : {
42 : u32 sw_if_index;
43 : u32 next_index;
44 : u32 session_index;
45 : nat_translation_error_e translation_error;
46 : nat_6t_flow_t i2of;
47 : nat_6t_flow_t o2if;
48 : clib_bihash_kv_16_8_t search_key;
49 : u8 is_slow_path;
50 : u8 translation_via_i2of;
51 : u8 lookup_skipped;
52 : u8 tcp_state;
53 : } nat_in2out_ed_trace_t;
54 :
55 : static u8 *
56 2756 : format_nat_in2out_ed_trace (u8 * s, va_list * args)
57 : {
58 2756 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
59 2756 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
60 2756 : nat_in2out_ed_trace_t *t = va_arg (*args, nat_in2out_ed_trace_t *);
61 : char *tag;
62 :
63 2756 : tag =
64 2756 : t->is_slow_path ? "NAT44_IN2OUT_ED_SLOW_PATH" :
65 : "NAT44_IN2OUT_ED_FAST_PATH";
66 :
67 2756 : s = format (s, "%s: sw_if_index %d, next index %d", tag, t->sw_if_index,
68 : t->next_index);
69 2756 : if (~0 != t->session_index)
70 : {
71 1218 : s = format (s, ", session %d, translation result '%U' via %s",
72 : t->session_index, format_nat_ed_translation_error,
73 1218 : t->translation_error,
74 1218 : t->translation_via_i2of ? "i2of" : "o2if");
75 1218 : s = format (s, "\n i2of %U", format_nat_6t_flow, &t->i2of);
76 1218 : s = format (s, "\n o2if %U", format_nat_6t_flow, &t->o2if);
77 : }
78 2756 : if (!t->is_slow_path)
79 : {
80 1587 : if (t->lookup_skipped)
81 : {
82 89 : s = format (s, "\n lookup skipped - cached session index used");
83 : }
84 : else
85 : {
86 1498 : s = format (s, "\n search key %U", format_ed_session_kvp,
87 : &t->search_key);
88 : }
89 : }
90 2756 : if (IP_PROTOCOL_TCP == t->i2of.match.proto)
91 : {
92 110 : s = format (s, "\n TCP state: %U", format_nat44_ed_tcp_state,
93 110 : t->tcp_state);
94 : }
95 :
96 2756 : return s;
97 : }
98 :
99 : static int
100 28348 : nat_ed_alloc_addr_and_port_with_snat_address (
101 : snat_main_t *sm, u8 proto, u32 thread_index, snat_address_t *a,
102 : u16 port_per_thread, u32 snat_thread_index, snat_session_t *s,
103 : ip4_address_t *outside_addr, u16 *outside_port)
104 : {
105 28348 : const u16 port_thread_offset =
106 28348 : (port_per_thread * snat_thread_index) + ED_USER_PORT_OFFSET;
107 :
108 : /* Backup original match in case of failure */
109 28348 : const nat_6t_t match = s->o2i.match;
110 :
111 28348 : s->o2i.match.daddr = a->addr;
112 : /* first try port suggested by caller */
113 28348 : u16 port = clib_net_to_host_u16 (*outside_port);
114 28348 : u16 port_offset = port - port_thread_offset;
115 28348 : if (port < port_thread_offset ||
116 206 : port >= port_thread_offset + port_per_thread)
117 : {
118 : /* need to pick a different port, suggested port doesn't fit in
119 : * this thread's port range */
120 28178 : port_offset = snat_random_port (0, port_per_thread - 1);
121 28178 : port = port_thread_offset + port_offset;
122 : }
123 28348 : u16 attempts = ED_PORT_ALLOC_ATTEMPTS;
124 : do
125 : {
126 42732 : if (IP_PROTOCOL_ICMP == proto)
127 : {
128 7531 : s->o2i.match.sport = clib_host_to_net_u16 (port);
129 : }
130 42732 : s->o2i.match.dport = clib_host_to_net_u16 (port);
131 42732 : if (0 == nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 2))
132 : {
133 28214 : *outside_addr = a->addr;
134 28214 : *outside_port = clib_host_to_net_u16 (port);
135 28214 : return 0;
136 : }
137 14519 : port_offset = snat_random_port (0, port_per_thread - 1);
138 14519 : port = port_thread_offset + port_offset;
139 14519 : --attempts;
140 : }
141 14519 : while (attempts > 0);
142 :
143 : /* Revert match */
144 135 : s->o2i.match = match;
145 135 : return 1;
146 : }
147 :
148 : static int
149 28352 : nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index,
150 : u32 tx_sw_if_index, u32 nat_proto,
151 : u32 thread_index, ip4_address_t s_addr,
152 : ip4_address_t d_addr, u32 snat_thread_index,
153 : snat_session_t *s, ip4_address_t *outside_addr,
154 : u16 *outside_port)
155 : {
156 28352 : if (vec_len (sm->addresses) > 0)
157 : {
158 56696 : u32 s_addr_offset = (s_addr.as_u32 + (s_addr.as_u32 >> 8) +
159 28348 : (s_addr.as_u32 >> 16) + (s_addr.as_u32 >> 24)) %
160 28348 : vec_len (sm->addresses);
161 28348 : snat_address_t *a, *ja = 0, *ra = 0, *ba = 0;
162 : int i;
163 :
164 : // output feature
165 28348 : if (tx_sw_if_index != ~0)
166 : {
167 44 : for (i = s_addr_offset; i < vec_len (sm->addresses); ++i)
168 : {
169 22 : a = sm->addresses + i;
170 22 : if (a->fib_index == rx_fib_index)
171 : {
172 0 : if (a->sw_if_index == tx_sw_if_index)
173 : {
174 0 : if ((a->addr_len != ~0) &&
175 0 : (a->net.as_u32 ==
176 0 : (d_addr.as_u32 & ip4_main.fib_masks[a->addr_len])))
177 :
178 : {
179 0 : return nat_ed_alloc_addr_and_port_with_snat_address (
180 : sm, nat_proto, thread_index, a,
181 0 : sm->port_per_thread, snat_thread_index, s,
182 : outside_addr, outside_port);
183 : }
184 0 : ra = a;
185 : }
186 0 : ja = a;
187 : }
188 22 : else if (a->fib_index == ~0)
189 : {
190 22 : ba = a;
191 : }
192 : }
193 22 : for (i = 0; i < s_addr_offset; ++i)
194 : {
195 0 : a = sm->addresses + i;
196 0 : if (a->fib_index == rx_fib_index)
197 : {
198 0 : if (a->sw_if_index == tx_sw_if_index)
199 : {
200 0 : if ((a->addr_len != ~0) &&
201 0 : (a->net.as_u32 ==
202 0 : (d_addr.as_u32 & ip4_main.fib_masks[a->addr_len])))
203 :
204 : {
205 0 : return nat_ed_alloc_addr_and_port_with_snat_address (
206 : sm, nat_proto, thread_index, a,
207 0 : sm->port_per_thread, snat_thread_index, s,
208 : outside_addr, outside_port);
209 : }
210 0 : ra = a;
211 : }
212 0 : ja = a;
213 : }
214 0 : else if (a->fib_index == ~0)
215 : {
216 0 : ba = a;
217 : }
218 : }
219 22 : if (ra)
220 : {
221 0 : return nat_ed_alloc_addr_and_port_with_snat_address (
222 0 : sm, nat_proto, thread_index, ra, sm->port_per_thread,
223 : snat_thread_index, s, outside_addr, outside_port);
224 : }
225 : }
226 : else
227 : {
228 : // first try nat pool addresses to sw interface addreses mappings
229 63904 : for (i = s_addr_offset; i < vec_len (sm->addresses); ++i)
230 : {
231 35578 : a = sm->addresses + i;
232 35578 : if (a->fib_index == rx_fib_index)
233 : {
234 3 : if ((a->addr_len != ~0) &&
235 0 : (a->net.as_u32 ==
236 0 : (d_addr.as_u32 & ip4_main.fib_masks[a->addr_len])))
237 : {
238 0 : return nat_ed_alloc_addr_and_port_with_snat_address (
239 0 : sm, nat_proto, thread_index, a, sm->port_per_thread,
240 : snat_thread_index, s, outside_addr, outside_port);
241 : }
242 3 : ja = a;
243 : }
244 35575 : else if (a->fib_index == ~0)
245 : {
246 35575 : ba = a;
247 : }
248 : }
249 33674 : for (i = 0; i < s_addr_offset; ++i)
250 : {
251 5348 : a = sm->addresses + i;
252 5348 : if (a->fib_index == rx_fib_index)
253 : {
254 0 : if ((a->addr_len != ~0) &&
255 0 : (a->net.as_u32 ==
256 0 : (d_addr.as_u32 & ip4_main.fib_masks[a->addr_len])))
257 : {
258 0 : return nat_ed_alloc_addr_and_port_with_snat_address (
259 0 : sm, nat_proto, thread_index, a, sm->port_per_thread,
260 : snat_thread_index, s, outside_addr, outside_port);
261 : }
262 0 : ja = a;
263 : }
264 5348 : else if (a->fib_index == ~0)
265 : {
266 5348 : ba = a;
267 : }
268 : }
269 : }
270 :
271 28348 : if (ja || ba)
272 : {
273 28348 : a = ja ? ja : ba;
274 28349 : return nat_ed_alloc_addr_and_port_with_snat_address (
275 28348 : sm, nat_proto, thread_index, a, sm->port_per_thread,
276 : snat_thread_index, s, outside_addr, outside_port);
277 : }
278 : }
279 : /* Totally out of translations to use... */
280 4 : nat_ipfix_logging_addresses_exhausted (thread_index, 0);
281 4 : return 1;
282 : }
283 :
284 : static_always_inline int
285 28358 : nat44_ed_external_sm_lookup (snat_main_t *sm, ip4_address_t match_addr,
286 : u16 match_port, ip_protocol_t match_protocol,
287 : ip4_address_t *daddr, u16 *dport)
288 : {
289 : snat_static_mapping_t *m =
290 28358 : nat44_ed_sm_o2i_lookup (sm, match_addr, match_port, 0, match_protocol);
291 28360 : if (!m)
292 : {
293 : /* Try address only mapping */
294 28358 : m = nat44_ed_sm_o2i_lookup (sm, match_addr, 0, 0, 0);
295 28358 : if (!m)
296 28350 : return 0;
297 : }
298 10 : *daddr = m->local_addr;
299 10 : if (dport)
300 : {
301 : /* Address only mapping doesn't change port */
302 9 : *dport = is_sm_addr_only (m->flags) ? match_port : m->local_port;
303 : }
304 10 : return 1;
305 : }
306 :
307 : static_always_inline vrf_table_t *
308 56698 : get_vrf_table_by_fib (u32 fib_index)
309 : {
310 56698 : snat_main_t *sm = &snat_main;
311 : vrf_table_t *t;
312 :
313 56698 : pool_foreach (t, sm->vrf_tables)
314 : {
315 0 : if (fib_index == t->table_fib_index)
316 : {
317 0 : return t;
318 : }
319 : }
320 :
321 56698 : return 0;
322 : }
323 :
324 : static_always_inline u32
325 28360 : get_tx_fib_index (u32 rx_fib_index, ip4_address_t addr)
326 : {
327 28360 : fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
328 28360 : fib_prefix_t pfx = {
329 : .fp_proto = FIB_PROTOCOL_IP4,
330 : .fp_len = 32,
331 28360 : .fp_addr = {.ip4.as_u32 = addr.as_u32,}
332 : ,
333 : };
334 :
335 28360 : snat_main_t *sm = &snat_main;
336 28360 : vrf_table_t *t = get_vrf_table_by_fib (rx_fib_index);
337 : // default to rx fib
338 28360 : u32 tx_fib_index = rx_fib_index;
339 :
340 28360 : if (0 != t)
341 : {
342 : // managed routes to other fibs
343 : vrf_route_t *r;
344 0 : pool_foreach (r, t->routes)
345 : {
346 0 : fei = fib_table_lookup (r->fib_index, &pfx);
347 0 : if ((FIB_NODE_INDEX_INVALID != fei) &&
348 0 : (~0 != fib_entry_get_resolving_interface (fei)))
349 : {
350 0 : tx_fib_index = r->fib_index;
351 0 : break;
352 : }
353 : }
354 : }
355 : else
356 : {
357 : // default to configured fib
358 28360 : tx_fib_index = sm->outside_fib_index;
359 :
360 : // default routes to other fibs
361 : nat_fib_t *f;
362 28360 : vec_foreach (f, sm->outside_fibs)
363 : {
364 28360 : fei = fib_table_lookup (f->fib_index, &pfx);
365 56717 : if ((FIB_NODE_INDEX_INVALID != fei) &&
366 28359 : (~0 != fib_entry_get_resolving_interface (fei)))
367 : {
368 28358 : tx_fib_index = f->fib_index;
369 28358 : break;
370 : }
371 : }
372 : }
373 :
374 28358 : return tx_fib_index;
375 : }
376 :
377 : static_always_inline int
378 28340 : is_destination_resolvable (u32 rx_fib_index, ip4_address_t addr)
379 : {
380 28340 : fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
381 28340 : fib_prefix_t pfx = {
382 : .fp_proto = FIB_PROTOCOL_IP4,
383 : .fp_len = 32,
384 28340 : .fp_addr = {.ip4.as_u32 = addr.as_u32,}
385 : ,
386 : };
387 :
388 28340 : snat_main_t *sm = &snat_main;
389 28340 : vrf_table_t *t = get_vrf_table_by_fib (rx_fib_index);
390 : u32 ii;
391 :
392 28338 : if (0 != t)
393 : {
394 : // managed routes to other fibs
395 : vrf_route_t *r;
396 0 : pool_foreach (r, t->routes)
397 : {
398 0 : fei = fib_table_lookup (r->fib_index, &pfx);
399 0 : if ((FIB_NODE_INDEX_INVALID != fei) &&
400 0 : (~0 != (ii = fib_entry_get_resolving_interface (fei))))
401 : {
402 0 : return 1;
403 : }
404 : }
405 : }
406 : else
407 : {
408 : // default routes to other fibs
409 : nat_fib_t *f;
410 28344 : vec_foreach (f, sm->outside_fibs)
411 : {
412 28340 : fei = fib_table_lookup (f->fib_index, &pfx);
413 56680 : if ((FIB_NODE_INDEX_INVALID != fei) &&
414 28343 : (~0 != (ii = fib_entry_get_resolving_interface (fei))))
415 : {
416 : snat_interface_t *i;
417 56695 : pool_foreach (i, sm->interfaces)
418 : {
419 56694 : if ((nat44_ed_is_interface_outside (i)) &&
420 28341 : (ii == i->sw_if_index))
421 : {
422 28337 : return 1;
423 : }
424 : }
425 : }
426 : }
427 : }
428 :
429 4 : return 0;
430 : }
431 :
432 : static u32
433 28369 : slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b,
434 : ip4_address_t l_addr, ip4_address_t r_addr, u16 l_port,
435 : u16 r_port, u8 proto, u32 rx_fib_index, u32 tx_sw_if_index,
436 : snat_session_t **sessionp, vlib_node_runtime_t *node, u32 next,
437 : u32 thread_index, f64 now)
438 : {
439 28369 : snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
440 : ip4_address_t outside_addr;
441 : u16 outside_port;
442 : u32 tx_fib_index;
443 28369 : u8 is_identity_nat = 0;
444 :
445 28369 : snat_session_t *s = NULL;
446 28369 : lb_nat_type_t lb = 0;
447 28369 : ip4_address_t daddr = r_addr;
448 28369 : u16 dport = r_port;
449 :
450 28369 : if (PREDICT_FALSE
451 : (nat44_ed_maximum_sessions_exceeded (sm, rx_fib_index, thread_index)))
452 : {
453 6 : if (!nat_lru_free_one (sm, thread_index, now))
454 : {
455 5 : b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
456 5 : nat_ipfix_logging_max_sessions (thread_index,
457 : sm->max_translations_per_thread);
458 5 : nat_elog_notice (sm, "maximum sessions exceeded");
459 5 : return NAT_NEXT_DROP;
460 : }
461 : }
462 :
463 : ip4_address_t sm_addr;
464 : u16 sm_port;
465 : u32 sm_fib_index;
466 28364 : int is_sm = 0;
467 : // First try to match static mapping by local address and port
468 28364 : if (!snat_static_mapping_match (vm, l_addr, l_port, rx_fib_index, proto,
469 : &sm_addr, &sm_port, &sm_fib_index, 0, 0, 0,
470 : &lb, 0, &is_identity_nat, 0))
471 : {
472 12 : if (PREDICT_FALSE (is_identity_nat))
473 : {
474 0 : *sessionp = NULL;
475 0 : return next;
476 : }
477 12 : is_sm = 1;
478 : }
479 :
480 28365 : if (PREDICT_TRUE (proto == IP_PROTOCOL_TCP))
481 : {
482 1603 : if (PREDICT_FALSE (!tcp_flags_is_init (
483 : vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
484 : {
485 8 : b->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN];
486 8 : return NAT_NEXT_DROP;
487 : }
488 : }
489 :
490 28357 : s = nat_ed_session_alloc (sm, thread_index, now, proto);
491 28358 : ASSERT (s);
492 :
493 28358 : tx_fib_index = get_tx_fib_index (rx_fib_index, r_addr);
494 :
495 28356 : if (!is_sm)
496 : {
497 28350 : s->in2out.addr = l_addr;
498 28350 : s->in2out.port = l_port;
499 28350 : s->proto = proto;
500 28350 : s->in2out.fib_index = rx_fib_index;
501 28350 : s->out2in.fib_index = tx_fib_index;
502 :
503 : // suggest using local port to allocation function
504 28350 : outside_port = l_port;
505 :
506 28350 : if (PREDICT_FALSE (nat44_ed_external_sm_lookup (sm, r_addr, r_port,
507 : proto, &daddr, &dport)))
508 : {
509 9 : s->flags |= SNAT_SESSION_FLAG_HAIRPINNING;
510 : }
511 :
512 : // destination addr/port updated with real values in
513 : // nat_ed_alloc_addr_and_port
514 28353 : nat_6t_o2i_flow_init (sm, thread_index, s, daddr, dport, daddr, 0,
515 : s->out2in.fib_index, proto);
516 28352 : nat_6t_flow_daddr_rewrite_set (&s->o2i, l_addr.as_u32);
517 28353 : if (IP_PROTOCOL_ICMP == proto)
518 : {
519 6566 : nat_6t_flow_icmp_id_rewrite_set (&s->o2i, l_port);
520 : }
521 : else
522 : {
523 21787 : nat_6t_flow_dport_rewrite_set (&s->o2i, l_port);
524 : }
525 28353 : nat_6t_flow_txfib_rewrite_set (&s->o2i, rx_fib_index);
526 :
527 28352 : if (nat_ed_alloc_addr_and_port (
528 : sm, rx_fib_index, tx_sw_if_index, proto, thread_index, l_addr,
529 : r_addr, tsm->snat_thread_index, s, &outside_addr, &outside_port))
530 : {
531 139 : nat_elog_notice (sm, "addresses exhausted");
532 139 : b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
533 139 : nat_ed_session_delete (sm, s, thread_index, 1);
534 139 : return NAT_NEXT_DROP;
535 : }
536 28214 : s->out2in.addr = outside_addr;
537 28214 : s->out2in.port = outside_port;
538 : }
539 : else
540 : {
541 : // static mapping
542 6 : s->out2in.addr = outside_addr = sm_addr;
543 6 : s->out2in.port = outside_port = sm_port;
544 6 : s->in2out.addr = l_addr;
545 6 : s->in2out.port = l_port;
546 6 : s->proto = proto;
547 6 : s->in2out.fib_index = rx_fib_index;
548 6 : s->out2in.fib_index = tx_fib_index;
549 6 : s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
550 :
551 : // hairpinning?
552 6 : int is_hairpinning = nat44_ed_external_sm_lookup (sm, r_addr, r_port,
553 : proto, &daddr, &dport);
554 6 : s->flags |= is_hairpinning * SNAT_SESSION_FLAG_HAIRPINNING;
555 :
556 6 : if (IP_PROTOCOL_ICMP == proto)
557 : {
558 0 : nat_6t_o2i_flow_init (sm, thread_index, s, daddr, sm_port, sm_addr,
559 : sm_port, s->out2in.fib_index, proto);
560 0 : nat_6t_flow_icmp_id_rewrite_set (&s->o2i, l_port);
561 : }
562 : else
563 : {
564 6 : nat_6t_o2i_flow_init (sm, thread_index, s, daddr, dport, sm_addr,
565 : sm_port, s->out2in.fib_index, proto);
566 6 : nat_6t_flow_dport_rewrite_set (&s->o2i, l_port);
567 : }
568 6 : nat_6t_flow_daddr_rewrite_set (&s->o2i, l_addr.as_u32);
569 6 : nat_6t_flow_txfib_rewrite_set (&s->o2i, rx_fib_index);
570 6 : if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 2))
571 : {
572 0 : nat_elog_notice (sm, "out2in key add failed");
573 0 : goto error;
574 : }
575 : }
576 :
577 28220 : if (lb)
578 0 : s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING;
579 28220 : s->ext_host_addr = r_addr;
580 28220 : s->ext_host_port = r_port;
581 :
582 28220 : nat_6t_i2o_flow_init (sm, thread_index, s, l_addr, l_port, r_addr, r_port,
583 : rx_fib_index, proto);
584 28220 : nat_6t_flow_saddr_rewrite_set (&s->i2o, outside_addr.as_u32);
585 28220 : nat_6t_flow_daddr_rewrite_set (&s->i2o, daddr.as_u32);
586 :
587 28220 : if (IP_PROTOCOL_ICMP == proto)
588 : {
589 6565 : nat_6t_flow_icmp_id_rewrite_set (&s->i2o, outside_port);
590 : }
591 : else
592 : {
593 21655 : nat_6t_flow_sport_rewrite_set (&s->i2o, outside_port);
594 21655 : nat_6t_flow_dport_rewrite_set (&s->i2o, dport);
595 : }
596 28220 : nat_6t_flow_txfib_rewrite_set (&s->i2o, tx_fib_index);
597 :
598 28220 : if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
599 : {
600 0 : nat_elog_notice (sm, "in2out key add failed");
601 0 : goto error;
602 : }
603 :
604 : /* log NAT event */
605 28220 : nat_ipfix_logging_nat44_ses_create (
606 28220 : thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32, s->proto,
607 28220 : s->in2out.port, s->out2in.port, s->in2out.fib_index);
608 :
609 28220 : nat_syslog_nat44_sadd (0, s->in2out.fib_index, &s->in2out.addr,
610 28220 : s->in2out.port, &s->ext_host_nat_addr,
611 28220 : s->ext_host_nat_port, &s->out2in.addr, s->out2in.port,
612 28220 : &s->ext_host_addr, s->ext_host_port, s->proto, 0);
613 :
614 28220 : per_vrf_sessions_register_session (s, thread_index);
615 :
616 28220 : *sessionp = s;
617 28220 : return next;
618 0 : error:
619 0 : if (s)
620 : {
621 0 : nat_ed_session_delete (sm, s, thread_index, 1);
622 : }
623 0 : *sessionp = s = NULL;
624 0 : return NAT_NEXT_DROP;
625 : }
626 :
627 : static_always_inline int
628 28369 : nat44_ed_not_translate (vlib_main_t *vm, vlib_node_runtime_t *node,
629 : u32 sw_if_index, vlib_buffer_t *b, ip4_header_t *ip,
630 : u32 proto, u32 rx_fib_index)
631 : {
632 28369 : snat_main_t *sm = &snat_main;
633 :
634 : clib_bihash_kv_16_8_t kv, value;
635 : ip4_address_t placeholder_addr;
636 : u32 placeholder_fib_index;
637 : u16 placeholder_port;
638 :
639 28369 : init_ed_k (&kv, ip->dst_address.as_u32,
640 28369 : vnet_buffer (b)->ip.reass.l4_dst_port, ip->src_address.as_u32,
641 28369 : vnet_buffer (b)->ip.reass.l4_src_port, sm->outside_fib_index,
642 28369 : ip->protocol);
643 :
644 : // do nat if active session or is static mapping
645 56740 : if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value) ||
646 28370 : !snat_static_mapping_match (
647 28370 : vm, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port,
648 : sm->outside_fib_index, proto, &placeholder_addr, &placeholder_port,
649 : &placeholder_fib_index, 1, 0, 0, 0, 0, 0, 0))
650 : {
651 9 : return 0;
652 : }
653 :
654 : // do not nat if forwarding enabled
655 28362 : if (sm->forwarding_enabled)
656 : {
657 17 : return 1;
658 : }
659 :
660 : // do not nat packet aimed at the interface address
661 28345 : if (PREDICT_FALSE (
662 : is_interface_addr (sm, node, sw_if_index, ip->dst_address.as_u32)))
663 : {
664 0 : return 1;
665 : }
666 :
667 : // do nat packets with resolvable destination
668 : // destination can be resolved either by:
669 : // a) vrf routing table entry
670 : // b) (non output feature) outside interface fib
671 28340 : if (is_destination_resolvable (rx_fib_index, ip->dst_address))
672 : {
673 28337 : return 0;
674 : }
675 :
676 4 : return 1;
677 : }
678 :
679 : static_always_inline int
680 66 : nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip,
681 : u32 thread_index, f64 now,
682 : vlib_main_t * vm, vlib_buffer_t * b)
683 : {
684 : clib_bihash_kv_16_8_t kv, value;
685 66 : snat_session_t *s = 0;
686 66 : snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
687 :
688 66 : if (!sm->forwarding_enabled)
689 21 : return 0;
690 :
691 45 : if (ip->protocol == IP_PROTOCOL_ICMP)
692 : {
693 : ip4_address_t lookup_saddr, lookup_daddr;
694 : u16 lookup_sport, lookup_dport;
695 : u8 lookup_protocol;
696 10 : if (nat_get_icmp_session_lookup_values (b, ip, &lookup_saddr,
697 : &lookup_sport, &lookup_daddr,
698 : &lookup_dport, &lookup_protocol))
699 0 : return 0;
700 10 : init_ed_k (&kv, lookup_saddr.as_u32, lookup_sport, lookup_daddr.as_u32,
701 : lookup_dport, 0, lookup_protocol);
702 : }
703 35 : else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
704 : {
705 35 : init_ed_k (&kv, ip->src_address.as_u32,
706 35 : vnet_buffer (b)->ip.reass.l4_src_port, ip->dst_address.as_u32,
707 35 : vnet_buffer (b)->ip.reass.l4_dst_port, 0, ip->protocol);
708 : }
709 : else
710 : {
711 0 : init_ed_k (&kv, ip->src_address.as_u32, 0, ip->dst_address.as_u32, 0, 0,
712 0 : ip->protocol);
713 : }
714 :
715 45 : if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value))
716 : {
717 10 : ASSERT (thread_index == ed_value_get_thread_index (&value));
718 10 : s =
719 10 : pool_elt_at_index (tsm->sessions,
720 : ed_value_get_session_index (&value));
721 :
722 10 : if (na44_ed_is_fwd_bypass_session (s))
723 : {
724 8 : if (ip->protocol == IP_PROTOCOL_TCP)
725 : {
726 4 : nat44_set_tcp_session_state_i2o (
727 4 : sm, now, s, vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags,
728 : thread_index);
729 : }
730 : /* Accounting */
731 8 : nat44_session_update_counters (s, now,
732 : vlib_buffer_length_in_chain (vm, b),
733 : thread_index);
734 : /* Per-user LRU list maintenance */
735 8 : nat44_session_update_lru (sm, s, thread_index);
736 8 : return 1;
737 : }
738 : else
739 2 : return 0;
740 : }
741 :
742 35 : return 0;
743 : }
744 :
745 : static_always_inline int
746 46 : nat44_ed_not_translate_output_feature (snat_main_t *sm, vlib_buffer_t *b,
747 : ip4_header_t *ip, u16 src_port,
748 : u16 dst_port, u32 thread_index,
749 : u32 rx_sw_if_index, u32 tx_sw_if_index,
750 : int is_multi_worker)
751 : {
752 : clib_bihash_kv_16_8_t kv, value;
753 46 : snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
754 : snat_interface_t *i;
755 : snat_session_t *s;
756 46 : u32 rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (rx_sw_if_index);
757 46 : u32 tx_fib_index = ip4_fib_table_get_index_for_sw_if_index (tx_sw_if_index);
758 :
759 : /* src NAT check */
760 46 : init_ed_k (&kv, ip->src_address.as_u32, src_port, ip->dst_address.as_u32,
761 46 : dst_port, tx_fib_index, ip->protocol);
762 46 : if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value))
763 : {
764 0 : ASSERT (thread_index == ed_value_get_thread_index (&value));
765 0 : s =
766 0 : pool_elt_at_index (tsm->sessions,
767 : ed_value_get_session_index (&value));
768 0 : return 1;
769 : }
770 :
771 : /* dst NAT check */
772 46 : if (is_multi_worker &&
773 29 : PREDICT_TRUE (!pool_is_free_index (
774 : tsm->sessions, vnet_buffer2 (b)->nat.cached_dst_nat_session_index)))
775 : {
776 : nat_6t_t lookup;
777 24 : lookup.fib_index = rx_fib_index;
778 24 : lookup.proto = ip->protocol;
779 24 : lookup.daddr.as_u32 = ip->src_address.as_u32;
780 24 : lookup.dport = src_port;
781 24 : lookup.saddr.as_u32 = ip->dst_address.as_u32;
782 24 : lookup.sport = dst_port;
783 24 : s = pool_elt_at_index (
784 : tsm->sessions, vnet_buffer2 (b)->nat.cached_dst_nat_session_index);
785 24 : if (PREDICT_TRUE (nat_6t_t_eq (&s->i2o.match, &lookup)))
786 : {
787 4 : goto skip_dst_nat_lookup;
788 : }
789 20 : s = NULL;
790 : }
791 :
792 42 : init_ed_k (&kv, ip->dst_address.as_u32, dst_port, ip->src_address.as_u32,
793 42 : src_port, rx_fib_index, ip->protocol);
794 42 : if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value))
795 : {
796 26 : ASSERT (thread_index == ed_value_get_thread_index (&value));
797 26 : s =
798 26 : pool_elt_at_index (tsm->sessions,
799 : ed_value_get_session_index (&value));
800 :
801 30 : skip_dst_nat_lookup:
802 30 : if (na44_ed_is_fwd_bypass_session (s))
803 6 : return 0;
804 :
805 : /* hairpinning */
806 48 : pool_foreach (i, sm->output_feature_interfaces)
807 : {
808 24 : if ((nat44_ed_is_interface_inside (i)) &&
809 24 : (rx_sw_if_index == i->sw_if_index))
810 0 : return 0;
811 : }
812 24 : return 1;
813 : }
814 :
815 16 : return 0;
816 : }
817 :
818 : static inline u32
819 6568 : icmp_in2out_ed_slow_path (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip,
820 : icmp46_header_t *icmp, u32 sw_if_index,
821 : u32 tx_sw_if_index, u32 rx_fib_index,
822 : vlib_node_runtime_t *node, u32 next, f64 now,
823 : u32 thread_index, snat_session_t **s_p,
824 : int is_multi_worker)
825 : {
826 6568 : vlib_main_t *vm = vlib_get_main ();
827 : u16 checksum;
828 : int err;
829 6568 : snat_session_t *s = NULL;
830 6568 : u8 lookup_protocol = ip->protocol;
831 : u16 lookup_sport, lookup_dport;
832 : ip4_address_t lookup_saddr, lookup_daddr;
833 :
834 6568 : err = nat_get_icmp_session_lookup_values (b, ip, &lookup_saddr,
835 : &lookup_sport, &lookup_daddr,
836 : &lookup_dport, &lookup_protocol);
837 6568 : if (err != 0)
838 : {
839 0 : b->error = node->errors[err];
840 0 : return NAT_NEXT_DROP;
841 : }
842 :
843 6568 : if (tx_sw_if_index != ~0)
844 : {
845 8 : if (PREDICT_FALSE (nat44_ed_not_translate_output_feature (
846 : sm, b, ip, lookup_sport, lookup_dport, thread_index, sw_if_index,
847 : tx_sw_if_index, is_multi_worker)))
848 : {
849 2 : return next;
850 : }
851 : }
852 : else
853 : {
854 6560 : if (PREDICT_FALSE (nat44_ed_not_translate (
855 : vm, node, sw_if_index, b, ip, IP_PROTOCOL_ICMP, rx_fib_index)))
856 : {
857 0 : return next;
858 : }
859 : }
860 :
861 6566 : if (PREDICT_FALSE (icmp_type_is_error_message (
862 : vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
863 : {
864 0 : b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
865 0 : return NAT_NEXT_DROP;
866 : }
867 :
868 : next =
869 6566 : slow_path_ed (vm, sm, b, ip->src_address, ip->dst_address, lookup_sport,
870 6566 : lookup_dport, ip->protocol, rx_fib_index, tx_sw_if_index, &s,
871 : node, next, thread_index, vlib_time_now (vm));
872 :
873 6566 : if (NAT_NEXT_DROP == next)
874 1 : goto out;
875 :
876 6565 : if (PREDICT_TRUE (!ip4_is_fragment (ip)))
877 : {
878 13112 : ip_csum_t sum = ip_incremental_checksum_buffer (
879 6556 : vm, b, (u8 *) icmp - (u8 *) vlib_buffer_get_current (b),
880 6556 : ntohs (ip->length) - ip4_header_bytes (ip), 0);
881 6556 : checksum = ~ip_csum_fold (sum);
882 6556 : if (PREDICT_FALSE (checksum != 0 && checksum != 0xffff))
883 : {
884 0 : next = NAT_NEXT_DROP;
885 0 : goto out;
886 : }
887 : }
888 :
889 6565 : out:
890 6566 : if (PREDICT_TRUE (next != NAT_NEXT_DROP && s))
891 : {
892 : /* Accounting */
893 6565 : nat44_session_update_counters (
894 : s, now, vlib_buffer_length_in_chain (vm, b), thread_index);
895 : /* Per-user LRU list maintenance */
896 6565 : nat44_session_update_lru (sm, s, thread_index);
897 : }
898 6566 : *s_p = s;
899 6566 : return next;
900 : }
901 :
902 : static snat_session_t *
903 2 : nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b,
904 : ip4_header_t *ip, u32 rx_fib_index,
905 : u32 thread_index, f64 now,
906 : vlib_main_t *vm,
907 : vlib_node_runtime_t *node)
908 : {
909 : clib_bihash_kv_16_8_t s_kv, s_value;
910 2 : snat_static_mapping_t *m = NULL;
911 2 : snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
912 2 : snat_session_t *s = NULL;
913 : u32 tx_fib_index;
914 : int i;
915 2 : ip4_address_t new_src_addr = { 0 };
916 2 : ip4_address_t new_dst_addr = ip->dst_address;
917 :
918 2 : if (PREDICT_FALSE (
919 : nat44_ed_maximum_sessions_exceeded (sm, rx_fib_index, thread_index)))
920 : {
921 0 : b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
922 0 : nat_ipfix_logging_max_sessions (thread_index,
923 : sm->max_translations_per_thread);
924 0 : nat_elog_notice (sm, "maximum sessions exceeded");
925 0 : return 0;
926 : }
927 :
928 2 : tx_fib_index = get_tx_fib_index (rx_fib_index, ip->dst_address);
929 :
930 : // Try to find static mapping first
931 2 : m = nat44_ed_sm_i2o_lookup (sm, ip->src_address, 0, rx_fib_index,
932 2 : ip->protocol);
933 2 : if (m)
934 : {
935 0 : new_src_addr = m->external_addr;
936 : }
937 : else
938 : {
939 2 : pool_foreach (s, tsm->sessions)
940 : {
941 2 : if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
942 : {
943 2 : init_ed_k (&s_kv, s->out2in.addr.as_u32, 0,
944 : ip->dst_address.as_u32, 0, tx_fib_index,
945 2 : ip->protocol);
946 2 : if (clib_bihash_search_16_8 (&sm->flow_hash, &s_kv, &s_value))
947 : {
948 2 : new_src_addr = s->out2in.addr;
949 : }
950 2 : break;
951 : }
952 : }
953 :
954 2 : if (!new_src_addr.as_u32)
955 : {
956 0 : for (i = 0; i < vec_len (sm->addresses); i++)
957 : {
958 0 : init_ed_k (&s_kv, sm->addresses[i].addr.as_u32, 0,
959 : ip->dst_address.as_u32, 0, tx_fib_index,
960 0 : ip->protocol);
961 0 : if (clib_bihash_search_16_8 (&sm->flow_hash, &s_kv, &s_value))
962 : {
963 0 : new_src_addr = sm->addresses[i].addr;
964 : }
965 : }
966 : }
967 : }
968 :
969 2 : if (!new_src_addr.as_u32)
970 : {
971 : // could not allocate address for translation ...
972 0 : return 0;
973 : }
974 :
975 2 : s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol);
976 2 : if (!s)
977 : {
978 0 : b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
979 0 : nat_elog_warn (sm, "create NAT session failed");
980 0 : return 0;
981 : }
982 :
983 2 : nat_6t_i2o_flow_init (sm, thread_index, s, ip->src_address, 0,
984 2 : ip->dst_address, 0, rx_fib_index, ip->protocol);
985 2 : nat_6t_flow_saddr_rewrite_set (&s->i2o, new_src_addr.as_u32);
986 2 : nat_6t_flow_txfib_rewrite_set (&s->i2o, tx_fib_index);
987 :
988 : // hairpinning?
989 2 : int is_hairpinning = nat44_ed_external_sm_lookup (
990 2 : sm, ip->dst_address, 0, ip->protocol, &new_dst_addr, NULL);
991 2 : s->flags |= is_hairpinning * SNAT_SESSION_FLAG_HAIRPINNING;
992 :
993 2 : nat_6t_flow_daddr_rewrite_set (&s->i2o, new_dst_addr.as_u32);
994 2 : nat_6t_flow_txfib_rewrite_set (&s->i2o, tx_fib_index);
995 :
996 2 : nat_6t_o2i_flow_init (sm, thread_index, s, new_dst_addr, 0, new_src_addr, 0,
997 2 : tx_fib_index, ip->protocol);
998 2 : nat_6t_flow_saddr_rewrite_set (&s->o2i, ip->dst_address.as_u32);
999 2 : nat_6t_flow_daddr_rewrite_set (&s->o2i, ip->src_address.as_u32);
1000 2 : nat_6t_flow_txfib_rewrite_set (&s->o2i, rx_fib_index);
1001 :
1002 2 : s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
1003 2 : s->out2in.addr.as_u32 = new_src_addr.as_u32;
1004 2 : s->out2in.fib_index = tx_fib_index;
1005 2 : s->in2out.addr.as_u32 = ip->src_address.as_u32;
1006 2 : s->in2out.fib_index = rx_fib_index;
1007 2 : s->in2out.port = s->out2in.port = ip->protocol;
1008 2 : if (m)
1009 0 : s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
1010 :
1011 2 : if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
1012 : {
1013 0 : nat_elog_notice (sm, "in2out flow hash add failed");
1014 0 : nat_ed_session_delete (sm, s, thread_index, 1);
1015 0 : return NULL;
1016 : }
1017 :
1018 2 : if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 1))
1019 : {
1020 0 : nat_elog_notice (sm, "out2in flow hash add failed");
1021 0 : nat_ed_session_delete (sm, s, thread_index, 1);
1022 0 : return NULL;
1023 : }
1024 :
1025 2 : per_vrf_sessions_register_session (s, thread_index);
1026 :
1027 : /* Accounting */
1028 2 : nat44_session_update_counters (s, now, vlib_buffer_length_in_chain (vm, b),
1029 : thread_index);
1030 : /* Per-user LRU list maintenance */
1031 2 : nat44_session_update_lru (sm, s, thread_index);
1032 :
1033 2 : return s;
1034 : }
1035 :
1036 : static inline uword
1037 365 : nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm,
1038 : vlib_node_runtime_t *node,
1039 : vlib_frame_t *frame,
1040 : int is_output_feature,
1041 : int is_multi_worker)
1042 : {
1043 : u32 n_left_from, *from;
1044 365 : snat_main_t *sm = &snat_main;
1045 365 : f64 now = vlib_time_now (vm);
1046 362 : u32 thread_index = vm->thread_index;
1047 362 : snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
1048 362 : u32 def_slow = is_output_feature ? NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH
1049 362 : : NAT_NEXT_IN2OUT_ED_SLOW_PATH;
1050 :
1051 362 : from = vlib_frame_vector_args (frame);
1052 362 : n_left_from = frame->n_vectors;
1053 :
1054 362 : vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
1055 362 : u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
1056 362 : vlib_get_buffers (vm, from, b, n_left_from);
1057 :
1058 28967 : while (n_left_from > 0)
1059 : {
1060 : vlib_buffer_t *b0;
1061 28602 : u32 rx_sw_if_index0, rx_fib_index0, iph_offset0 = 0;
1062 : u32 tx_sw_if_index0;
1063 : u32 cntr_sw_if_index0;
1064 : ip_protocol_t proto0;
1065 : ip4_header_t *ip0;
1066 28602 : snat_session_t *s0 = 0;
1067 28602 : clib_bihash_kv_16_8_t kv0 = { 0 }, value0;
1068 28602 : nat_translation_error_e translation_error = NAT_ED_TRNSL_ERR_SUCCESS;
1069 28602 : nat_6t_flow_t *f = 0;
1070 : nat_6t_t lookup;
1071 28602 : int lookup_skipped = 0;
1072 :
1073 28602 : b0 = *b;
1074 28602 : b++;
1075 :
1076 : /* Prefetch next iteration. */
1077 28602 : if (PREDICT_TRUE (n_left_from >= 2))
1078 : {
1079 : vlib_buffer_t *p2;
1080 :
1081 28237 : p2 = *b;
1082 :
1083 28237 : vlib_prefetch_buffer_header (p2, LOAD);
1084 :
1085 28240 : clib_prefetch_load (p2->data);
1086 : }
1087 :
1088 28605 : if (is_output_feature)
1089 : {
1090 66 : iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
1091 : }
1092 :
1093 28605 : next[0] = vnet_buffer2 (b0)->nat.arc_next;
1094 :
1095 28604 : ip0 =
1096 28605 : (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) + iph_offset0);
1097 :
1098 28604 : rx_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1099 28604 : tx_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
1100 28604 : cntr_sw_if_index0 =
1101 28604 : is_output_feature ? tx_sw_if_index0 : rx_sw_if_index0;
1102 28604 : rx_fib_index0 = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
1103 : rx_sw_if_index0);
1104 28600 : lookup.fib_index = rx_fib_index0;
1105 :
1106 28600 : if (PREDICT_FALSE (!is_output_feature && ip0->ttl == 1))
1107 : {
1108 0 : vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1109 0 : icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1110 : ICMP4_time_exceeded_ttl_exceeded_in_transit,
1111 : 0);
1112 0 : next[0] = NAT_NEXT_ICMP_ERROR;
1113 0 : goto trace0;
1114 : }
1115 :
1116 28600 : proto0 = ip0->protocol;
1117 :
1118 28600 : if (is_output_feature)
1119 : {
1120 66 : if (PREDICT_FALSE
1121 : (nat_not_translate_output_feature_fwd
1122 : (sm, ip0, thread_index, now, vm, b0)))
1123 8 : goto trace0;
1124 : }
1125 :
1126 28592 : if (PREDICT_FALSE (proto0 == IP_PROTOCOL_ICMP))
1127 : {
1128 6597 : if (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
1129 15 : ICMP4_echo_request &&
1130 15 : vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
1131 3 : ICMP4_echo_reply &&
1132 3 : !icmp_type_is_error_message (
1133 3 : vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags))
1134 : {
1135 0 : b0->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
1136 0 : next[0] = NAT_NEXT_DROP;
1137 0 : goto trace0;
1138 : }
1139 6597 : int err = nat_get_icmp_session_lookup_values (
1140 : b0, ip0, &lookup.saddr, &lookup.sport, &lookup.daddr,
1141 : &lookup.dport, &lookup.proto);
1142 6597 : if (err != 0)
1143 : {
1144 0 : b0->error = node->errors[err];
1145 0 : next[0] = NAT_NEXT_DROP;
1146 0 : goto trace0;
1147 : }
1148 : }
1149 : else
1150 : {
1151 21995 : lookup.proto = ip0->protocol;
1152 21995 : lookup.saddr.as_u32 = ip0->src_address.as_u32;
1153 21995 : lookup.daddr.as_u32 = ip0->dst_address.as_u32;
1154 21995 : lookup.sport = vnet_buffer (b0)->ip.reass.l4_src_port;
1155 21995 : lookup.dport = vnet_buffer (b0)->ip.reass.l4_dst_port;
1156 : }
1157 :
1158 : /* there might be a stashed index in vnet_buffer2 from handoff or
1159 : * classify node, see if it can be used */
1160 56999 : if (is_multi_worker &&
1161 28409 : !pool_is_free_index (tsm->sessions,
1162 28409 : vnet_buffer2 (b0)->nat.cached_session_index))
1163 : {
1164 24025 : s0 = pool_elt_at_index (tsm->sessions,
1165 : vnet_buffer2 (b0)->nat.cached_session_index);
1166 24025 : if (PREDICT_TRUE (
1167 : nat_6t_t_eq (&s0->i2o.match, &lookup)
1168 : // for some hairpinning cases there are two "i2i" flows instead
1169 : // of i2o and o2i as both hosts are on inside
1170 : || (s0->flags & SNAT_SESSION_FLAG_HAIRPINNING &&
1171 : nat_6t_t_eq (&s0->o2i.match, &lookup))))
1172 : {
1173 : /* yes, this is the droid we're looking for */
1174 140 : lookup_skipped = 1;
1175 140 : goto skip_lookup;
1176 : }
1177 23885 : s0 = NULL;
1178 : }
1179 :
1180 28450 : init_ed_k (&kv0, lookup.saddr.as_u32, lookup.sport, lookup.daddr.as_u32,
1181 28450 : lookup.dport, lookup.fib_index, lookup.proto);
1182 :
1183 : // lookup flow
1184 28450 : if (clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0))
1185 : {
1186 : // flow does not exist go slow path
1187 28417 : next[0] = def_slow;
1188 28417 : goto trace0;
1189 : }
1190 :
1191 39 : ASSERT (thread_index == ed_value_get_thread_index (&value0));
1192 39 : s0 =
1193 39 : pool_elt_at_index (tsm->sessions,
1194 : ed_value_get_session_index (&value0));
1195 :
1196 179 : skip_lookup:
1197 :
1198 179 : ASSERT (thread_index == s0->thread_index);
1199 :
1200 179 : if (PREDICT_FALSE (per_vrf_sessions_is_expired (s0, thread_index)))
1201 : {
1202 : // session is closed, go slow path
1203 0 : nat44_ed_free_session_data (sm, s0, thread_index, 0);
1204 0 : nat_ed_session_delete (sm, s0, thread_index, 1);
1205 0 : s0 = 0;
1206 0 : next[0] = def_slow;
1207 0 : goto trace0;
1208 : }
1209 :
1210 : // drop if session expired
1211 : u64 sess_timeout_time;
1212 179 : sess_timeout_time =
1213 179 : s0->last_heard + (f64) nat44_session_get_timeout (sm, s0);
1214 179 : if (now >= sess_timeout_time)
1215 : {
1216 7 : nat44_ed_free_session_data (sm, s0, thread_index, 0);
1217 7 : nat_ed_session_delete (sm, s0, thread_index, 1);
1218 7 : s0 = 0;
1219 : // session is closed, go slow path
1220 7 : next[0] = def_slow;
1221 7 : goto trace0;
1222 : }
1223 :
1224 172 : b0->flags |= VNET_BUFFER_F_IS_NATED;
1225 :
1226 172 : if (nat_6t_t_eq (&s0->i2o.match, &lookup))
1227 : {
1228 171 : f = &s0->i2o;
1229 : }
1230 2 : else if (s0->flags & SNAT_SESSION_FLAG_HAIRPINNING &&
1231 1 : nat_6t_t_eq (&s0->o2i.match, &lookup))
1232 : {
1233 1 : f = &s0->o2i;
1234 : }
1235 : else
1236 : {
1237 0 : translation_error = NAT_ED_TRNSL_ERR_FLOW_MISMATCH;
1238 0 : nat44_ed_free_session_data (sm, s0, thread_index, 0);
1239 0 : nat_ed_session_delete (sm, s0, thread_index, 1);
1240 0 : s0 = 0;
1241 0 : next[0] = NAT_NEXT_DROP;
1242 0 : b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED];
1243 0 : goto trace0;
1244 : }
1245 :
1246 172 : if (NAT_ED_TRNSL_ERR_SUCCESS !=
1247 172 : (translation_error = nat_6t_flow_buf_translate_i2o (
1248 : vm, sm, b0, ip0, f, proto0, is_output_feature)))
1249 : {
1250 0 : nat44_ed_free_session_data (sm, s0, thread_index, 0);
1251 0 : nat_ed_session_delete (sm, s0, thread_index, 1);
1252 0 : s0 = 0;
1253 0 : next[0] = NAT_NEXT_DROP;
1254 0 : b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED];
1255 0 : goto trace0;
1256 : }
1257 :
1258 172 : switch (proto0)
1259 : {
1260 116 : case IP_PROTOCOL_TCP:
1261 116 : vlib_increment_simple_counter (&sm->counters.fastpath.in2out.tcp,
1262 : thread_index, cntr_sw_if_index0, 1);
1263 116 : nat44_set_tcp_session_state_i2o (
1264 116 : sm, now, s0, vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags,
1265 : thread_index);
1266 116 : break;
1267 25 : case IP_PROTOCOL_UDP:
1268 25 : vlib_increment_simple_counter (&sm->counters.fastpath.in2out.udp,
1269 : thread_index, cntr_sw_if_index0, 1);
1270 25 : break;
1271 30 : case IP_PROTOCOL_ICMP:
1272 30 : vlib_increment_simple_counter (&sm->counters.fastpath.in2out.icmp,
1273 : thread_index, cntr_sw_if_index0, 1);
1274 30 : break;
1275 1 : default:
1276 1 : vlib_increment_simple_counter (&sm->counters.fastpath.in2out.other,
1277 : thread_index, cntr_sw_if_index0, 1);
1278 1 : break;
1279 : }
1280 :
1281 : /* Accounting */
1282 172 : nat44_session_update_counters (s0, now,
1283 : vlib_buffer_length_in_chain (vm, b0),
1284 : thread_index);
1285 : /* Per-user LRU list maintenance */
1286 172 : nat44_session_update_lru (sm, s0, thread_index);
1287 :
1288 28604 : trace0:
1289 28604 : if (PREDICT_FALSE
1290 : ((node->flags & VLIB_NODE_FLAG_TRACE)
1291 : && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1292 : {
1293 : nat_in2out_ed_trace_t *t =
1294 20106 : vlib_add_trace (vm, node, b0, sizeof (*t));
1295 20110 : t->sw_if_index = rx_sw_if_index0;
1296 20110 : t->next_index = next[0];
1297 20110 : t->is_slow_path = 0;
1298 20110 : t->translation_error = translation_error;
1299 20110 : t->lookup_skipped = lookup_skipped;
1300 20110 : clib_memcpy (&t->search_key, &kv0, sizeof (t->search_key));
1301 :
1302 20106 : if (s0)
1303 : {
1304 172 : t->session_index = s0 - tsm->sessions;
1305 172 : clib_memcpy (&t->i2of, &s0->i2o, sizeof (t->i2of));
1306 172 : clib_memcpy (&t->o2if, &s0->o2i, sizeof (t->o2if));
1307 172 : t->translation_via_i2of = (&s0->i2o == f);
1308 172 : t->tcp_state = s0->tcp_state;
1309 : }
1310 : else
1311 : {
1312 19934 : t->session_index = ~0;
1313 : }
1314 : }
1315 :
1316 28604 : if (next[0] == NAT_NEXT_DROP)
1317 : {
1318 0 : vlib_increment_simple_counter (&sm->counters.fastpath.in2out.drops,
1319 : thread_index, cntr_sw_if_index0, 1);
1320 : }
1321 :
1322 28604 : n_left_from--;
1323 28604 : next++;
1324 : }
1325 :
1326 365 : vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1327 365 : frame->n_vectors);
1328 365 : return frame->n_vectors;
1329 : }
1330 :
1331 : static inline uword
1332 257 : nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm,
1333 : vlib_node_runtime_t *node,
1334 : vlib_frame_t *frame,
1335 : int is_output_feature,
1336 : int is_multi_worker)
1337 : {
1338 : u32 n_left_from, *from;
1339 257 : snat_main_t *sm = &snat_main;
1340 257 : f64 now = vlib_time_now (vm);
1341 257 : u32 thread_index = vm->thread_index;
1342 257 : snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
1343 :
1344 257 : from = vlib_frame_vector_args (frame);
1345 257 : n_left_from = frame->n_vectors;
1346 :
1347 257 : vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
1348 257 : u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
1349 257 : vlib_get_buffers (vm, from, b, n_left_from);
1350 :
1351 28696 : while (n_left_from > 0)
1352 : {
1353 : vlib_buffer_t *b0;
1354 28439 : u32 rx_sw_if_index0, rx_fib_index0, iph_offset0 = 0;
1355 : u32 tx_sw_if_index0;
1356 : u32 cntr_sw_if_index0;
1357 : ip_protocol_t proto0;
1358 : ip4_header_t *ip0;
1359 : udp_header_t *udp0;
1360 : icmp46_header_t *icmp0;
1361 28439 : snat_session_t *s0 = 0;
1362 28439 : clib_bihash_kv_16_8_t kv0 = { 0 }, value0;
1363 28439 : int translation_error = NAT_ED_TRNSL_ERR_SUCCESS;
1364 :
1365 28439 : b0 = *b;
1366 :
1367 28439 : if (is_output_feature)
1368 52 : iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
1369 :
1370 28439 : next[0] = vnet_buffer2 (b0)->nat.arc_next;
1371 :
1372 28439 : ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
1373 : iph_offset0);
1374 :
1375 28439 : rx_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1376 28439 : tx_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
1377 28439 : cntr_sw_if_index0 =
1378 28439 : is_output_feature ? tx_sw_if_index0 : rx_sw_if_index0;
1379 28439 : rx_fib_index0 = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
1380 : rx_sw_if_index0);
1381 :
1382 28439 : if (PREDICT_FALSE (!is_output_feature && ip0->ttl == 1))
1383 : {
1384 0 : vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1385 0 : icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1386 : ICMP4_time_exceeded_ttl_exceeded_in_transit,
1387 : 0);
1388 0 : next[0] = NAT_NEXT_ICMP_ERROR;
1389 0 : goto trace0;
1390 : }
1391 :
1392 28439 : udp0 = ip4_next_header (ip0);
1393 28439 : icmp0 = (icmp46_header_t *) udp0;
1394 28439 : proto0 = ip0->protocol;
1395 :
1396 28439 : if (PREDICT_FALSE (nat44_ed_is_unk_proto (proto0)))
1397 : {
1398 2 : s0 = nat44_ed_in2out_slowpath_unknown_proto (
1399 : sm, b0, ip0, rx_fib_index0, thread_index, now, vm, node);
1400 2 : if (!s0)
1401 0 : next[0] = NAT_NEXT_DROP;
1402 :
1403 2 : if (NAT_NEXT_DROP != next[0] && s0 &&
1404 : NAT_ED_TRNSL_ERR_SUCCESS !=
1405 2 : (translation_error = nat_6t_flow_buf_translate_i2o (
1406 2 : vm, sm, b0, ip0, &s0->i2o, proto0, is_output_feature)))
1407 : {
1408 0 : nat44_ed_free_session_data (sm, s0, thread_index, 0);
1409 0 : nat_ed_session_delete (sm, s0, thread_index, 1);
1410 0 : s0 = 0;
1411 0 : next[0] = NAT_NEXT_DROP;
1412 0 : b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED];
1413 0 : goto trace0;
1414 : }
1415 :
1416 2 : vlib_increment_simple_counter (&sm->counters.slowpath.in2out.other,
1417 : thread_index, cntr_sw_if_index0, 1);
1418 2 : goto trace0;
1419 : }
1420 :
1421 28437 : if (PREDICT_FALSE (proto0 == IP_PROTOCOL_ICMP))
1422 : {
1423 13136 : next[0] = icmp_in2out_ed_slow_path (
1424 : sm, b0, ip0, icmp0, rx_sw_if_index0, tx_sw_if_index0,
1425 6568 : rx_fib_index0, node, next[0], now, thread_index, &s0,
1426 : is_multi_worker);
1427 6568 : if (NAT_NEXT_DROP != next[0] && s0 &&
1428 : NAT_ED_TRNSL_ERR_SUCCESS !=
1429 6565 : (translation_error = nat_6t_flow_buf_translate_i2o (
1430 6565 : vm, sm, b0, ip0, &s0->i2o, proto0, is_output_feature)))
1431 : {
1432 0 : nat44_ed_free_session_data (sm, s0, thread_index, 0);
1433 0 : nat_ed_session_delete (sm, s0, thread_index, 1);
1434 0 : s0 = 0;
1435 0 : next[0] = NAT_NEXT_DROP;
1436 0 : b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED];
1437 0 : goto trace0;
1438 : }
1439 :
1440 6568 : if (NAT_NEXT_DROP != next[0])
1441 : {
1442 6567 : vlib_increment_simple_counter (
1443 : &sm->counters.slowpath.in2out.icmp, thread_index,
1444 : cntr_sw_if_index0, 1);
1445 : }
1446 6568 : goto trace0;
1447 : }
1448 :
1449 21869 : init_ed_k (
1450 21869 : &kv0, ip0->src_address.as_u32, vnet_buffer (b0)->ip.reass.l4_src_port,
1451 21869 : ip0->dst_address.as_u32, vnet_buffer (b0)->ip.reass.l4_dst_port,
1452 21869 : rx_fib_index0, ip0->protocol);
1453 21869 : if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0))
1454 : {
1455 21 : ASSERT (thread_index == ed_value_get_thread_index (&value0));
1456 21 : s0 =
1457 21 : pool_elt_at_index (tsm->sessions,
1458 : ed_value_get_session_index (&value0));
1459 : }
1460 :
1461 21869 : if (!s0)
1462 : {
1463 21848 : if (is_output_feature)
1464 : {
1465 38 : if (PREDICT_FALSE (nat44_ed_not_translate_output_feature (
1466 : sm, b0, ip0, vnet_buffer (b0)->ip.reass.l4_src_port,
1467 : vnet_buffer (b0)->ip.reass.l4_dst_port, thread_index,
1468 : rx_sw_if_index0, tx_sw_if_index0, is_multi_worker)))
1469 22 : goto trace0;
1470 :
1471 : /*
1472 : * Send DHCP packets to the ipv4 stack, or we won't
1473 : * be able to use dhcp client on the outside interface
1474 : */
1475 16 : if (PREDICT_FALSE (
1476 : proto0 == IP_PROTOCOL_UDP &&
1477 : (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1478 : clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_server)) &&
1479 : ip0->dst_address.as_u32 == 0xffffffff))
1480 0 : goto trace0;
1481 : }
1482 : else
1483 : {
1484 21810 : if (PREDICT_FALSE (
1485 : nat44_ed_not_translate (vm, node, rx_sw_if_index0, b0, ip0,
1486 : proto0, rx_fib_index0)))
1487 21 : goto trace0;
1488 : }
1489 :
1490 21806 : next[0] =
1491 21803 : slow_path_ed (vm, sm, b0, ip0->src_address, ip0->dst_address,
1492 21803 : vnet_buffer (b0)->ip.reass.l4_src_port,
1493 21803 : vnet_buffer (b0)->ip.reass.l4_dst_port,
1494 21803 : ip0->protocol, rx_fib_index0, tx_sw_if_index0, &s0,
1495 21803 : node, next[0], thread_index, now);
1496 :
1497 21806 : if (PREDICT_FALSE (next[0] == NAT_NEXT_DROP))
1498 151 : goto trace0;
1499 :
1500 21655 : if (PREDICT_FALSE (!s0))
1501 0 : goto trace0;
1502 :
1503 : }
1504 :
1505 21676 : b0->flags |= VNET_BUFFER_F_IS_NATED;
1506 :
1507 21676 : if (NAT_ED_TRNSL_ERR_SUCCESS !=
1508 21676 : (translation_error = nat_6t_flow_buf_translate_i2o (
1509 21676 : vm, sm, b0, ip0, &s0->i2o, proto0, is_output_feature)))
1510 : {
1511 0 : nat44_ed_free_session_data (sm, s0, thread_index, 0);
1512 0 : nat_ed_session_delete (sm, s0, thread_index, 1);
1513 0 : s0 = 0;
1514 0 : next[0] = NAT_NEXT_DROP;
1515 0 : b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED];
1516 0 : goto trace0;
1517 : }
1518 :
1519 21676 : if (PREDICT_TRUE (proto0 == IP_PROTOCOL_TCP))
1520 : {
1521 1608 : vlib_increment_simple_counter (&sm->counters.slowpath.in2out.tcp,
1522 : thread_index, cntr_sw_if_index0, 1);
1523 1608 : nat44_set_tcp_session_state_i2o (
1524 1608 : sm, now, s0, vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags,
1525 : thread_index);
1526 : }
1527 : else
1528 : {
1529 20068 : vlib_increment_simple_counter (&sm->counters.slowpath.in2out.udp,
1530 : thread_index, cntr_sw_if_index0, 1);
1531 : }
1532 :
1533 : /* Accounting */
1534 21676 : nat44_session_update_counters (s0, now,
1535 : vlib_buffer_length_in_chain
1536 : (vm, b0), thread_index);
1537 : /* Per-user LRU list maintenance */
1538 21676 : nat44_session_update_lru (sm, s0, thread_index);
1539 :
1540 28440 : trace0:
1541 28440 : if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1542 : && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1543 : {
1544 : nat_in2out_ed_trace_t *t =
1545 17555 : vlib_add_trace (vm, node, b0, sizeof (*t));
1546 17551 : t->sw_if_index = rx_sw_if_index0;
1547 17551 : t->next_index = next[0];
1548 17551 : t->is_slow_path = 1;
1549 17551 : t->translation_error = translation_error;
1550 17551 : clib_memcpy (&t->search_key, &kv0, sizeof (t->search_key));
1551 :
1552 17552 : if (s0)
1553 : {
1554 17355 : t->session_index = s0 - tsm->sessions;
1555 17355 : clib_memcpy (&t->i2of, &s0->i2o, sizeof (t->i2of));
1556 17355 : clib_memcpy (&t->o2if, &s0->o2i, sizeof (t->o2if));
1557 17357 : t->translation_via_i2of = 1;
1558 17357 : t->tcp_state = s0->tcp_state;
1559 : }
1560 :
1561 : else
1562 : {
1563 197 : t->session_index = ~0;
1564 : }
1565 : }
1566 :
1567 28439 : if (next[0] == NAT_NEXT_DROP)
1568 : {
1569 152 : vlib_increment_simple_counter (&sm->counters.slowpath.in2out.drops,
1570 : thread_index, cntr_sw_if_index0, 1);
1571 : }
1572 :
1573 28439 : n_left_from--;
1574 28439 : next++;
1575 28439 : b++;
1576 : }
1577 :
1578 257 : vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1579 257 : frame->n_vectors);
1580 :
1581 257 : return frame->n_vectors;
1582 : }
1583 :
1584 2638 : VLIB_NODE_FN (nat44_ed_in2out_node) (vlib_main_t * vm,
1585 : vlib_node_runtime_t * node,
1586 : vlib_frame_t * frame)
1587 : {
1588 338 : if (snat_main.num_workers > 1)
1589 : {
1590 302 : return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 0, 1);
1591 : }
1592 : else
1593 : {
1594 36 : return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 0, 0);
1595 : }
1596 : }
1597 :
1598 58202 : VLIB_REGISTER_NODE (nat44_ed_in2out_node) = {
1599 : .name = "nat44-ed-in2out",
1600 : .vector_size = sizeof (u32),
1601 : .sibling_of = "nat-default",
1602 : .format_trace = format_nat_in2out_ed_trace,
1603 : .type = VLIB_NODE_TYPE_INTERNAL,
1604 : .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1605 : .error_strings = nat_in2out_ed_error_strings,
1606 : .runtime_data_bytes = sizeof (snat_runtime_t),
1607 : };
1608 :
1609 2327 : VLIB_NODE_FN (nat44_ed_in2out_output_node) (vlib_main_t * vm,
1610 : vlib_node_runtime_t * node,
1611 : vlib_frame_t * frame)
1612 : {
1613 27 : if (snat_main.num_workers > 1)
1614 : {
1615 15 : return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 1, 1);
1616 : }
1617 : else
1618 : {
1619 12 : return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 1, 0);
1620 : }
1621 : }
1622 :
1623 58202 : VLIB_REGISTER_NODE (nat44_ed_in2out_output_node) = {
1624 : .name = "nat44-ed-in2out-output",
1625 : .vector_size = sizeof (u32),
1626 : .sibling_of = "nat-default",
1627 : .format_trace = format_nat_in2out_ed_trace,
1628 : .type = VLIB_NODE_TYPE_INTERNAL,
1629 : .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1630 : .error_strings = nat_in2out_ed_error_strings,
1631 : .runtime_data_bytes = sizeof (snat_runtime_t),
1632 : };
1633 :
1634 2533 : VLIB_NODE_FN (nat44_ed_in2out_slowpath_node) (vlib_main_t * vm,
1635 : vlib_node_runtime_t *
1636 : node, vlib_frame_t * frame)
1637 : {
1638 233 : if (snat_main.num_workers > 1)
1639 : {
1640 221 : return nat44_ed_in2out_slow_path_node_fn_inline (vm, node, frame, 0, 1);
1641 : }
1642 : else
1643 : {
1644 12 : return nat44_ed_in2out_slow_path_node_fn_inline (vm, node, frame, 0, 0);
1645 : }
1646 : }
1647 :
1648 58202 : VLIB_REGISTER_NODE (nat44_ed_in2out_slowpath_node) = {
1649 : .name = "nat44-ed-in2out-slowpath",
1650 : .vector_size = sizeof (u32),
1651 : .sibling_of = "nat-default",
1652 : .format_trace = format_nat_in2out_ed_trace,
1653 : .type = VLIB_NODE_TYPE_INTERNAL,
1654 : .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1655 : .error_strings = nat_in2out_ed_error_strings,
1656 : .runtime_data_bytes = sizeof (snat_runtime_t),
1657 : };
1658 :
1659 2324 : VLIB_NODE_FN (nat44_ed_in2out_output_slowpath_node) (vlib_main_t * vm,
1660 : vlib_node_runtime_t
1661 : * node,
1662 : vlib_frame_t * frame)
1663 : {
1664 24 : if (snat_main.num_workers > 1)
1665 : {
1666 13 : return nat44_ed_in2out_slow_path_node_fn_inline (vm, node, frame, 1, 1);
1667 : }
1668 : else
1669 : {
1670 11 : return nat44_ed_in2out_slow_path_node_fn_inline (vm, node, frame, 1, 0);
1671 : }
1672 : }
1673 :
1674 58202 : VLIB_REGISTER_NODE (nat44_ed_in2out_output_slowpath_node) = {
1675 : .name = "nat44-ed-in2out-output-slowpath",
1676 : .vector_size = sizeof (u32),
1677 : .sibling_of = "nat-default",
1678 : .format_trace = format_nat_in2out_ed_trace,
1679 : .type = VLIB_NODE_TYPE_INTERNAL,
1680 : .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1681 : .error_strings = nat_in2out_ed_error_strings,
1682 : .runtime_data_bytes = sizeof (snat_runtime_t),
1683 : };
1684 :
1685 : static u8 *
1686 141 : format_nat_pre_trace (u8 * s, va_list * args)
1687 : {
1688 141 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1689 141 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1690 141 : nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *);
1691 141 : return format (s, "in2out next_index %d arc_next_index %d", t->next_index,
1692 : t->arc_next_index);
1693 : }
1694 :
1695 2318 : VLIB_NODE_FN (nat_pre_in2out_node)
1696 : (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1697 : {
1698 18 : return nat_pre_node_fn_inline (vm, node, frame,
1699 : NAT_NEXT_IN2OUT_ED_FAST_PATH);
1700 : }
1701 :
1702 2312 : VLIB_NODE_FN (nat_pre_in2out_output_node)
1703 : (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1704 : {
1705 12 : return nat_pre_node_fn_inline (vm, node, frame,
1706 : NAT_NEXT_IN2OUT_ED_OUTPUT_FAST_PATH);
1707 : }
1708 :
1709 58202 : VLIB_REGISTER_NODE (nat_pre_in2out_node) = {
1710 : .name = "nat-pre-in2out",
1711 : .vector_size = sizeof (u32),
1712 : .sibling_of = "nat-default",
1713 : .format_trace = format_nat_pre_trace,
1714 : .type = VLIB_NODE_TYPE_INTERNAL,
1715 : .n_errors = 0,
1716 : };
1717 :
1718 58202 : VLIB_REGISTER_NODE (nat_pre_in2out_output_node) = {
1719 : .name = "nat-pre-in2out-output",
1720 : .vector_size = sizeof (u32),
1721 : .sibling_of = "nat-default",
1722 : .format_trace = format_nat_pre_trace,
1723 : .type = VLIB_NODE_TYPE_INTERNAL,
1724 : .n_errors = 0,
1725 : };
1726 :
1727 : /*
1728 : * fd.io coding-style-patch-verification: ON
1729 : *
1730 : * Local Variables:
1731 : * eval: (c-set-style "gnu")
1732 : * End:
1733 : */
|