55 "NAT44_OUT2IN: sw_if_index %d, next index %d, session index %d",
67 s =
format (s,
"NAT44_OUT2IN_FAST: sw_if_index %d, next index %d",
72 #define foreach_snat_out2in_error \ 73 _(UNSUPPORTED_PROTOCOL, "unsupported protocol") \ 74 _(OUT_OF_PORTS, "out of ports") \ 75 _(BAD_ICMP_TYPE, "unsupported ICMP type") \ 76 _(NO_TRANSLATION, "no translation") \ 77 _(MAX_SESSIONS_EXCEEDED, "maximum sessions exceeded") \ 78 _(CANNOT_CREATE_USER, "cannot create NAT user") 82 #define _(sym,str) SNAT_OUT2IN_ERROR_##sym, 89 #define _(sym,string) string, 102 #ifndef CLIB_MARCH_VARIANT 109 u64 sess_timeout_time;
116 if (ctx->
now >= sess_timeout_time)
119 if (clib_bihash_add_del_8_8 (&tsm->
in2out, &s_kv, 0))
123 s->in2out.addr.as_u32,
124 s->out2in.addr.as_u32,
128 s->in2out.fib_index);
131 &s->in2out.addr, s->in2out.port,
132 &s->out2in.addr, s->out2in.port, s->nat_proto);
134 nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
135 s->ext_host_port, s->nat_proto, s->out2in.fib_index,
140 &s->out2in.addr, s->out2in.port,
165 static inline snat_session_t *
176 u32 thread_index,
f64 now)
187 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_MAX_SESSIONS_EXCEEDED];
198 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_CANNOT_CREATE_USER];
214 s->in2out.addr = i2o_addr;
215 s->in2out.port = i2o_port;
216 s->in2out.fib_index = i2o_fib_index;
217 s->out2in.addr = o2i_addr;
218 s->out2in.port = o2i_port;
219 s->out2in.fib_index = o2i_fib_index;
220 s->nat_proto =
proto;
226 if (clib_bihash_add_or_overwrite_stale_8_8
232 if (clib_bihash_add_or_overwrite_stale_8_8
239 s->in2out.addr.as_u32,
240 s->out2in.addr.as_u32,
243 s->out2in.port, s->in2out.fib_index);
246 &s->in2out.addr, s->in2out.port, &s->out2in.addr,
247 s->out2in.port, s->nat_proto);
249 nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
250 s->out2in.port, &s->ext_host_addr, s->ext_host_port,
251 &s->ext_host_nat_addr, s->ext_host_nat_port,
252 s->nat_proto, s->in2out.fib_index, s->flags, thread_index, 0);
257 #ifndef CLIB_MARCH_VARIANT 262 icmp46_header_t *icmp0;
266 icmp46_header_t *inner_icmp0;
272 (
vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
274 *nat_proto = NAT_PROTOCOL_ICMP;
286 case NAT_PROTOCOL_ICMP:
287 inner_icmp0 = (icmp46_header_t *) l4_header;
291 case NAT_PROTOCOL_UDP:
292 case NAT_PROTOCOL_TCP:
296 return SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL;
327 snat_session_t *s0 = 0;
344 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
351 u32 mapping_fib_index;
353 init_nat_k (&kv0, *addr, *port, *fib_index, *proto);
354 if (clib_bihash_search_8_8 (&tsm->
out2in, &kv0, &value0))
359 (sm, *addr, *port, *fib_index, *proto,
360 &mapping_addr, &mapping_port, &mapping_fib_index, 1, &is_addr_only,
361 0, 0, 0, &identity_nat, 0))
372 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
387 ICMP4_echo_request || !is_addr_only)))
389 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
402 mapping_fib_index, *addr, *port,
403 *fib_index, *proto, node,
420 reass.icmp_type_or_tcp_flags)))
422 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
433 *addr = s0->in2out.addr;
434 *port = s0->in2out.port;
435 *fib_index = s0->in2out.fib_index;
438 *(snat_session_t **) d = s0;
443 #ifndef CLIB_MARCH_VARIANT 462 u16 * mapping_port,
u32 * mapping_fib_index,
486 (sm, addr, port, rx_fib_index0, *proto, mapping_addr, mapping_port,
487 mapping_fib_index, 1, &is_addr_only, 0, 0, 0, 0, 0))
495 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
501 (
vnet_buffer (b0)->
ip.reass.icmp_type_or_tcp_flags != ICMP4_echo_reply
503 ICMP4_echo_request || !is_addr_only)
505 reass.icmp_type_or_tcp_flags)))
507 b0->
error = node->
errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
517 #ifndef CLIB_MARCH_VARIANT 522 icmp46_header_t * icmp0,
526 u32 next0,
u32 thread_index,
void *d,
void *e)
531 icmp46_header_t *inner_icmp0;
533 u32 new_addr0, old_addr0;
534 u16 old_id0, new_id0;
547 &addr, &port, &fib_index, &proto,
548 d, e, &dont_translate);
563 if (checksum0 != 0 && checksum0 != 0xffff)
582 if (icmp0->checksum == 0)
583 icmp0->checksum = 0xffff;
594 sum0 = icmp0->checksum;
616 sum0 = icmp0->checksum;
623 case NAT_PROTOCOL_ICMP:
624 inner_icmp0 = (icmp46_header_t *) l4_header;
631 sum0 = icmp0->checksum;
637 case NAT_PROTOCOL_UDP:
638 case NAT_PROTOCOL_TCP:
643 sum0 = icmp0->checksum;
663 icmp46_header_t * icmp0,
668 u32 thread_index, snat_session_t ** p_s0)
672 next0 =
icmp_out2in (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
673 next0, thread_index, p_s0, 0);
674 snat_session_t *s0 = *p_s0;
680 (vm, b0), thread_index);
694 u32 old_addr, new_addr;
717 u32 n_left_from, *from;
724 n_left_from =
frame->n_vectors;
730 while (n_left_from >= 2)
735 u32 sw_if_index0, sw_if_index1;
738 u32 new_addr0, old_addr0;
739 u16 new_port0, old_port0;
740 u32 new_addr1, old_addr1;
741 u16 new_port1, old_port1;
744 icmp46_header_t *icmp0, *icmp1;
745 u32 rx_fib_index0, rx_fib_index1;
747 snat_session_t *s0 = 0, *s1 = 0;
749 u8 identity_nat0, identity_nat1;
751 u16 sm_port0, sm_port1;
752 u32 sm_fib_index0, sm_fib_index1;
780 icmp0 = (icmp46_header_t *) udp0;
790 ICMP4_time_exceeded_ttl_exceeded_in_transit,
805 node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
810 thread_index, sw_if_index0, 1);
818 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
node,
819 next0, now, thread_index, &s0);
821 thread_index, sw_if_index0, 1);
828 if (clib_bihash_search_8_8
836 proto0, &sm_addr0, &sm_port0, &sm_fib_index0, 1, 0, 0, 0,
837 0, &identity_nat0, 0))
844 (proto0 == NAT_PROTOCOL_UDP
846 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
854 b0->
error =
node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
870 rx_fib_index0, proto0,
node,
895 old_port0 =
vnet_buffer (b0)->ip.reass.l4_dst_port;
896 new_port0 = udp0->
dst_port = s0->in2out.port;
897 sum0 = tcp0->checksum;
908 thread_index, sw_if_index0, 1);
914 old_port0 =
vnet_buffer (b0)->ip.reass.l4_dst_port;
915 new_port0 = udp0->
dst_port = s0->in2out.port;
929 thread_index, sw_if_index0, 1);
941 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
955 thread_index, sw_if_index0, 1);
962 icmp1 = (icmp46_header_t *) udp1;
972 ICMP4_time_exceeded_ttl_exceeded_in_transit,
987 node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
992 thread_index, sw_if_index1, 1);
999 (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1,
node,
1000 next1, now, thread_index, &s1);
1002 thread_index, sw_if_index1, 1);
1010 if (clib_bihash_search_8_8
1018 rx_fib_index1, &sm_addr1, &sm_port1, &sm_fib_index1, 1, 0,
1019 0, 0, 0, &identity_nat1, 0))
1026 (proto1 == NAT_PROTOCOL_UDP
1028 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
1036 b1->
error =
node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
1052 rx_fib_index1, proto1,
node,
1079 old_port1 =
vnet_buffer (b1)->ip.reass.l4_dst_port;
1080 new_port1 = udp1->
dst_port = s1->in2out.port;
1082 sum1 = tcp1->checksum;
1093 thread_index, sw_if_index1, 1);
1099 old_port1 =
vnet_buffer (b1)->ip.reass.l4_dst_port;
1100 new_port1 = udp1->
dst_port = s1->in2out.port;
1117 thread_index, sw_if_index1, 1);
1129 && (b1->
flags & VLIB_BUFFER_IS_TRACED)))
1143 thread_index, sw_if_index1, 1);
1152 while (n_left_from > 0)
1159 u32 new_addr0, old_addr0;
1160 u16 new_port0, old_port0;
1163 icmp46_header_t *icmp0;
1166 snat_session_t *s0 = 0;
1181 icmp0 = (icmp46_header_t *) udp0;
1196 node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
1201 thread_index, sw_if_index0, 1);
1209 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1218 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
node,
1219 next0, now, thread_index, &s0);
1221 thread_index, sw_if_index0, 1);
1229 if (clib_bihash_search_8_8
1237 proto0, &sm_addr0, &sm_port0, &sm_fib_index0, 1, 0, 0, 0,
1238 0, &identity_nat0, 0))
1245 (proto0 == NAT_PROTOCOL_UDP
1247 clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client))))
1255 b0->
error =
node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
1271 rx_fib_index0, proto0,
node,
1298 old_port0 =
vnet_buffer (b0)->ip.reass.l4_dst_port;
1299 new_port0 = udp0->
dst_port = s0->in2out.port;
1301 sum0 = tcp0->checksum;
1312 thread_index, sw_if_index0, 1);
1318 old_port0 =
vnet_buffer (b0)->ip.reass.l4_dst_port;
1319 new_port0 = udp0->
dst_port = s0->in2out.port;
1333 thread_index, sw_if_index0, 1);
1345 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
1359 thread_index, sw_if_index0, 1);
1370 return frame->n_vectors;
1375 .name =
"nat44-out2in",
1376 .vector_size =
sizeof (
u32),
1400 u32 n_left_from, *from;
1404 n_left_from =
frame->n_vectors;
1409 while (n_left_from > 0)
1416 u32 new_addr0, old_addr0;
1417 u16 new_port0, old_port0;
1420 icmp46_header_t *icmp0;
1433 icmp0 = (icmp46_header_t *) udp0;
1444 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1457 next0 =
icmp_out2in (sm, b0, ip0, icmp0, sw_if_index0,
1458 rx_fib_index0,
node, next0, ~0, 0, 0);
1464 &sm_addr0, &sm_port0, &sm_fib_index0, 1, 0, 0, 0, 0, 0, 0))
1466 b0->
error =
node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
1470 new_addr0 = sm_addr0.
as_u32;
1471 new_port0 = sm_port0;
1488 sum0 = tcp0->checksum;
1513 sum0 = tcp0->checksum;
1532 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
1553 return frame->n_vectors;
1558 .name =
"nat44-out2in-fast",
1559 .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.
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)
description fragment has unexpected format
#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)
void nat_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 fib_index)
Generate NAT44 session create event.
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.
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)
void nat_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 fib_index)
Generate NAT44 session delete event.