56 "NAT44_OUT2IN: sw_if_index %d, next index %d, session index %d",
68 s =
format (s,
"NAT44_OUT2IN_FAST: sw_if_index %d, next index %d",
73 #define foreach_snat_out2in_error \ 74 _(UNSUPPORTED_PROTOCOL, "unsupported protocol") \ 75 _(OUT_OF_PORTS, "out of ports") \ 76 _(BAD_ICMP_TYPE, "unsupported ICMP type") \ 77 _(NO_TRANSLATION, "no translation") \ 78 _(MAX_SESSIONS_EXCEEDED, "maximum sessions exceeded") \ 79 _(CANNOT_CREATE_USER, "cannot create NAT user") 83 #define _(sym,str) SNAT_OUT2IN_ERROR_##sym, 90 #define _(sym,string) string, 103 #ifndef CLIB_MARCH_VARIANT 110 u64 sess_timeout_time;
117 if (ctx->
now >= sess_timeout_time)
120 if (clib_bihash_add_del_8_8 (&tsm->
in2out, &s_kv, 0))
124 s->in2out.addr.as_u32,
125 s->out2in.addr.as_u32,
129 s->in2out.fib_index);
132 &s->in2out.addr, s->in2out.port,
133 &s->out2in.addr, s->out2in.port, s->nat_proto);
135 nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
136 s->ext_host_port, s->nat_proto, s->out2in.fib_index,
141 &s->out2in.addr, s->out2in.port,
166 static inline snat_session_t *
177 u32 thread_index,
f64 now)
188 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_MAX_SESSIONS_EXCEEDED];
199 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_CANNOT_CREATE_USER];
215 s->in2out.addr = i2o_addr;
216 s->in2out.port = i2o_port;
217 s->in2out.fib_index = i2o_fib_index;
218 s->out2in.addr = o2i_addr;
219 s->out2in.port = o2i_port;
220 s->out2in.fib_index = o2i_fib_index;
221 s->nat_proto =
proto;
227 if (clib_bihash_add_or_overwrite_stale_8_8
233 if (clib_bihash_add_or_overwrite_stale_8_8
240 s->in2out.addr.as_u32,
241 s->out2in.addr.as_u32,
244 s->out2in.port, s->in2out.fib_index);
247 &s->in2out.addr, s->in2out.port, &s->out2in.addr,
248 s->out2in.port, s->nat_proto);
250 nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
251 s->out2in.port, &s->ext_host_addr, s->ext_host_port,
252 &s->ext_host_nat_addr, s->ext_host_nat_port,
253 s->nat_proto, s->in2out.fib_index, s->flags, thread_index, 0);
258 #ifndef CLIB_MARCH_VARIANT 263 icmp46_header_t *icmp0;
267 icmp46_header_t *inner_icmp0;
273 (
vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
275 *nat_proto = NAT_PROTOCOL_ICMP;
287 case NAT_PROTOCOL_ICMP:
288 inner_icmp0 = (icmp46_header_t *) l4_header;
292 case NAT_PROTOCOL_UDP:
293 case NAT_PROTOCOL_TCP:
297 return SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL;
328 snat_session_t *s0 = 0;
345 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
352 u32 mapping_fib_index;
354 init_nat_k (&kv0, *addr, *port, *fib_index, *proto);
355 if (clib_bihash_search_8_8 (&tsm->
out2in, &kv0, &value0))
360 (sm, *addr, *port, *fib_index, *proto,
361 &mapping_addr, &mapping_port, &mapping_fib_index, 1, &is_addr_only,
362 0, 0, 0, &identity_nat, 0))
373 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
388 ICMP4_echo_request || !is_addr_only)))
390 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
403 mapping_fib_index, *addr, *port,
404 *fib_index, *proto, node,
421 reass.icmp_type_or_tcp_flags)))
423 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
434 *addr = s0->in2out.addr;
435 *port = s0->in2out.port;
436 *fib_index = s0->in2out.fib_index;
439 *(snat_session_t **) d = s0;
444 #ifndef CLIB_MARCH_VARIANT 463 u16 * mapping_port,
u32 * mapping_fib_index,
487 (sm, addr, port, rx_fib_index0, *proto, mapping_addr, mapping_port,
488 mapping_fib_index, 1, &is_addr_only, 0, 0, 0, 0, 0))
496 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
502 (
vnet_buffer (b0)->
ip.reass.icmp_type_or_tcp_flags != ICMP4_echo_reply
504 ICMP4_echo_request || !is_addr_only)
506 reass.icmp_type_or_tcp_flags)))
508 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
518 #ifndef CLIB_MARCH_VARIANT 523 icmp46_header_t * icmp0,
527 u32 next0,
u32 thread_index,
void *d,
void *e)
532 icmp46_header_t *inner_icmp0;
534 u32 new_addr0, old_addr0;
535 u16 old_id0, new_id0;
548 &addr, &port, &fib_index, &proto,
549 d, e, &dont_translate);
564 if (checksum0 != 0 && checksum0 != 0xffff)
583 if (icmp0->checksum == 0)
584 icmp0->checksum = 0xffff;
595 sum0 = icmp0->checksum;
617 sum0 = icmp0->checksum;
624 case NAT_PROTOCOL_ICMP:
625 inner_icmp0 = (icmp46_header_t *) l4_header;
632 sum0 = icmp0->checksum;
638 case NAT_PROTOCOL_UDP:
639 case NAT_PROTOCOL_TCP:
644 sum0 = icmp0->checksum;
664 icmp46_header_t * icmp0,
669 u32 thread_index, snat_session_t ** p_s0)
673 next0 =
icmp_out2in (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
674 next0, thread_index, p_s0, 0);
675 snat_session_t *s0 = *p_s0;
681 (vm, b0), thread_index);
695 u32 old_addr, new_addr;
718 u32 n_left_from, *from;
725 n_left_from =
frame->n_vectors;
731 while (n_left_from >= 2)
736 u32 sw_if_index0, sw_if_index1;
739 u32 new_addr0, old_addr0;
740 u16 new_port0, old_port0;
741 u32 new_addr1, old_addr1;
742 u16 new_port1, old_port1;
745 icmp46_header_t *icmp0, *icmp1;
746 u32 rx_fib_index0, rx_fib_index1;
748 snat_session_t *s0 = 0, *s1 = 0;
750 u8 identity_nat0, identity_nat1;
752 u16 sm_port0, sm_port1;
753 u32 sm_fib_index0, sm_fib_index1;
781 icmp0 = (icmp46_header_t *) udp0;
791 ICMP4_time_exceeded_ttl_exceeded_in_transit,
806 node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
811 thread_index, sw_if_index0, 1);
819 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
node,
820 next0, now, thread_index, &s0);
822 thread_index, sw_if_index0, 1);
829 if (clib_bihash_search_8_8
837 proto0, &sm_addr0, &sm_port0, &sm_fib_index0, 1, 0, 0, 0,
838 0, &identity_nat0, 0))
845 (proto0 == NAT_PROTOCOL_UDP
847 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
855 b0->
error =
node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
871 rx_fib_index0, proto0,
node,
896 old_port0 =
vnet_buffer (b0)->ip.reass.l4_dst_port;
897 new_port0 = udp0->
dst_port = s0->in2out.port;
898 sum0 = tcp0->checksum;
909 thread_index, sw_if_index0, 1);
915 old_port0 =
vnet_buffer (b0)->ip.reass.l4_dst_port;
916 new_port0 = udp0->
dst_port = s0->in2out.port;
930 thread_index, sw_if_index0, 1);
942 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
956 thread_index, sw_if_index0, 1);
963 icmp1 = (icmp46_header_t *) udp1;
973 ICMP4_time_exceeded_ttl_exceeded_in_transit,
988 node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
993 thread_index, sw_if_index1, 1);
1000 (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1,
node,
1001 next1, now, thread_index, &s1);
1003 thread_index, sw_if_index1, 1);
1011 if (clib_bihash_search_8_8
1019 rx_fib_index1, &sm_addr1, &sm_port1, &sm_fib_index1, 1, 0,
1020 0, 0, 0, &identity_nat1, 0))
1027 (proto1 == NAT_PROTOCOL_UDP
1029 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
1037 b1->
error =
node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
1053 rx_fib_index1, proto1,
node,
1080 old_port1 =
vnet_buffer (b1)->ip.reass.l4_dst_port;
1081 new_port1 = udp1->
dst_port = s1->in2out.port;
1083 sum1 = tcp1->checksum;
1094 thread_index, sw_if_index1, 1);
1100 old_port1 =
vnet_buffer (b1)->ip.reass.l4_dst_port;
1101 new_port1 = udp1->
dst_port = s1->in2out.port;
1118 thread_index, sw_if_index1, 1);
1130 && (b1->
flags & VLIB_BUFFER_IS_TRACED)))
1144 thread_index, sw_if_index1, 1);
1153 while (n_left_from > 0)
1160 u32 new_addr0, old_addr0;
1161 u16 new_port0, old_port0;
1164 icmp46_header_t *icmp0;
1167 snat_session_t *s0 = 0;
1182 icmp0 = (icmp46_header_t *) udp0;
1197 node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
1202 thread_index, sw_if_index0, 1);
1210 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1219 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
node,
1220 next0, now, thread_index, &s0);
1222 thread_index, sw_if_index0, 1);
1230 if (clib_bihash_search_8_8
1238 proto0, &sm_addr0, &sm_port0, &sm_fib_index0, 1, 0, 0, 0,
1239 0, &identity_nat0, 0))
1246 (proto0 == NAT_PROTOCOL_UDP
1248 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
1256 b0->
error =
node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
1272 rx_fib_index0, proto0,
node,
1299 old_port0 =
vnet_buffer (b0)->ip.reass.l4_dst_port;
1300 new_port0 = udp0->
dst_port = s0->in2out.port;
1302 sum0 = tcp0->checksum;
1313 thread_index, sw_if_index0, 1);
1319 old_port0 =
vnet_buffer (b0)->ip.reass.l4_dst_port;
1320 new_port0 = udp0->
dst_port = s0->in2out.port;
1334 thread_index, sw_if_index0, 1);
1346 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
1360 thread_index, sw_if_index0, 1);
1371 return frame->n_vectors;
1376 .name =
"nat44-out2in",
1377 .vector_size =
sizeof (
u32),
1401 u32 n_left_from, *from;
1405 n_left_from =
frame->n_vectors;
1410 while (n_left_from > 0)
1417 u32 new_addr0, old_addr0;
1418 u16 new_port0, old_port0;
1421 icmp46_header_t *icmp0;
1434 icmp0 = (icmp46_header_t *) udp0;
1445 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1458 next0 =
icmp_out2in (sm, b0, ip0, icmp0, sw_if_index0,
1459 rx_fib_index0,
node, next0, ~0, 0, 0);
1465 &sm_addr0, &sm_port0, &sm_fib_index0, 1, 0, 0, 0, 0, 0, 0))
1467 b0->
error =
node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
1471 new_addr0 = sm_addr0.
as_u32;
1472 new_port0 = sm_port0;
1489 sum0 = tcp0->checksum;
1514 sum0 = tcp0->checksum;
1533 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
1554 return frame->n_vectors;
1559 .name =
"nat44-out2in-fast",
1560 .vector_size =
sizeof (
u32),
vlib_node_registration_t snat_out2in_fast_node
(constructor) VLIB_REGISTER_NODE (snat_out2in_fast_node)
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
static ip_csum_t ip_incremental_checksum_buffer(vlib_main_t *vm, vlib_buffer_t *first_buffer, u32 first_buffer_offset, u32 n_bytes_to_checksum, ip_csum_t sum)
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
static u8 * format_snat_out2in_fast_trace(u8 *s, va_list *args)
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
#define nat_elog_notice(nat_elog_str)
static u32 icmp_out2in_slow_path(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0, u32 sw_if_index0, u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0, f64 now, u32 thread_index, snat_session_t **p_s0)
static void init_nat_i2o_kv(clib_bihash_kv_8_8_t *kv, snat_session_t *s, u64 value)
static f64 vlib_time_now(vlib_main_t *vm)
static void init_nat_i2o_k(clib_bihash_kv_8_8_t *kv, snat_session_t *s)
#define nat_elog_warn(nat_elog_str)
void nat_ha_sadd(ip4_address_t *in_addr, u16 in_port, ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, ip4_address_t *ehn_addr, u16 ehn_port, u8 proto, u32 fib_index, u16 flags, u32 thread_index, u8 is_resync)
Create session add HA event.
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
#define VLIB_NODE_FN(node)
vlib_error_t * errors
Vector of errors for this node.
int nat44_o2i_is_idle_session_cb(clib_bihash_kv_8_8_t *kv, void *arg)
static_always_inline snat_out2in_error_t icmp_get_key(vlib_buffer_t *b, ip4_header_t *ip0, ip4_address_t *addr, u16 *port, nat_protocol_t *nat_proto)
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
void snat_ipfix_logging_nat44_ses_create(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session create event.
struct _tcp_header tcp_header_t
static int ip4_is_fragment(const ip4_header_t *i)
snat_session_t * nat_session_alloc_or_recycle(snat_main_t *sm, snat_user_t *u, u32 thread_index, f64 now)
Allocate new NAT session or recycle last used.
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, ip4_address_t *mapping_addr, u16 *mapping_port, u32 *mapping_fib_index, nat_protocol_t *proto, void *d, void *e, u8 *dont_translate)
Get address and port values to be used for ICMP packet translation.
#define static_always_inline
static uword ip4_header_checksum_is_valid(ip4_header_t *i)
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
void nat_syslog_nat44_apmdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *xsaddr, u16 xsport, nat_protocol_t proto)
int snat_static_mapping_match(snat_main_t *sm, ip4_address_t match_addr, u16 match_port, u32 match_fib_index, nat_protocol_t match_protocol, ip4_address_t *mapping_addr, u16 *mapping_port, u32 *mapping_fib_index, u8 by_external, u8 *is_addr_only, twice_nat_type_t *twice_nat, lb_nat_type_t *lb, ip4_address_t *ext_host_addr, u8 *is_identity_nat, snat_static_mapping_t **out)
Match NAT44 static mapping.
static void init_nat_o2i_kv(clib_bihash_kv_8_8_t *kv, snat_session_t *s, u64 value)
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
static void * ip4_next_header(ip4_header_t *i)
#define foreach_snat_out2in_error
static void nat44_delete_session(snat_main_t *sm, snat_session_t *ses, u32 thread_index)
vl_api_fib_path_type_t type
vlib_error_t error
Error code for buffers to be enqueued to error handler.
snat_user_t * nat_user_get_or_create(snat_main_t *sm, ip4_address_t *addr, u32 fib_index, u32 thread_index)
Find or create NAT user.
void nat_syslog_nat44_apmadd(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *xsaddr, u16 xsport, nat_protocol_t proto)
u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, ip4_address_t *addr, u16 *port, u32 *fib_index, nat_protocol_t *proto, void *d, void *e, u8 *dont_translate)
Get address and port values to be used for ICMP packet translation and create session if needed...
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
snat_static_mapping_t * static_mappings
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
struct snat_main_s::@91 counters
clib_bihash_8_8_t static_mapping_by_external
vl_api_address_union_t src_address
struct snat_main_s::@91::@93 slowpath
vlib_node_registration_t snat_out2in_node
(constructor) VLIB_REGISTER_NODE (snat_out2in_node)
static void init_nat_k(clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port, u32 fib_index, nat_protocol_t proto)
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
vl_api_ip_port_and_mask_t src_port
static void nat44_delete_user_with_no_session(snat_main_t *sm, snat_user_t *u, u32 thread_index)
#define VLIB_REGISTER_NODE(x,...)
#define CLIB_PREFETCH(addr, size, type)
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes, u32 thread_index)
8 octet key, 8 octet key value pair
vlib_main_t vlib_node_runtime_t * node
static_always_inline u8 nat44_maximum_sessions_exceeded(snat_main_t *sm, u32 thread_index)
The NAT44 inline functions.
snat_icmp_match_function_t * icmp_match_out2in_cb
static void nat44_session_update_lru(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Per-user LRU list maintenance.
void snat_ipfix_logging_nat44_ses_delete(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session delete event.
static vlib_main_t * vlib_get_main(void)
void nat_ha_sdel(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 thread_index)
Create session delete HA event.
#define vec_elt(v, i)
Get vector value at index i.
static snat_session_t * create_session_for_static_mapping(snat_main_t *sm, vlib_buffer_t *b0, ip4_address_t i2o_addr, u16 i2o_port, u32 i2o_fib_index, ip4_address_t o2i_addr, u16 o2i_port, u32 o2i_fib_index, nat_protocol_t proto, vlib_node_runtime_t *node, u32 thread_index, f64 now)
Create session for static mapping.
struct snat_main_s::@91::@92 fastpath
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
static char * snat_out2in_error_strings[]
static int nat_out2in_sm_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index)
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
VLIB buffer representation.
snat_main_per_thread_data_t * per_thread_data
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
#define ip_csum_update(sum, old, new, type, field)
static u8 is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr)
static u8 * format_snat_out2in_trace(u8 *s, va_list *args)
snat_address_t * addresses
#define SNAT_SESSION_FLAG_STATIC_MAPPING
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
static int ip4_header_bytes(const ip4_header_t *i)
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
#define VLIB_NODE_FLAG_TRACE
#define CLIB_CACHE_LINE_BYTES
void snat_free_outside_address_and_port(snat_address_t *addresses, u32 thread_index, ip4_address_t *addr, u16 port, nat_protocol_t protocol)
Free outside address and port pair.
u32 icmp_out2in(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0, u32 sw_if_index0, u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0, u32 thread_index, void *d, void *e)
int nat44_i2o_is_idle_session_cb(clib_bihash_kv_8_8_t *kv, void *arg)
snat_session_t * sessions
static_always_inline void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
static u16 ip_csum_fold(ip_csum_t c)