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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @brief NAT44 endpoint-dependent inside to outside network translation
20 #include <vlib/vlib.h>
21 #include <vnet/vnet.h>
22 #include <vnet/pg/pg.h>
23 #include <vnet/ip/ip.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vnet/fib/ip4_fib.h>
26 #include <vnet/udp/udp.h>
27 #include <vppinfra/error.h>
29 #include <nat/nat_ipfix_logging.h>
30 #include <nat/nat_inlines.h>
31 #include <nat/nat44/inlines.h>
32 #include <nat/nat_syslog.h>
33 #include <nat/nat_ha.h>
35 static char *nat_in2out_ed_error_strings[] = {
36 #define _(sym,string) string,
37 foreach_nat_in2out_ed_error
47 } nat_in2out_ed_trace_t;
50 format_nat_in2out_ed_trace (u8 * s, va_list * args)
52 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
53 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
54 nat_in2out_ed_trace_t *t = va_arg (*args, nat_in2out_ed_trace_t *);
58 t->is_slow_path ? "NAT44_IN2OUT_ED_SLOW_PATH" :
59 "NAT44_IN2OUT_ED_FAST_PATH";
61 s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag,
62 t->sw_if_index, t->next_index, t->session_index);
67 #ifndef CLIB_MARCH_VARIANT
69 nat44_i2o_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg)
71 snat_main_t *sm = &snat_main;
72 nat44_is_idle_session_ctx_t *ctx = arg;
74 u64 sess_timeout_time;
75 nat_ed_ses_key_t ed_key;
76 clib_bihash_kv_16_8_t ed_kv;
79 snat_session_key_t key;
80 snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data,
83 s = pool_elt_at_index (tsm->sessions, kv->value);
84 sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
85 if (ctx->now >= sess_timeout_time)
87 if (is_fwd_bypass_session (s))
90 ed_key.l_addr = s->out2in.addr;
91 ed_key.r_addr = s->ext_host_addr;
92 ed_key.fib_index = s->out2in.fib_index;
93 if (snat_is_unk_proto_session (s))
95 ed_key.proto = s->in2out.port;
101 ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
102 ed_key.l_port = s->out2in.port;
103 ed_key.r_port = s->ext_host_port;
105 ed_kv.key[0] = ed_key.as_u64[0];
106 ed_kv.key[1] = ed_key.as_u64[1];
107 if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
108 nat_elog_warn ("out2in_ed key del failed");
110 if (snat_is_unk_proto_session (s))
113 snat_ipfix_logging_nat44_ses_delete (ctx->thread_index,
114 s->in2out.addr.as_u32,
115 s->out2in.addr.as_u32,
119 s->in2out.fib_index);
121 nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
122 &s->in2out.addr, s->in2out.port,
123 &s->ext_host_nat_addr, s->ext_host_nat_port,
124 &s->out2in.addr, s->out2in.port,
125 &s->ext_host_addr, s->ext_host_port,
126 s->in2out.protocol, is_twice_nat_session (s));
128 nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
129 s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
132 if (is_twice_nat_session (s))
134 for (i = 0; i < vec_len (sm->twice_nat_addresses); i++)
136 key.protocol = s->in2out.protocol;
137 key.port = s->ext_host_nat_port;
138 a = sm->twice_nat_addresses + i;
139 if (a->addr.as_u32 == s->ext_host_nat_addr.as_u32)
141 snat_free_outside_address_and_port (sm->twice_nat_addresses,
149 if (snat_is_session_static (s))
152 snat_free_outside_address_and_port (sm->addresses, ctx->thread_index,
155 nat44_delete_session (sm, s, ctx->thread_index);
164 icmp_in2out_ed_slow_path (snat_main_t * sm, vlib_buffer_t * b0,
165 ip4_header_t * ip0, icmp46_header_t * icmp0,
166 u32 sw_if_index0, u32 rx_fib_index0,
167 vlib_node_runtime_t * node, u32 next0, f64 now,
168 u32 thread_index, snat_session_t ** p_s0)
170 next0 = icmp_in2out (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
171 next0, thread_index, p_s0, 0);
172 snat_session_t *s0 = *p_s0;
173 if (PREDICT_TRUE (next0 != NAT_NEXT_DROP && s0))
176 nat44_session_update_counters (s0, now,
177 vlib_buffer_length_in_chain
178 (sm->vlib_main, b0), thread_index);
179 /* Per-user LRU list maintenance */
180 nat44_session_update_lru (sm, s0, thread_index);
186 slow_path_ed (snat_main_t * sm,
189 clib_bihash_kv_16_8_t * kv,
190 snat_session_t ** sessionp,
191 vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now)
193 snat_session_t *s = 0;
195 snat_session_key_t key0, key1;
196 lb_nat_type_t lb = 0, is_sm = 0;
197 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
198 nat_ed_ses_key_t *key = (nat_ed_ses_key_t *) kv->key;
199 u32 proto = ip_proto_to_snat_proto (key->proto);
200 nat_outside_fib_t *outside_fib;
201 fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
204 .fp_proto = FIB_PROTOCOL_IP4,
207 .ip4.as_u32 = key->r_addr.as_u32,
210 nat44_is_idle_session_ctx_t ctx;
214 if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index)))
217 (!(cleared = nat44_users_cleanup (thread_index, now))))
219 b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
220 nat_ipfix_logging_max_sessions (thread_index, sm->max_translations);
221 nat_elog_notice ("maximum sessions exceeded");
222 return NAT_NEXT_DROP;
226 key0.addr = key->l_addr;
227 key0.port = key->l_port;
228 key1.protocol = key0.protocol = proto;
229 key0.fib_index = rx_fib_index;
230 key1.fib_index = sm->outside_fib_index;
232 /* First try to match static mapping by local address and port */
233 if (snat_static_mapping_match
234 (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat))
236 /* Try to create dynamic translation */
237 if (snat_alloc_outside_address_and_port (sm->addresses, rx_fib_index,
240 tsm->snat_thread_index))
242 if (cleared || !nat44_out_of_ports_cleanup (thread_index, now) ||
243 snat_alloc_outside_address_and_port (sm->addresses,
244 rx_fib_index, thread_index,
245 &key1, sm->port_per_thread,
246 tsm->snat_thread_index))
248 nat_elog_notice ("addresses exhausted");
249 b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
250 return NAT_NEXT_DROP;
256 if (PREDICT_FALSE (identity_nat))
264 if (PREDICT_TRUE (proto == SNAT_PROTOCOL_TCP))
268 (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
270 b->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN];
272 snat_free_outside_address_and_port (sm->addresses,
273 thread_index, &key1);
274 return NAT_NEXT_DROP;
278 u = nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index);
281 nat_elog_warn ("create NAT user failed");
283 snat_free_outside_address_and_port (sm->addresses,
284 thread_index, &key1);
285 return NAT_NEXT_DROP;
288 s = nat_ed_session_alloc (sm, u, thread_index, now);
291 nat44_delete_user_with_no_session (sm, u, thread_index);
292 nat_elog_warn ("create NAT session failed");
294 snat_free_outside_address_and_port (sm->addresses,
295 thread_index, &key1);
296 return NAT_NEXT_DROP;
299 user_session_increment (sm, u, is_sm);
301 s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
303 s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING;
304 s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
305 s->ext_host_addr = key->r_addr;
306 s->ext_host_port = key->r_port;
309 s->out2in.protocol = key0.protocol;
311 switch (vec_len (sm->outside_fibs))
314 s->out2in.fib_index = sm->outside_fib_index;
317 s->out2in.fib_index = sm->outside_fibs[0].fib_index;
321 vec_foreach (outside_fib, sm->outside_fibs)
323 fei = fib_table_lookup (outside_fib->fib_index, &pfx);
324 if (FIB_NODE_INDEX_INVALID != fei)
326 if (fib_entry_get_resolving_interface (fei) != ~0)
328 s->out2in.fib_index = outside_fib->fib_index;
337 /* Add to lookup tables */
338 kv->value = s - tsm->sessions;
340 ctx.thread_index = thread_index;
341 if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, kv,
342 nat44_i2o_ed_is_idle_session_cb,
344 nat_elog_notice ("in2out-ed key add failed");
346 make_ed_kv (kv, &key1.addr, &key->r_addr, key->proto, s->out2in.fib_index,
347 key1.port, key->r_port);
348 kv->value = s - tsm->sessions;
349 if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->out2in_ed, kv,
350 nat44_o2i_ed_is_idle_session_cb,
352 nat_elog_notice ("out2in-ed key add failed");
357 snat_ipfix_logging_nat44_ses_create (thread_index,
358 s->in2out.addr.as_u32,
359 s->out2in.addr.as_u32,
362 s->out2in.port, s->in2out.fib_index);
364 nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index,
365 &s->in2out.addr, s->in2out.port,
366 &s->ext_host_nat_addr, s->ext_host_nat_port,
367 &s->out2in.addr, s->out2in.port,
368 &s->ext_host_addr, s->ext_host_port,
369 s->in2out.protocol, 0);
371 nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
372 s->out2in.port, &s->ext_host_addr, s->ext_host_port,
373 &s->ext_host_nat_addr, s->ext_host_nat_port,
374 s->in2out.protocol, s->in2out.fib_index, s->flags,
380 static_always_inline int
381 nat44_ed_not_translate (snat_main_t * sm, vlib_node_runtime_t * node,
382 u32 sw_if_index, ip4_header_t * ip, u32 proto,
383 u32 rx_fib_index, u32 thread_index)
385 udp_header_t *udp = ip4_next_header (ip);
386 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
387 clib_bihash_kv_16_8_t kv, value;
388 snat_session_key_t key0, key1;
390 make_ed_kv (&kv, &ip->dst_address, &ip->src_address, ip->protocol,
391 sm->outside_fib_index, udp->dst_port, udp->src_port);
393 /* NAT packet aimed at external address if */
394 /* has active sessions */
395 if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
397 key0.addr = ip->dst_address;
398 key0.port = udp->dst_port;
399 key0.protocol = proto;
400 key0.fib_index = sm->outside_fib_index;
401 /* or is static mappings */
402 if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0, 0))
408 if (sm->forwarding_enabled)
411 return snat_not_translate_fast (sm, node, sw_if_index, ip, proto,
415 static_always_inline int
416 nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip,
417 u32 thread_index, f64 now,
418 vlib_main_t * vm, vlib_buffer_t * b)
420 nat_ed_ses_key_t key;
421 clib_bihash_kv_16_8_t kv, value;
422 snat_session_t *s = 0;
423 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
425 if (!sm->forwarding_enabled)
428 if (ip->protocol == IP_PROTOCOL_ICMP)
430 key.as_u64[0] = key.as_u64[1] = 0;
431 if (get_icmp_i2o_ed_key (b, ip, &key))
434 kv.key[0] = key.as_u64[0];
435 kv.key[1] = key.as_u64[1];
437 else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
439 make_ed_kv (&kv, &ip->src_address, &ip->dst_address, ip->protocol, 0,
440 vnet_buffer (b)->ip.reass.l4_src_port,
441 vnet_buffer (b)->ip.reass.l4_dst_port);
445 make_ed_kv (&kv, &ip->src_address, &ip->dst_address, ip->protocol, 0, 0,
449 if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
451 s = pool_elt_at_index (tsm->sessions, value.value);
452 if (is_fwd_bypass_session (s))
454 if (ip->protocol == IP_PROTOCOL_TCP)
456 if (nat44_set_tcp_session_state_i2o (sm, s, b, thread_index))
460 nat44_session_update_counters (s, now,
461 vlib_buffer_length_in_chain (vm, b),
463 /* Per-user LRU list maintenance */
464 nat44_session_update_lru (sm, s, thread_index);
474 static_always_inline int
475 nat44_ed_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip,
476 u8 proto, u16 src_port, u16 dst_port,
477 u32 thread_index, u32 rx_sw_if_index,
480 clib_bihash_kv_16_8_t kv, value;
481 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
484 u32 rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (rx_sw_if_index);
485 u32 tx_fib_index = ip4_fib_table_get_index_for_sw_if_index (tx_sw_if_index);
488 make_ed_kv (&kv, &ip->src_address, &ip->dst_address, proto, tx_fib_index,
490 if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
492 s = pool_elt_at_index (tsm->sessions, value.value);
493 if (nat44_is_ses_closed (s))
495 nat_free_session_data (sm, s, thread_index, 0);
496 nat44_delete_session (sm, s, thread_index);
499 s->flags |= SNAT_SESSION_FLAG_OUTPUT_FEATURE;
504 make_ed_kv (&kv, &ip->dst_address, &ip->src_address, proto, rx_fib_index,
506 if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
508 s = pool_elt_at_index (tsm->sessions, value.value);
509 if (is_fwd_bypass_session (s))
514 pool_foreach (i, sm->output_feature_interfaces,
516 if ((nat_interface_is_inside (i)) && (rx_sw_if_index == i->sw_if_index))
526 #ifndef CLIB_MARCH_VARIANT
528 icmp_match_in2out_ed (snat_main_t * sm, vlib_node_runtime_t * node,
529 u32 thread_index, vlib_buffer_t * b, ip4_header_t * ip,
530 u8 * p_proto, snat_session_key_t * p_value,
531 u8 * p_dont_translate, void *d, void *e)
535 nat_ed_ses_key_t key;
536 snat_session_t *s = 0;
537 u8 dont_translate = 0;
538 clib_bihash_kv_16_8_t kv, value;
541 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
543 sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
544 rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
546 key.as_u64[0] = key.as_u64[1] = 0;
547 err = get_icmp_i2o_ed_key (b, ip, &key);
550 b->error = node->errors[err];
551 next = NAT_NEXT_DROP;
554 key.fib_index = rx_fib_index;
556 kv.key[0] = key.as_u64[0];
557 kv.key[1] = key.as_u64[1];
559 if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
561 if (vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0)
564 (nat44_ed_not_translate_output_feature
565 (sm, ip, key.proto, key.l_port, key.r_port, thread_index,
566 sw_if_index, vnet_buffer (b)->sw_if_index[VLIB_TX])))
574 if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index,
575 ip, SNAT_PROTOCOL_ICMP,
585 (icmp_type_is_error_message
586 (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
588 b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
589 next = NAT_NEXT_DROP;
593 next = slow_path_ed (sm, b, rx_fib_index, &kv, &s, node, next,
594 thread_index, vlib_time_now (sm->vlib_main));
596 if (PREDICT_FALSE (next == NAT_NEXT_DROP))
608 (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
610 && vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
612 && !icmp_type_is_error_message (vnet_buffer (b)->ip.
613 reass.icmp_type_or_tcp_flags)))
615 b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
616 next = NAT_NEXT_DROP;
620 s = pool_elt_at_index (tsm->sessions, value.value);
623 *p_proto = ip_proto_to_snat_proto (key.proto);
626 *p_value = s->out2in;
627 *p_dont_translate = dont_translate;
629 *(snat_session_t **) d = s;
634 static snat_session_t *
635 nat44_ed_in2out_unknown_proto (snat_main_t * sm,
641 vlib_main_t * vm, vlib_node_runtime_t * node)
643 clib_bihash_kv_8_8_t kv, value;
644 clib_bihash_kv_16_8_t s_kv, s_value;
645 snat_static_mapping_t *m;
646 u32 old_addr, new_addr = 0;
649 dlist_elt_t *head, *elt;
650 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
651 u32 elt_index, head_index, ses_index;
653 u32 outside_fib_index = sm->outside_fib_index;
656 nat_outside_fib_t *outside_fib;
657 fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
659 .fp_proto = FIB_PROTOCOL_IP4,
662 .ip4.as_u32 = ip->dst_address.as_u32,
666 switch (vec_len (sm->outside_fibs))
669 outside_fib_index = sm->outside_fib_index;
672 outside_fib_index = sm->outside_fibs[0].fib_index;
676 vec_foreach (outside_fib, sm->outside_fibs)
678 fei = fib_table_lookup (outside_fib->fib_index, &pfx);
679 if (FIB_NODE_INDEX_INVALID != fei)
681 if (fib_entry_get_resolving_interface (fei) != ~0)
683 outside_fib_index = outside_fib->fib_index;
691 old_addr = ip->src_address.as_u32;
693 make_ed_kv (&s_kv, &ip->src_address, &ip->dst_address, ip->protocol,
696 if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &s_kv, &s_value))
698 s = pool_elt_at_index (tsm->sessions, s_value.value);
699 new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
703 if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index)))
705 b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
706 nat_ipfix_logging_max_sessions (thread_index, sm->max_translations);
707 nat_elog_notice ("maximum sessions exceeded");
711 u = nat_user_get_or_create (sm, &ip->src_address, rx_fib_index,
715 nat_elog_warn ("create NAT user failed");
719 make_sm_kv (&kv, &ip->src_address, 0, rx_fib_index, 0);
721 /* Try to find static mapping first */
722 if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value))
724 m = pool_elt_at_index (sm->static_mappings, value.value);
725 new_addr = ip->src_address.as_u32 = m->external_addr.as_u32;
729 /* Fallback to 3-tuple key */
732 /* Choose same out address as for TCP/UDP session to same destination */
733 head_index = u->sessions_per_user_list_head_index;
734 head = pool_elt_at_index (tsm->list_pool, head_index);
735 elt_index = head->next;
736 if (PREDICT_FALSE (elt_index == ~0))
740 elt = pool_elt_at_index (tsm->list_pool, elt_index);
741 ses_index = elt->value;
744 while (ses_index != ~0)
746 s = pool_elt_at_index (tsm->sessions, ses_index);
747 elt_index = elt->next;
748 elt = pool_elt_at_index (tsm->list_pool, elt_index);
749 ses_index = elt->value;
751 if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
753 new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
755 make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address,
756 ip->protocol, outside_fib_index, 0, 0);
757 if (clib_bihash_search_16_8
758 (&tsm->out2in_ed, &s_kv, &s_value))
765 for (i = 0; i < vec_len (sm->addresses); i++)
767 make_ed_kv (&s_kv, &sm->addresses[i].addr, &ip->dst_address,
768 ip->protocol, outside_fib_index, 0, 0);
769 if (clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
771 new_addr = ip->src_address.as_u32 =
772 sm->addresses[i].addr.as_u32;
780 s = nat_ed_session_alloc (sm, u, thread_index, now);
783 nat44_delete_user_with_no_session (sm, u, thread_index);
784 nat_elog_warn ("create NAT session failed");
788 s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
789 s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO;
790 s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
791 s->out2in.addr.as_u32 = new_addr;
792 s->out2in.fib_index = outside_fib_index;
793 s->in2out.addr.as_u32 = old_addr;
794 s->in2out.fib_index = rx_fib_index;
795 s->in2out.port = s->out2in.port = ip->protocol;
797 s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
798 user_session_increment (sm, u, is_sm);
800 /* Add to lookup tables */
801 make_ed_kv (&s_kv, &s->in2out.addr, &ip->dst_address, ip->protocol,
803 s_kv.value = s - tsm->sessions;
804 if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
805 nat_elog_notice ("in2out key add failed");
807 make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address, ip->protocol,
808 outside_fib_index, 0, 0);
809 s_kv.value = s - tsm->sessions;
810 if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1))
811 nat_elog_notice ("out2in key add failed");
814 /* Update IP checksum */
816 sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, src_address);
817 ip->checksum = ip_csum_fold (sum);
820 nat44_session_update_counters (s, now, vlib_buffer_length_in_chain (vm, b),
822 /* Per-user LRU list maintenance */
823 nat44_session_update_lru (sm, s, thread_index);
826 if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
827 nat44_ed_hairpinning_unknown_proto (sm, b, ip);
829 if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
830 vnet_buffer (b)->sw_if_index[VLIB_TX] = outside_fib_index;
836 nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t * vm,
837 vlib_node_runtime_t * node,
838 vlib_frame_t * frame,
839 int is_output_feature)
841 u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
842 nat_next_t next_index;
843 snat_main_t *sm = &snat_main;
844 f64 now = vlib_time_now (vm);
845 u32 thread_index = vm->thread_index;
846 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
847 u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
850 def_slow = is_output_feature ? NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH :
851 NAT_NEXT_IN2OUT_ED_SLOW_PATH;
853 stats_node_index = sm->ed_in2out_node_index;
855 from = vlib_frame_vector_args (frame);
856 n_left_from = frame->n_vectors;
857 next_index = node->cached_next_index;
859 while (n_left_from > 0)
863 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
865 while (n_left_from > 0 && n_left_to_next > 0)
869 u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
870 new_addr0, old_addr0;
871 u16 old_port0, new_port0;
875 snat_session_t *s0 = 0;
876 clib_bihash_kv_16_8_t kv0, value0;
879 /* speculatively enqueue b0 to the current next frame */
887 b0 = vlib_get_buffer (vm, bi0);
889 if (is_output_feature)
891 vnet_feature_next (&nat_buffer_opaque (b0)->arc_next, b0);
892 iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
895 next0 = nat_buffer_opaque (b0)->arc_next;
897 ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
900 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
902 fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
905 if (PREDICT_FALSE (ip0->ttl == 1))
907 vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
908 icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
909 ICMP4_time_exceeded_ttl_exceeded_in_transit,
911 next0 = NAT_NEXT_ICMP_ERROR;
915 udp0 = ip4_next_header (ip0);
916 tcp0 = (tcp_header_t *) udp0;
917 proto0 = ip_proto_to_snat_proto (ip0->protocol);
919 if (PREDICT_FALSE (proto0 == ~0))
925 if (is_output_feature)
927 if (PREDICT_FALSE (nat_not_translate_output_feature_fwd
928 (sm, ip0, thread_index, now, vm, b0)))
932 if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
938 make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
939 ip0->protocol, rx_fib_index0,
940 vnet_buffer (b0)->ip.reass.l4_src_port,
941 vnet_buffer (b0)->ip.reass.l4_dst_port);
943 // lookup for session
944 if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
946 // session does not exist go slow path
950 s0 = pool_elt_at_index (tsm->sessions, value0.value);
952 // drop if session expired
953 u64 sess_timeout_time;
954 sess_timeout_time = s0->last_heard +
955 (f64) nat44_session_get_timeout (sm, s0);
956 if (now >= sess_timeout_time)
959 nat_free_session_data (sm, s0, thread_index, 0);
960 nat44_delete_session (sm, s0, thread_index);
962 next0 = NAT_NEXT_DROP;
967 b0->flags |= VNET_BUFFER_F_IS_NATED;
969 if (!is_output_feature)
970 vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
972 old_addr0 = ip0->src_address.as_u32;
973 new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
974 sum0 = ip0->checksum;
975 sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
977 if (PREDICT_FALSE (is_twice_nat_session (s0)))
978 sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
979 s0->ext_host_addr.as_u32, ip4_header_t,
981 ip0->checksum = ip_csum_fold (sum0);
983 old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
985 if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
987 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
989 new_port0 = udp0->src_port = s0->out2in.port;
990 sum0 = tcp0->checksum;
992 ip_csum_update (sum0, old_addr0, new_addr0,
993 ip4_header_t, dst_address);
995 ip_csum_update (sum0, old_port0, new_port0,
996 ip4_header_t, length);
997 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1000 ip_csum_update (sum0, ip0->dst_address.as_u32,
1001 s0->ext_host_addr.as_u32,
1002 ip4_header_t, dst_address);
1004 ip_csum_update (sum0,
1005 vnet_buffer (b0)->ip.
1006 reass.l4_dst_port, s0->ext_host_port,
1007 ip4_header_t, length);
1008 tcp0->dst_port = s0->ext_host_port;
1009 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1011 mss_clamping (sm, tcp0, &sum0);
1012 tcp0->checksum = ip_csum_fold (sum0);
1015 if (nat44_set_tcp_session_state_i2o (sm, s0, b0, thread_index))
1018 else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1021 new_port0 = udp0->src_port = s0->out2in.port;
1022 sum0 = udp0->checksum;
1024 ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1027 ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1029 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1031 sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1032 s0->ext_host_addr.as_u32,
1033 ip4_header_t, dst_address);
1035 ip_csum_update (sum0,
1036 vnet_buffer (b0)->ip.reass.l4_dst_port,
1037 s0->ext_host_port, ip4_header_t, length);
1038 udp0->dst_port = s0->ext_host_port;
1039 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1041 udp0->checksum = ip_csum_fold (sum0);
1046 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1048 new_port0 = udp0->src_port = s0->out2in.port;
1049 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1051 udp0->dst_port = s0->ext_host_port;
1052 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1059 nat44_session_update_counters (s0, now,
1060 vlib_buffer_length_in_chain
1061 (vm, b0), thread_index);
1062 /* Per-user LRU list maintenance */
1063 nat44_session_update_lru (sm, s0, thread_index);
1066 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1067 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1069 nat_in2out_ed_trace_t *t =
1070 vlib_add_trace (vm, node, b0, sizeof (*t));
1071 t->sw_if_index = sw_if_index0;
1072 t->next_index = next0;
1073 t->is_slow_path = 0;
1076 t->session_index = s0 - tsm->sessions;
1078 t->session_index = ~0;
1081 pkts_processed += next0 == nat_buffer_opaque (b0)->arc_next;
1082 /* verify speculative enqueue, maybe switch current next frame */
1083 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1084 to_next, n_left_to_next,
1088 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1091 vlib_node_increment_counter (vm, stats_node_index,
1092 NAT_IN2OUT_ED_ERROR_IN2OUT_PACKETS,
1094 vlib_node_increment_counter (vm, stats_node_index,
1095 NAT_IN2OUT_ED_ERROR_TCP_PACKETS, tcp_packets);
1096 vlib_node_increment_counter (vm, stats_node_index,
1097 NAT_IN2OUT_ED_ERROR_UDP_PACKETS, udp_packets);
1098 vlib_node_increment_counter (vm, stats_node_index,
1099 NAT_IN2OUT_ED_ERROR_ICMP_PACKETS,
1101 vlib_node_increment_counter (vm, stats_node_index,
1102 NAT_IN2OUT_ED_ERROR_OTHER_PACKETS,
1104 return frame->n_vectors;
1108 nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
1109 vlib_node_runtime_t * node,
1110 vlib_frame_t * frame,
1111 int is_output_feature)
1113 u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
1114 nat_next_t next_index;
1115 snat_main_t *sm = &snat_main;
1116 f64 now = vlib_time_now (vm);
1117 u32 thread_index = vm->thread_index;
1118 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
1119 u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets = 0;
1121 stats_node_index = sm->ed_in2out_slowpath_node_index;
1123 from = vlib_frame_vector_args (frame);
1124 n_left_from = frame->n_vectors;
1125 next_index = node->cached_next_index;
1127 while (n_left_from > 0)
1131 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1133 while (n_left_from > 0 && n_left_to_next > 0)
1137 u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
1138 new_addr0, old_addr0;
1139 u16 old_port0, new_port0;
1143 icmp46_header_t *icmp0;
1144 snat_session_t *s0 = 0;
1145 clib_bihash_kv_16_8_t kv0, value0;
1148 /* speculatively enqueue b0 to the current next frame */
1154 n_left_to_next -= 1;
1156 b0 = vlib_get_buffer (vm, bi0);
1158 if (is_output_feature)
1159 iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
1161 next0 = nat_buffer_opaque (b0)->arc_next;
1163 ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
1166 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1168 fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
1171 if (PREDICT_FALSE (ip0->ttl == 1))
1173 vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1174 icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1175 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1177 next0 = NAT_NEXT_ICMP_ERROR;
1181 udp0 = ip4_next_header (ip0);
1182 tcp0 = (tcp_header_t *) udp0;
1183 icmp0 = (icmp46_header_t *) udp0;
1184 proto0 = ip_proto_to_snat_proto (ip0->protocol);
1186 if (PREDICT_FALSE (proto0 == ~0))
1188 s0 = nat44_ed_in2out_unknown_proto (sm, b0, ip0,
1193 next0 = NAT_NEXT_DROP;
1199 if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1201 next0 = icmp_in2out_ed_slow_path
1202 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
1203 node, next0, now, thread_index, &s0);
1209 make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
1210 ip0->protocol, rx_fib_index0,
1211 vnet_buffer (b0)->ip.reass.l4_src_port,
1212 vnet_buffer (b0)->ip.reass.l4_dst_port);
1214 if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1217 if (is_output_feature)
1220 (nat44_ed_not_translate_output_feature
1221 (sm, ip0, ip0->protocol,
1222 vnet_buffer (b0)->ip.reass.l4_src_port,
1223 vnet_buffer (b0)->ip.reass.l4_dst_port,
1224 thread_index, sw_if_index0,
1225 vnet_buffer (b0)->sw_if_index[VLIB_TX])))
1229 * Send DHCP packets to the ipv4 stack, or we won't
1230 * be able to use dhcp client on the outside interface
1233 (proto0 == SNAT_PROTOCOL_UDP
1234 && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1235 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_server))
1236 && ip0->dst_address.as_u32 == 0xffffffff))
1242 (nat44_ed_not_translate
1243 (sm, node, sw_if_index0, ip0, proto0, rx_fib_index0,
1248 next0 = slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
1249 next0, thread_index, now);
1251 if (PREDICT_FALSE (next0 == NAT_NEXT_DROP))
1254 if (PREDICT_FALSE (!s0))
1260 s0 = pool_elt_at_index (tsm->sessions, value0.value);
1264 b0->flags |= VNET_BUFFER_F_IS_NATED;
1266 if (!is_output_feature)
1267 vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1269 old_addr0 = ip0->src_address.as_u32;
1270 new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1271 sum0 = ip0->checksum;
1272 sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1274 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1275 sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1276 s0->ext_host_addr.as_u32, ip4_header_t,
1278 ip0->checksum = ip_csum_fold (sum0);
1280 old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1282 if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1284 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1286 new_port0 = udp0->src_port = s0->out2in.port;
1287 sum0 = tcp0->checksum;
1289 ip_csum_update (sum0, old_addr0, new_addr0,
1290 ip4_header_t, dst_address);
1292 ip_csum_update (sum0, old_port0, new_port0,
1293 ip4_header_t, length);
1294 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1297 ip_csum_update (sum0, ip0->dst_address.as_u32,
1298 s0->ext_host_addr.as_u32,
1299 ip4_header_t, dst_address);
1301 ip_csum_update (sum0,
1302 vnet_buffer (b0)->ip.
1303 reass.l4_dst_port, s0->ext_host_port,
1304 ip4_header_t, length);
1305 tcp0->dst_port = s0->ext_host_port;
1306 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1308 mss_clamping (sm, tcp0, &sum0);
1309 tcp0->checksum = ip_csum_fold (sum0);
1312 if (nat44_set_tcp_session_state_i2o (sm, s0, b0, thread_index))
1315 else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1318 new_port0 = udp0->src_port = s0->out2in.port;
1319 sum0 = udp0->checksum;
1321 ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1324 ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1326 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1328 sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1329 s0->ext_host_addr.as_u32,
1330 ip4_header_t, dst_address);
1332 ip_csum_update (sum0,
1333 vnet_buffer (b0)->ip.reass.l4_dst_port,
1334 s0->ext_host_port, ip4_header_t, length);
1335 udp0->dst_port = s0->ext_host_port;
1336 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1338 udp0->checksum = ip_csum_fold (sum0);
1343 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1345 new_port0 = udp0->src_port = s0->out2in.port;
1346 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1348 udp0->dst_port = s0->ext_host_port;
1349 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1356 nat44_session_update_counters (s0, now,
1357 vlib_buffer_length_in_chain
1358 (vm, b0), thread_index);
1359 /* Per-user LRU list maintenance */
1360 nat44_session_update_lru (sm, s0, thread_index);
1363 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1364 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1366 nat_in2out_ed_trace_t *t =
1367 vlib_add_trace (vm, node, b0, sizeof (*t));
1368 t->sw_if_index = sw_if_index0;
1369 t->next_index = next0;
1370 t->is_slow_path = 1;
1373 t->session_index = s0 - tsm->sessions;
1375 t->session_index = ~0;
1378 pkts_processed += next0 == nat_buffer_opaque (b0)->arc_next;
1380 /* verify speculative enqueue, maybe switch current next frame */
1381 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1382 to_next, n_left_to_next,
1386 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1389 vlib_node_increment_counter (vm, stats_node_index,
1390 NAT_IN2OUT_ED_ERROR_IN2OUT_PACKETS,
1392 vlib_node_increment_counter (vm, stats_node_index,
1393 NAT_IN2OUT_ED_ERROR_TCP_PACKETS, tcp_packets);
1394 vlib_node_increment_counter (vm, stats_node_index,
1395 NAT_IN2OUT_ED_ERROR_UDP_PACKETS, udp_packets);
1396 vlib_node_increment_counter (vm, stats_node_index,
1397 NAT_IN2OUT_ED_ERROR_ICMP_PACKETS,
1399 vlib_node_increment_counter (vm, stats_node_index,
1400 NAT_IN2OUT_ED_ERROR_OTHER_PACKETS,
1402 return frame->n_vectors;
1405 VLIB_NODE_FN (nat44_ed_in2out_node) (vlib_main_t * vm,
1406 vlib_node_runtime_t * node,
1407 vlib_frame_t * frame)
1409 return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 0);
1413 VLIB_REGISTER_NODE (nat44_ed_in2out_node) = {
1414 .name = "nat44-ed-in2out",
1415 .vector_size = sizeof (u32),
1416 .sibling_of = "nat-default",
1417 .format_trace = format_nat_in2out_ed_trace,
1418 .type = VLIB_NODE_TYPE_INTERNAL,
1419 .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1420 .error_strings = nat_in2out_ed_error_strings,
1421 .runtime_data_bytes = sizeof (snat_runtime_t),
1425 VLIB_NODE_FN (nat44_ed_in2out_output_node) (vlib_main_t * vm,
1426 vlib_node_runtime_t * node,
1427 vlib_frame_t * frame)
1429 return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 1);
1433 VLIB_REGISTER_NODE (nat44_ed_in2out_output_node) = {
1434 .name = "nat44-ed-in2out-output",
1435 .vector_size = sizeof (u32),
1436 .sibling_of = "nat-default",
1437 .format_trace = format_nat_in2out_ed_trace,
1438 .type = VLIB_NODE_TYPE_INTERNAL,
1439 .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1440 .error_strings = nat_in2out_ed_error_strings,
1441 .runtime_data_bytes = sizeof (snat_runtime_t),
1445 VLIB_NODE_FN (nat44_ed_in2out_slowpath_node) (vlib_main_t * vm,
1446 vlib_node_runtime_t *
1447 node, vlib_frame_t * frame)
1449 return nat44_ed_in2out_slow_path_node_fn_inline (vm, node, frame, 0);
1453 VLIB_REGISTER_NODE (nat44_ed_in2out_slowpath_node) = {
1454 .name = "nat44-ed-in2out-slowpath",
1455 .vector_size = sizeof (u32),
1456 .sibling_of = "nat-default",
1457 .format_trace = format_nat_in2out_ed_trace,
1458 .type = VLIB_NODE_TYPE_INTERNAL,
1459 .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1460 .error_strings = nat_in2out_ed_error_strings,
1461 .runtime_data_bytes = sizeof (snat_runtime_t),
1465 VLIB_NODE_FN (nat44_ed_in2out_output_slowpath_node) (vlib_main_t * vm,
1468 vlib_frame_t * frame)
1470 return nat44_ed_in2out_slow_path_node_fn_inline (vm, node, frame, 1);
1474 VLIB_REGISTER_NODE (nat44_ed_in2out_output_slowpath_node) = {
1475 .name = "nat44-ed-in2out-output-slowpath",
1476 .vector_size = sizeof (u32),
1477 .sibling_of = "nat-default",
1478 .format_trace = format_nat_in2out_ed_trace,
1479 .type = VLIB_NODE_TYPE_INTERNAL,
1480 .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1481 .error_strings = nat_in2out_ed_error_strings,
1482 .runtime_data_bytes = sizeof (snat_runtime_t),
1487 format_nat_pre_trace (u8 * s, va_list * args)
1489 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1490 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1491 nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *);
1492 return format (s, "in2out next_index %d", t->next_index);
1495 VLIB_NODE_FN (nat_pre_in2out_node)
1496 (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1498 return nat_pre_node_fn_inline (vm, node, frame,
1499 NAT_NEXT_IN2OUT_ED_FAST_PATH);
1503 VLIB_REGISTER_NODE (nat_pre_in2out_node) = {
1504 .name = "nat-pre-in2out",
1505 .vector_size = sizeof (u32),
1506 .sibling_of = "nat-default",
1507 .format_trace = format_nat_pre_trace,
1508 .type = VLIB_NODE_TYPE_INTERNAL,
1514 * fd.io coding-style-patch-verification: ON
1517 * eval: (c-set-style "gnu")