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 ed_bihash_kv_t bihash_key;
111 clib_memset (&bihash_key, 0, sizeof (bihash_key));
112 bihash_key.k.dst_address = s->ext_host_addr.as_u32;
113 bihash_key.k.dst_port = s->ext_host_port;
114 bihash_key.k.src_address = s->out2in.addr.as_u32;
115 bihash_key.k.src_port = s->out2in.port;
116 bihash_key.k.protocol = s->out2in.protocol;
117 clib_bihash_add_del_16_8 (&sm->ed_ext_ports, &bihash_key.kv,
120 if (snat_is_unk_proto_session (s))
123 snat_ipfix_logging_nat44_ses_delete (ctx->thread_index,
124 s->in2out.addr.as_u32,
125 s->out2in.addr.as_u32,
129 s->in2out.fib_index);
131 nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
132 &s->in2out.addr, s->in2out.port,
133 &s->ext_host_nat_addr, s->ext_host_nat_port,
134 &s->out2in.addr, s->out2in.port,
135 &s->ext_host_addr, s->ext_host_port,
136 s->in2out.protocol, is_twice_nat_session (s));
138 nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
139 s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
142 if (is_twice_nat_session (s))
144 for (i = 0; i < vec_len (sm->twice_nat_addresses); i++)
146 key.protocol = s->in2out.protocol;
147 key.port = s->ext_host_nat_port;
148 a = sm->twice_nat_addresses + i;
149 if (a->addr.as_u32 == s->ext_host_nat_addr.as_u32)
151 snat_free_outside_address_and_port (sm->twice_nat_addresses,
159 if (snat_is_session_static (s))
162 snat_free_outside_address_and_port (sm->addresses, ctx->thread_index,
165 nat44_delete_session (sm, s, ctx->thread_index);
174 icmp_in2out_ed_slow_path (snat_main_t * sm, vlib_buffer_t * b0,
175 ip4_header_t * ip0, icmp46_header_t * icmp0,
176 u32 sw_if_index0, u32 rx_fib_index0,
177 vlib_node_runtime_t * node, u32 next0, f64 now,
178 u32 thread_index, snat_session_t ** p_s0)
180 next0 = icmp_in2out (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
181 next0, thread_index, p_s0, 0);
182 snat_session_t *s0 = *p_s0;
183 if (PREDICT_TRUE (next0 != NAT_NEXT_DROP && s0))
186 nat44_session_update_counters (s0, now,
187 vlib_buffer_length_in_chain
188 (sm->vlib_main, b0), thread_index);
189 /* Per-user LRU list maintenance */
190 nat44_session_update_lru (sm, s0, thread_index);
195 static_always_inline u16
196 snat_random_port (u16 min, u16 max)
198 snat_main_t *sm = &snat_main;
199 return min + random_u32 (&sm->random_seed) /
200 (random_u32_max () / (max - min + 1) + 1);
204 nat_alloc_addr_and_port_ed (snat_address_t * addresses, u32 fib_index,
205 u32 thread_index, nat_ed_ses_key_t * key,
206 snat_session_key_t * key1, u16 port_per_thread,
207 u32 snat_thread_index)
210 snat_address_t *a, *ga = 0;
213 const u16 port_thread_offset = (port_per_thread * snat_thread_index) + 1024;
214 ed_bihash_kv_t bihash_key;
215 clib_memset (&bihash_key, 0, sizeof (bihash_key));
216 bihash_key.k.dst_address = key->r_addr.as_u32;
217 bihash_key.k.dst_port = key->r_port;
218 bihash_key.k.protocol = key1->protocol;
220 for (i = 0; i < vec_len (addresses); i++)
223 switch (key1->protocol)
225 #define _(N, j, n, s) \
226 case SNAT_PROTOCOL_##N: \
227 if (a->fib_index == fib_index) \
229 bihash_key.k.src_address = a->addr.as_u32; \
230 u16 port = snat_random_port (1, port_per_thread); \
231 u16 attempts = port_per_thread; \
232 while (attempts > 0) \
235 portnum = port_thread_offset + port; \
236 bihash_key.k.src_port = clib_host_to_net_u16 (portnum); \
237 int rv = clib_bihash_add_del_16_8 ( \
238 &snat_main.ed_ext_ports, &bihash_key.kv, 2 /* is_add */); \
241 ++a->busy_##n##_port_refcounts[portnum]; \
242 a->busy_##n##_ports_per_thread[thread_index]++; \
243 a->busy_##n##_ports++; \
244 key1->addr = a->addr; \
245 key1->port = clib_host_to_net_u16 (portnum); \
248 port = (port + 1) % port_per_thread; \
251 else if (a->fib_index == ~0) \
257 foreach_snat_protocol;
259 nat_elog_info ("unknown protocol");
266 /* fake fib_index to reuse macro */
269 switch (key1->protocol)
271 foreach_snat_protocol;
273 nat_elog_info ("unknown protocol");
280 /* Totally out of translations to use... */
281 snat_ipfix_logging_addresses_exhausted (thread_index, 0);
286 slow_path_ed (snat_main_t * sm,
289 clib_bihash_kv_16_8_t * kv,
290 snat_session_t ** sessionp,
291 vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now)
293 snat_session_t *s = 0;
295 snat_session_key_t key0, key1;
296 lb_nat_type_t lb = 0, is_sm = 0;
297 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
298 nat_ed_ses_key_t *key = (nat_ed_ses_key_t *) kv->key;
299 u32 proto = ip_proto_to_snat_proto (key->proto);
300 nat_outside_fib_t *outside_fib;
301 fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
304 .fp_proto = FIB_PROTOCOL_IP4,
307 .ip4.as_u32 = key->r_addr.as_u32,
310 nat44_is_idle_session_ctx_t ctx;
312 if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index)))
314 b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
315 nat_ipfix_logging_max_sessions (thread_index, sm->max_translations);
316 nat_elog_notice ("maximum sessions exceeded");
317 return NAT_NEXT_DROP;
320 key0.addr = key->l_addr;
321 key0.port = key->l_port;
322 key1.protocol = key0.protocol = proto;
323 key0.fib_index = rx_fib_index;
324 key1.fib_index = sm->outside_fib_index;
326 /* First try to match static mapping by local address and port */
327 if (snat_static_mapping_match
328 (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat))
330 /* Try to create dynamic translation */
331 if (nat_alloc_addr_and_port_ed (sm->addresses, rx_fib_index,
332 thread_index, key, &key1,
334 tsm->snat_thread_index))
336 nat_elog_notice ("addresses exhausted");
337 b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
338 return NAT_NEXT_DROP;
343 if (PREDICT_FALSE (identity_nat))
351 if (PREDICT_TRUE (proto == SNAT_PROTOCOL_TCP))
355 (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
357 b->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN];
359 snat_free_outside_address_and_port (sm->addresses,
360 thread_index, &key1);
361 return NAT_NEXT_DROP;
365 u = nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index);
368 nat_elog_warn ("create NAT user failed");
370 snat_free_outside_address_and_port (sm->addresses,
371 thread_index, &key1);
372 b->error = node->errors[NAT_IN2OUT_ED_ERROR_CANNOT_CREATE_USER];
373 return NAT_NEXT_DROP;
376 s = nat_ed_session_alloc (sm, u, thread_index, now);
379 nat44_delete_user_with_no_session (sm, u, thread_index);
380 nat_elog_warn ("create NAT session failed");
382 snat_free_outside_address_and_port (sm->addresses,
383 thread_index, &key1);
384 b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_USER_SESS_EXCEEDED];
385 return NAT_NEXT_DROP;
388 user_session_increment (sm, u, is_sm);
390 s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
392 s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING;
393 s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
394 s->ext_host_addr = key->r_addr;
395 s->ext_host_port = key->r_port;
398 s->out2in.protocol = key0.protocol;
400 switch (vec_len (sm->outside_fibs))
403 s->out2in.fib_index = sm->outside_fib_index;
406 s->out2in.fib_index = sm->outside_fibs[0].fib_index;
410 vec_foreach (outside_fib, sm->outside_fibs)
412 fei = fib_table_lookup (outside_fib->fib_index, &pfx);
413 if (FIB_NODE_INDEX_INVALID != fei)
415 if (fib_entry_get_resolving_interface (fei) != ~0)
417 s->out2in.fib_index = outside_fib->fib_index;
426 /* Add to lookup tables */
427 kv->value = s - tsm->sessions;
429 ctx.thread_index = thread_index;
430 if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, kv,
431 nat44_i2o_ed_is_idle_session_cb,
433 nat_elog_notice ("in2out-ed key add failed");
435 make_ed_kv (kv, &key1.addr, &key->r_addr, key->proto, s->out2in.fib_index,
436 key1.port, key->r_port);
437 kv->value = s - tsm->sessions;
438 if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->out2in_ed, kv,
439 nat44_o2i_ed_is_idle_session_cb,
441 nat_elog_notice ("out2in-ed key add failed");
446 snat_ipfix_logging_nat44_ses_create (thread_index,
447 s->in2out.addr.as_u32,
448 s->out2in.addr.as_u32,
451 s->out2in.port, s->in2out.fib_index);
453 nat_syslog_nat44_sadd (s->user_index, s->in2out.fib_index,
454 &s->in2out.addr, s->in2out.port,
455 &s->ext_host_nat_addr, s->ext_host_nat_port,
456 &s->out2in.addr, s->out2in.port,
457 &s->ext_host_addr, s->ext_host_port,
458 s->in2out.protocol, 0);
460 nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
461 s->out2in.port, &s->ext_host_addr, s->ext_host_port,
462 &s->ext_host_nat_addr, s->ext_host_nat_port,
463 s->in2out.protocol, s->in2out.fib_index, s->flags,
469 static_always_inline int
470 nat44_ed_not_translate (snat_main_t * sm, vlib_node_runtime_t * node,
471 u32 sw_if_index, ip4_header_t * ip, u32 proto,
472 u32 rx_fib_index, u32 thread_index)
474 udp_header_t *udp = ip4_next_header (ip);
475 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
476 clib_bihash_kv_16_8_t kv, value;
477 snat_session_key_t key0, key1;
479 make_ed_kv (&kv, &ip->dst_address, &ip->src_address, ip->protocol,
480 sm->outside_fib_index, udp->dst_port, udp->src_port);
482 /* NAT packet aimed at external address if */
483 /* has active sessions */
484 if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
486 key0.addr = ip->dst_address;
487 key0.port = udp->dst_port;
488 key0.protocol = proto;
489 key0.fib_index = sm->outside_fib_index;
490 /* or is static mappings */
491 if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0, 0))
497 if (sm->forwarding_enabled)
500 return snat_not_translate_fast (sm, node, sw_if_index, ip, proto,
504 static_always_inline int
505 nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip,
506 u32 thread_index, f64 now,
507 vlib_main_t * vm, vlib_buffer_t * b)
509 nat_ed_ses_key_t key;
510 clib_bihash_kv_16_8_t kv, value;
511 snat_session_t *s = 0;
512 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
514 if (!sm->forwarding_enabled)
517 if (ip->protocol == IP_PROTOCOL_ICMP)
519 key.as_u64[0] = key.as_u64[1] = 0;
520 if (get_icmp_i2o_ed_key (b, ip, &key))
523 kv.key[0] = key.as_u64[0];
524 kv.key[1] = key.as_u64[1];
526 else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
528 make_ed_kv (&kv, &ip->src_address, &ip->dst_address, ip->protocol, 0,
529 vnet_buffer (b)->ip.reass.l4_src_port,
530 vnet_buffer (b)->ip.reass.l4_dst_port);
534 make_ed_kv (&kv, &ip->src_address, &ip->dst_address, ip->protocol, 0, 0,
538 if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
540 s = pool_elt_at_index (tsm->sessions, value.value);
541 if (is_fwd_bypass_session (s))
543 if (ip->protocol == IP_PROTOCOL_TCP)
545 if (nat44_set_tcp_session_state_i2o
546 (sm, now, s, b, thread_index))
550 nat44_session_update_counters (s, now,
551 vlib_buffer_length_in_chain (vm, b),
553 /* Per-user LRU list maintenance */
554 nat44_session_update_lru (sm, s, thread_index);
564 static_always_inline int
565 nat44_ed_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip,
566 u8 proto, u16 src_port, u16 dst_port,
567 u32 thread_index, u32 rx_sw_if_index,
570 clib_bihash_kv_16_8_t kv, value;
571 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
574 u32 rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (rx_sw_if_index);
575 u32 tx_fib_index = ip4_fib_table_get_index_for_sw_if_index (tx_sw_if_index);
578 make_ed_kv (&kv, &ip->src_address, &ip->dst_address, proto, tx_fib_index,
580 if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
582 s = pool_elt_at_index (tsm->sessions, value.value);
583 if (nat44_is_ses_closed (s))
585 nat_free_session_data (sm, s, thread_index, 0);
586 nat44_delete_session (sm, s, thread_index);
589 s->flags |= SNAT_SESSION_FLAG_OUTPUT_FEATURE;
594 make_ed_kv (&kv, &ip->dst_address, &ip->src_address, proto, rx_fib_index,
596 if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
598 s = pool_elt_at_index (tsm->sessions, value.value);
599 if (is_fwd_bypass_session (s))
604 pool_foreach (i, sm->output_feature_interfaces,
606 if ((nat_interface_is_inside (i)) && (rx_sw_if_index == i->sw_if_index))
616 #ifndef CLIB_MARCH_VARIANT
618 icmp_match_in2out_ed (snat_main_t * sm, vlib_node_runtime_t * node,
619 u32 thread_index, vlib_buffer_t * b, ip4_header_t * ip,
620 u8 * p_proto, snat_session_key_t * p_value,
621 u8 * p_dont_translate, void *d, void *e)
625 nat_ed_ses_key_t key;
626 snat_session_t *s = 0;
627 u8 dont_translate = 0;
628 clib_bihash_kv_16_8_t kv, value;
631 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
633 sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
634 rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
636 key.as_u64[0] = key.as_u64[1] = 0;
637 err = get_icmp_i2o_ed_key (b, ip, &key);
640 b->error = node->errors[err];
641 next = NAT_NEXT_DROP;
644 key.fib_index = rx_fib_index;
646 kv.key[0] = key.as_u64[0];
647 kv.key[1] = key.as_u64[1];
649 if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
651 if (vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0)
654 (nat44_ed_not_translate_output_feature
655 (sm, ip, key.proto, key.l_port, key.r_port, thread_index,
656 sw_if_index, vnet_buffer (b)->sw_if_index[VLIB_TX])))
664 if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index,
665 ip, SNAT_PROTOCOL_ICMP,
675 (icmp_type_is_error_message
676 (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)))
678 b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
679 next = NAT_NEXT_DROP;
683 next = slow_path_ed (sm, b, rx_fib_index, &kv, &s, node, next,
684 thread_index, vlib_time_now (sm->vlib_main));
686 if (PREDICT_FALSE (next == NAT_NEXT_DROP))
698 (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
700 && vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags !=
702 && !icmp_type_is_error_message (vnet_buffer (b)->ip.
703 reass.icmp_type_or_tcp_flags)))
705 b->error = node->errors[NAT_IN2OUT_ED_ERROR_BAD_ICMP_TYPE];
706 next = NAT_NEXT_DROP;
710 s = pool_elt_at_index (tsm->sessions, value.value);
713 *p_proto = ip_proto_to_snat_proto (key.proto);
716 *p_value = s->out2in;
717 *p_dont_translate = dont_translate;
719 *(snat_session_t **) d = s;
724 static snat_session_t *
725 nat44_ed_in2out_unknown_proto (snat_main_t * sm,
731 vlib_main_t * vm, vlib_node_runtime_t * node)
733 clib_bihash_kv_8_8_t kv, value;
734 clib_bihash_kv_16_8_t s_kv, s_value;
735 snat_static_mapping_t *m;
736 u32 old_addr, new_addr = 0;
739 dlist_elt_t *head, *elt;
740 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
741 u32 elt_index, head_index, ses_index;
743 u32 outside_fib_index = sm->outside_fib_index;
746 nat_outside_fib_t *outside_fib;
747 fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
749 .fp_proto = FIB_PROTOCOL_IP4,
752 .ip4.as_u32 = ip->dst_address.as_u32,
756 switch (vec_len (sm->outside_fibs))
759 outside_fib_index = sm->outside_fib_index;
762 outside_fib_index = sm->outside_fibs[0].fib_index;
766 vec_foreach (outside_fib, sm->outside_fibs)
768 fei = fib_table_lookup (outside_fib->fib_index, &pfx);
769 if (FIB_NODE_INDEX_INVALID != fei)
771 if (fib_entry_get_resolving_interface (fei) != ~0)
773 outside_fib_index = outside_fib->fib_index;
781 old_addr = ip->src_address.as_u32;
783 make_ed_kv (&s_kv, &ip->src_address, &ip->dst_address, ip->protocol,
786 if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &s_kv, &s_value))
788 s = pool_elt_at_index (tsm->sessions, s_value.value);
789 new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
793 if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index)))
795 b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_SESSIONS_EXCEEDED];
796 nat_ipfix_logging_max_sessions (thread_index, sm->max_translations);
797 nat_elog_notice ("maximum sessions exceeded");
801 u = nat_user_get_or_create (sm, &ip->src_address, rx_fib_index,
805 b->error = node->errors[NAT_IN2OUT_ED_ERROR_CANNOT_CREATE_USER];
806 nat_elog_warn ("create NAT user failed");
810 make_sm_kv (&kv, &ip->src_address, 0, rx_fib_index, 0);
812 /* Try to find static mapping first */
813 if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value))
815 m = pool_elt_at_index (sm->static_mappings, value.value);
816 new_addr = ip->src_address.as_u32 = m->external_addr.as_u32;
820 /* Fallback to 3-tuple key */
823 /* Choose same out address as for TCP/UDP session to same destination */
824 head_index = u->sessions_per_user_list_head_index;
825 head = pool_elt_at_index (tsm->list_pool, head_index);
826 elt_index = head->next;
827 if (PREDICT_FALSE (elt_index == ~0))
831 elt = pool_elt_at_index (tsm->list_pool, elt_index);
832 ses_index = elt->value;
835 while (ses_index != ~0)
837 s = pool_elt_at_index (tsm->sessions, ses_index);
838 elt_index = elt->next;
839 elt = pool_elt_at_index (tsm->list_pool, elt_index);
840 ses_index = elt->value;
842 if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
844 new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
846 make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address,
847 ip->protocol, outside_fib_index, 0, 0);
848 if (clib_bihash_search_16_8
849 (&tsm->out2in_ed, &s_kv, &s_value))
856 for (i = 0; i < vec_len (sm->addresses); i++)
858 make_ed_kv (&s_kv, &sm->addresses[i].addr, &ip->dst_address,
859 ip->protocol, outside_fib_index, 0, 0);
860 if (clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
862 new_addr = ip->src_address.as_u32 =
863 sm->addresses[i].addr.as_u32;
871 s = nat_ed_session_alloc (sm, u, thread_index, now);
874 b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_USER_SESS_EXCEEDED];
875 nat44_delete_user_with_no_session (sm, u, thread_index);
876 nat_elog_warn ("create NAT session failed");
880 s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
881 s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO;
882 s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
883 s->out2in.addr.as_u32 = new_addr;
884 s->out2in.fib_index = outside_fib_index;
885 s->in2out.addr.as_u32 = old_addr;
886 s->in2out.fib_index = rx_fib_index;
887 s->in2out.port = s->out2in.port = ip->protocol;
889 s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
890 user_session_increment (sm, u, is_sm);
892 /* Add to lookup tables */
893 make_ed_kv (&s_kv, &s->in2out.addr, &ip->dst_address, ip->protocol,
895 s_kv.value = s - tsm->sessions;
896 if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
897 nat_elog_notice ("in2out key add failed");
899 make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address, ip->protocol,
900 outside_fib_index, 0, 0);
901 s_kv.value = s - tsm->sessions;
902 if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1))
903 nat_elog_notice ("out2in key add failed");
906 /* Update IP checksum */
908 sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, src_address);
909 ip->checksum = ip_csum_fold (sum);
912 nat44_session_update_counters (s, now, vlib_buffer_length_in_chain (vm, b),
914 /* Per-user LRU list maintenance */
915 nat44_session_update_lru (sm, s, thread_index);
918 if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
919 nat44_ed_hairpinning_unknown_proto (sm, b, ip);
921 if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
922 vnet_buffer (b)->sw_if_index[VLIB_TX] = outside_fib_index;
928 nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t * vm,
929 vlib_node_runtime_t * node,
930 vlib_frame_t * frame,
931 int is_output_feature)
933 u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
934 nat_next_t next_index;
935 snat_main_t *sm = &snat_main;
936 f64 now = vlib_time_now (vm);
937 u32 thread_index = vm->thread_index;
938 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
939 u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
942 def_slow = is_output_feature ? NAT_NEXT_IN2OUT_ED_OUTPUT_SLOW_PATH :
943 NAT_NEXT_IN2OUT_ED_SLOW_PATH;
945 stats_node_index = sm->ed_in2out_node_index;
947 from = vlib_frame_vector_args (frame);
948 n_left_from = frame->n_vectors;
949 next_index = node->cached_next_index;
951 while (n_left_from > 0)
955 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
957 while (n_left_from > 0 && n_left_to_next > 0)
961 u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
962 new_addr0, old_addr0;
963 u16 old_port0, new_port0;
967 snat_session_t *s0 = 0;
968 clib_bihash_kv_16_8_t kv0, value0;
971 /* speculatively enqueue b0 to the current next frame */
979 b0 = vlib_get_buffer (vm, bi0);
981 if (is_output_feature)
983 vnet_feature_next (&nat_buffer_opaque (b0)->arc_next, b0);
984 iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
987 next0 = nat_buffer_opaque (b0)->arc_next;
989 ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
992 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
994 fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
997 if (PREDICT_FALSE (ip0->ttl == 1))
999 vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1000 icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1001 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1003 next0 = NAT_NEXT_ICMP_ERROR;
1007 udp0 = ip4_next_header (ip0);
1008 tcp0 = (tcp_header_t *) udp0;
1009 proto0 = ip_proto_to_snat_proto (ip0->protocol);
1011 if (PREDICT_FALSE (proto0 == ~0))
1017 if (is_output_feature)
1019 if (PREDICT_FALSE (nat_not_translate_output_feature_fwd
1020 (sm, ip0, thread_index, now, vm, b0)))
1024 if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1030 make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
1031 ip0->protocol, rx_fib_index0,
1032 vnet_buffer (b0)->ip.reass.l4_src_port,
1033 vnet_buffer (b0)->ip.reass.l4_dst_port);
1035 // lookup for session
1036 if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1038 // session does not exist go slow path
1042 s0 = pool_elt_at_index (tsm->sessions, value0.value);
1044 if (s0->tcp_close_timestamp)
1046 if (now >= s0->tcp_close_timestamp)
1048 // session is closed, go slow path
1053 // session in transitory timeout, drop
1054 b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TCP_CLOSED];
1055 next0 = NAT_NEXT_DROP;
1060 // drop if session expired
1061 u64 sess_timeout_time;
1062 sess_timeout_time = s0->last_heard +
1063 (f64) nat44_session_get_timeout (sm, s0);
1064 if (now >= sess_timeout_time)
1066 nat_free_session_data (sm, s0, thread_index, 0);
1067 nat44_delete_session (sm, s0, thread_index);
1068 // session is closed, go slow path
1073 b0->flags |= VNET_BUFFER_F_IS_NATED;
1075 if (!is_output_feature)
1076 vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1078 old_addr0 = ip0->src_address.as_u32;
1079 new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1080 sum0 = ip0->checksum;
1081 sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1083 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1084 sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1085 s0->ext_host_addr.as_u32, ip4_header_t,
1087 ip0->checksum = ip_csum_fold (sum0);
1089 old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1091 if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1093 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1095 new_port0 = udp0->src_port = s0->out2in.port;
1096 sum0 = tcp0->checksum;
1098 ip_csum_update (sum0, old_addr0, new_addr0,
1099 ip4_header_t, dst_address);
1101 ip_csum_update (sum0, old_port0, new_port0,
1102 ip4_header_t, length);
1103 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1106 ip_csum_update (sum0, ip0->dst_address.as_u32,
1107 s0->ext_host_addr.as_u32,
1108 ip4_header_t, dst_address);
1110 ip_csum_update (sum0,
1111 vnet_buffer (b0)->ip.
1112 reass.l4_dst_port, s0->ext_host_port,
1113 ip4_header_t, length);
1114 tcp0->dst_port = s0->ext_host_port;
1115 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1117 mss_clamping (sm, tcp0, &sum0);
1118 tcp0->checksum = ip_csum_fold (sum0);
1121 if (nat44_set_tcp_session_state_i2o
1122 (sm, now, s0, b0, thread_index))
1125 else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1128 new_port0 = udp0->src_port = s0->out2in.port;
1129 sum0 = udp0->checksum;
1131 ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1134 ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1136 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1138 sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1139 s0->ext_host_addr.as_u32,
1140 ip4_header_t, dst_address);
1142 ip_csum_update (sum0,
1143 vnet_buffer (b0)->ip.reass.l4_dst_port,
1144 s0->ext_host_port, ip4_header_t, length);
1145 udp0->dst_port = s0->ext_host_port;
1146 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1148 udp0->checksum = ip_csum_fold (sum0);
1153 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1155 new_port0 = udp0->src_port = s0->out2in.port;
1156 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1158 udp0->dst_port = s0->ext_host_port;
1159 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1166 nat44_session_update_counters (s0, now,
1167 vlib_buffer_length_in_chain
1168 (vm, b0), thread_index);
1169 /* Per-user LRU list maintenance */
1170 nat44_session_update_lru (sm, s0, thread_index);
1173 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1174 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1176 nat_in2out_ed_trace_t *t =
1177 vlib_add_trace (vm, node, b0, sizeof (*t));
1178 t->sw_if_index = sw_if_index0;
1179 t->next_index = next0;
1180 t->is_slow_path = 0;
1183 t->session_index = s0 - tsm->sessions;
1185 t->session_index = ~0;
1188 pkts_processed += next0 == nat_buffer_opaque (b0)->arc_next;
1189 /* verify speculative enqueue, maybe switch current next frame */
1190 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1191 to_next, n_left_to_next,
1195 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1198 vlib_node_increment_counter (vm, stats_node_index,
1199 NAT_IN2OUT_ED_ERROR_IN2OUT_PACKETS,
1201 vlib_node_increment_counter (vm, stats_node_index,
1202 NAT_IN2OUT_ED_ERROR_TCP_PACKETS, tcp_packets);
1203 vlib_node_increment_counter (vm, stats_node_index,
1204 NAT_IN2OUT_ED_ERROR_UDP_PACKETS, udp_packets);
1205 vlib_node_increment_counter (vm, stats_node_index,
1206 NAT_IN2OUT_ED_ERROR_ICMP_PACKETS,
1208 vlib_node_increment_counter (vm, stats_node_index,
1209 NAT_IN2OUT_ED_ERROR_OTHER_PACKETS,
1211 return frame->n_vectors;
1215 nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
1216 vlib_node_runtime_t * node,
1217 vlib_frame_t * frame,
1218 int is_output_feature)
1220 u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
1221 nat_next_t next_index;
1222 snat_main_t *sm = &snat_main;
1223 f64 now = vlib_time_now (vm);
1224 u32 thread_index = vm->thread_index;
1225 snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
1226 u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets = 0;
1228 stats_node_index = sm->ed_in2out_slowpath_node_index;
1230 from = vlib_frame_vector_args (frame);
1231 n_left_from = frame->n_vectors;
1232 next_index = node->cached_next_index;
1234 while (n_left_from > 0)
1238 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1240 while (n_left_from > 0 && n_left_to_next > 0)
1244 u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
1245 new_addr0, old_addr0;
1246 u16 old_port0, new_port0;
1250 icmp46_header_t *icmp0;
1251 snat_session_t *s0 = 0;
1252 clib_bihash_kv_16_8_t kv0, value0;
1255 /* speculatively enqueue b0 to the current next frame */
1261 n_left_to_next -= 1;
1263 b0 = vlib_get_buffer (vm, bi0);
1265 if (is_output_feature)
1266 iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
1268 next0 = nat_buffer_opaque (b0)->arc_next;
1270 ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
1273 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1275 fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
1278 if (PREDICT_FALSE (ip0->ttl == 1))
1280 vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1281 icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1282 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1284 next0 = NAT_NEXT_ICMP_ERROR;
1288 udp0 = ip4_next_header (ip0);
1289 tcp0 = (tcp_header_t *) udp0;
1290 icmp0 = (icmp46_header_t *) udp0;
1291 proto0 = ip_proto_to_snat_proto (ip0->protocol);
1293 if (PREDICT_FALSE (proto0 == ~0))
1295 s0 = nat44_ed_in2out_unknown_proto (sm, b0, ip0,
1300 next0 = NAT_NEXT_DROP;
1306 if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
1308 next0 = icmp_in2out_ed_slow_path
1309 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
1310 node, next0, now, thread_index, &s0);
1316 make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
1317 ip0->protocol, rx_fib_index0,
1318 vnet_buffer (b0)->ip.reass.l4_src_port,
1319 vnet_buffer (b0)->ip.reass.l4_dst_port);
1321 if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
1323 s0 = pool_elt_at_index (tsm->sessions, value0.value);
1325 if (s0->tcp_close_timestamp && now >= s0->tcp_close_timestamp)
1327 nat_free_session_data (sm, s0, thread_index, 0);
1328 nat44_delete_session (sm, s0, thread_index);
1335 if (is_output_feature)
1338 (nat44_ed_not_translate_output_feature
1339 (sm, ip0, ip0->protocol,
1340 vnet_buffer (b0)->ip.reass.l4_src_port,
1341 vnet_buffer (b0)->ip.reass.l4_dst_port,
1342 thread_index, sw_if_index0,
1343 vnet_buffer (b0)->sw_if_index[VLIB_TX])))
1347 * Send DHCP packets to the ipv4 stack, or we won't
1348 * be able to use dhcp client on the outside interface
1351 (proto0 == SNAT_PROTOCOL_UDP
1352 && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1353 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_server))
1354 && ip0->dst_address.as_u32 == 0xffffffff))
1360 (nat44_ed_not_translate
1361 (sm, node, sw_if_index0, ip0, proto0, rx_fib_index0,
1366 next0 = slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
1367 next0, thread_index, now);
1369 if (PREDICT_FALSE (next0 == NAT_NEXT_DROP))
1372 if (PREDICT_FALSE (!s0))
1377 b0->flags |= VNET_BUFFER_F_IS_NATED;
1379 if (!is_output_feature)
1380 vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1382 old_addr0 = ip0->src_address.as_u32;
1383 new_addr0 = ip0->src_address.as_u32 = s0->out2in.addr.as_u32;
1384 sum0 = ip0->checksum;
1385 sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1387 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1388 sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1389 s0->ext_host_addr.as_u32, ip4_header_t,
1391 ip0->checksum = ip_csum_fold (sum0);
1393 old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1395 if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP))
1397 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1399 new_port0 = udp0->src_port = s0->out2in.port;
1400 sum0 = tcp0->checksum;
1402 ip_csum_update (sum0, old_addr0, new_addr0,
1403 ip4_header_t, dst_address);
1405 ip_csum_update (sum0, old_port0, new_port0,
1406 ip4_header_t, length);
1407 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1410 ip_csum_update (sum0, ip0->dst_address.as_u32,
1411 s0->ext_host_addr.as_u32,
1412 ip4_header_t, dst_address);
1414 ip_csum_update (sum0,
1415 vnet_buffer (b0)->ip.
1416 reass.l4_dst_port, s0->ext_host_port,
1417 ip4_header_t, length);
1418 tcp0->dst_port = s0->ext_host_port;
1419 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1421 mss_clamping (sm, tcp0, &sum0);
1422 tcp0->checksum = ip_csum_fold (sum0);
1425 if (nat44_set_tcp_session_state_i2o
1426 (sm, now, s0, b0, thread_index))
1429 else if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment
1432 new_port0 = udp0->src_port = s0->out2in.port;
1433 sum0 = udp0->checksum;
1435 ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1438 ip_csum_update (sum0, old_port0, new_port0, ip4_header_t,
1440 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1442 sum0 = ip_csum_update (sum0, ip0->dst_address.as_u32,
1443 s0->ext_host_addr.as_u32,
1444 ip4_header_t, dst_address);
1446 ip_csum_update (sum0,
1447 vnet_buffer (b0)->ip.reass.l4_dst_port,
1448 s0->ext_host_port, ip4_header_t, length);
1449 udp0->dst_port = s0->ext_host_port;
1450 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1452 udp0->checksum = ip_csum_fold (sum0);
1457 if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1459 new_port0 = udp0->src_port = s0->out2in.port;
1460 if (PREDICT_FALSE (is_twice_nat_session (s0)))
1462 udp0->dst_port = s0->ext_host_port;
1463 ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
1470 nat44_session_update_counters (s0, now,
1471 vlib_buffer_length_in_chain
1472 (vm, b0), thread_index);
1473 /* Per-user LRU list maintenance */
1474 nat44_session_update_lru (sm, s0, thread_index);
1477 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
1478 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1480 nat_in2out_ed_trace_t *t =
1481 vlib_add_trace (vm, node, b0, sizeof (*t));
1482 t->sw_if_index = sw_if_index0;
1483 t->next_index = next0;
1484 t->is_slow_path = 1;
1487 t->session_index = s0 - tsm->sessions;
1489 t->session_index = ~0;
1492 pkts_processed += next0 == nat_buffer_opaque (b0)->arc_next;
1494 /* verify speculative enqueue, maybe switch current next frame */
1495 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1496 to_next, n_left_to_next,
1500 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1503 vlib_node_increment_counter (vm, stats_node_index,
1504 NAT_IN2OUT_ED_ERROR_IN2OUT_PACKETS,
1506 vlib_node_increment_counter (vm, stats_node_index,
1507 NAT_IN2OUT_ED_ERROR_TCP_PACKETS, tcp_packets);
1508 vlib_node_increment_counter (vm, stats_node_index,
1509 NAT_IN2OUT_ED_ERROR_UDP_PACKETS, udp_packets);
1510 vlib_node_increment_counter (vm, stats_node_index,
1511 NAT_IN2OUT_ED_ERROR_ICMP_PACKETS,
1513 vlib_node_increment_counter (vm, stats_node_index,
1514 NAT_IN2OUT_ED_ERROR_OTHER_PACKETS,
1516 return frame->n_vectors;
1519 VLIB_NODE_FN (nat44_ed_in2out_node) (vlib_main_t * vm,
1520 vlib_node_runtime_t * node,
1521 vlib_frame_t * frame)
1523 return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 0);
1527 VLIB_REGISTER_NODE (nat44_ed_in2out_node) = {
1528 .name = "nat44-ed-in2out",
1529 .vector_size = sizeof (u32),
1530 .sibling_of = "nat-default",
1531 .format_trace = format_nat_in2out_ed_trace,
1532 .type = VLIB_NODE_TYPE_INTERNAL,
1533 .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1534 .error_strings = nat_in2out_ed_error_strings,
1535 .runtime_data_bytes = sizeof (snat_runtime_t),
1539 VLIB_NODE_FN (nat44_ed_in2out_output_node) (vlib_main_t * vm,
1540 vlib_node_runtime_t * node,
1541 vlib_frame_t * frame)
1543 return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 1);
1547 VLIB_REGISTER_NODE (nat44_ed_in2out_output_node) = {
1548 .name = "nat44-ed-in2out-output",
1549 .vector_size = sizeof (u32),
1550 .sibling_of = "nat-default",
1551 .format_trace = format_nat_in2out_ed_trace,
1552 .type = VLIB_NODE_TYPE_INTERNAL,
1553 .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1554 .error_strings = nat_in2out_ed_error_strings,
1555 .runtime_data_bytes = sizeof (snat_runtime_t),
1559 VLIB_NODE_FN (nat44_ed_in2out_slowpath_node) (vlib_main_t * vm,
1560 vlib_node_runtime_t *
1561 node, vlib_frame_t * frame)
1563 return nat44_ed_in2out_slow_path_node_fn_inline (vm, node, frame, 0);
1567 VLIB_REGISTER_NODE (nat44_ed_in2out_slowpath_node) = {
1568 .name = "nat44-ed-in2out-slowpath",
1569 .vector_size = sizeof (u32),
1570 .sibling_of = "nat-default",
1571 .format_trace = format_nat_in2out_ed_trace,
1572 .type = VLIB_NODE_TYPE_INTERNAL,
1573 .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1574 .error_strings = nat_in2out_ed_error_strings,
1575 .runtime_data_bytes = sizeof (snat_runtime_t),
1579 VLIB_NODE_FN (nat44_ed_in2out_output_slowpath_node) (vlib_main_t * vm,
1582 vlib_frame_t * frame)
1584 return nat44_ed_in2out_slow_path_node_fn_inline (vm, node, frame, 1);
1588 VLIB_REGISTER_NODE (nat44_ed_in2out_output_slowpath_node) = {
1589 .name = "nat44-ed-in2out-output-slowpath",
1590 .vector_size = sizeof (u32),
1591 .sibling_of = "nat-default",
1592 .format_trace = format_nat_in2out_ed_trace,
1593 .type = VLIB_NODE_TYPE_INTERNAL,
1594 .n_errors = ARRAY_LEN (nat_in2out_ed_error_strings),
1595 .error_strings = nat_in2out_ed_error_strings,
1596 .runtime_data_bytes = sizeof (snat_runtime_t),
1601 format_nat_pre_trace (u8 * s, va_list * args)
1603 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1604 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1605 nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *);
1606 return format (s, "in2out next_index %d", t->next_index);
1609 VLIB_NODE_FN (nat_pre_in2out_node)
1610 (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1612 return nat_pre_node_fn_inline (vm, node, frame,
1613 NAT_NEXT_IN2OUT_ED_FAST_PATH);
1617 VLIB_REGISTER_NODE (nat_pre_in2out_node) = {
1618 .name = "nat-pre-in2out",
1619 .vector_size = sizeof (u32),
1620 .sibling_of = "nat-default",
1621 .format_trace = format_nat_pre_trace,
1622 .type = VLIB_NODE_TYPE_INTERNAL,
1628 * fd.io coding-style-patch-verification: ON
1631 * eval: (c-set-style "gnu")