53 tag = t->
is_slow_path ?
"NAT44_IN2OUT_SLOW_PATH" :
"NAT44_IN2OUT_FAST_PATH";
55 s =
format (s,
"%s: sw_if_index %d, next index %d, session %d", tag,
67 s =
format (s,
"NAT44_IN2OUT_FAST: sw_if_index %d, next index %d",
81 m = t->
do_handoff ?
"next worker" :
"same worker";
99 s =
format (s,
"NAT44_IN2OUT_REASS: sw_if_index %d, next index %d, status %s",
101 t->
cached ?
"cached" :
"translated");
120 #define foreach_snat_in2out_error \ 121 _(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \ 122 _(IN2OUT_PACKETS, "Good in2out packets processed") \ 123 _(OUT_OF_PORTS, "Out of ports") \ 124 _(BAD_OUTSIDE_FIB, "Outside VRF ID not found") \ 125 _(BAD_ICMP_TYPE, "unsupported ICMP type") \ 126 _(NO_TRANSLATION, "No translation") \ 127 _(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded") \ 128 _(DROP_FRAGMENT, "Drop fragment") \ 129 _(MAX_REASS, "Maximum reassemblies exceeded") \ 130 _(MAX_FRAG, "Maximum fragments per reassembly exceeded") 133 #define _(sym,str) SNAT_IN2OUT_ERROR_##sym, 140 #define _(sym,string) string, 200 if (sw_if_index == ~0)
210 if ((nat_interface_is_outside(i)) && (sw_if_index == i->sw_if_index))
221 u32 rx_fib_index0,
u32 thread_index)
255 u32 thread_index,
u32 sw_if_index)
263 key0.
port = src_port;
274 key0.
port = dst_port;
284 if ((nat_interface_is_inside(i)) && (sw_if_index == i->sw_if_index))
297 snat_session_t ** sessionp,
306 u32 address_index = ~0;
307 u32 outside_fib_index;
314 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
321 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_OUTSIDE_FIB];
324 outside_fib_index = p[0];
346 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
363 s->outside_address_index = address_index;
367 s->out2in.fib_index = outside_fib_index;
373 kv0.
key = s->in2out.as_u64;
379 kv0.
key = s->out2in.as_u64;
388 s->out2in.addr.as_u32,
392 s->in2out.fib_index);
400 icmp46_header_t *icmp0;
405 icmp46_header_t *inner_icmp0;
424 case SNAT_PROTOCOL_ICMP:
425 inner_icmp0 = (icmp46_header_t*)l4_header;
429 case SNAT_PROTOCOL_UDP:
430 case SNAT_PROTOCOL_TCP:
434 return SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL;
444 icmp46_header_t *icmp0;
449 icmp46_header_t *inner_icmp0;
456 key0.
proto = IP_PROTOCOL_ICMP;
470 case SNAT_PROTOCOL_ICMP:
471 inner_icmp0 = (icmp46_header_t*)l4_header;
475 case SNAT_PROTOCOL_UDP:
476 case SNAT_PROTOCOL_TCP:
481 return SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL;
498 if (ip->
protocol == IP_PROTOCOL_ICMP)
503 else if (ip->
protocol == IP_PROTOCOL_UDP || ip->
protocol == IP_PROTOCOL_TCP)
523 if (!clib_bihash_search_16_8 (&sm->
in2out_ed, &kv, &value))
524 return value.
value == ~0ULL;
547 u8 *p_dont_translate,
void *d,
void *e)
549 icmp46_header_t *icmp0;
553 snat_session_t *s0 = 0;
554 u8 dont_translate = 0;
580 ip0, SNAT_PROTOCOL_ICMP, key0.
port, key0.
port, thread_index, sw_if_index0)))
589 ip0, SNAT_PROTOCOL_ICMP, rx_fib_index0, thread_index)))
598 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
603 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
604 &s0, node, next0, thread_index);
612 icmp0->type != ICMP4_echo_reply &&
615 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
629 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
636 if (!clib_bihash_search_16_8 (&sm->
in2out_ed, &s_kv, &s_value))
653 *p_value = s0->out2in;
654 *p_dont_translate = dont_translate;
656 *(snat_session_t**)d = s0;
677 u8 *p_dont_translate,
void *d,
void *e)
679 icmp46_header_t *icmp0;
684 u8 dont_translate = 0;
705 IP_PROTOCOL_ICMP, rx_fib_index0)))
717 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
723 (icmp0->type != ICMP4_echo_reply || !is_addr_only) &&
726 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
735 *p_dont_translate = dont_translate;
742 icmp46_header_t * icmp0,
756 icmp46_header_t *inner_icmp0;
758 u32 new_addr0, old_addr0;
759 u16 old_id0, new_id0;
767 &protocol, &sm0, &dont_translate, d, e);
792 if (icmp0->checksum == 0)
793 icmp0->checksum = 0xffff;
804 sum0 = icmp0->checksum;
825 sum0 = icmp0->checksum;
832 case SNAT_PROTOCOL_ICMP:
833 inner_icmp0 = (icmp46_header_t*)l4_header;
840 sum0 = icmp0->checksum;
845 case SNAT_PROTOCOL_UDP:
846 case SNAT_PROTOCOL_TCP:
851 sum0 = icmp0->checksum;
891 u32 new_dst_addr0 = 0, old_dst_addr0, ti = 0, si;
892 u16 new_dst_port0, old_dst_port0;
904 new_dst_port0 = sm0.
port;
920 new_dst_addr0 = s0->in2out.addr.as_u32;
921 new_dst_port0 = s0->in2out.port;
936 old_dst_port0 = tcp0->dst;
941 tcp0->dst = new_dst_port0;
942 sum0 = tcp0->checksum;
959 sum0 = tcp0->checksum;
974 icmp46_header_t * icmp0)
978 u32 new_dst_addr0 = 0, old_dst_addr0, si, ti = 0;
987 key0.
port = icmp_id0;
1013 new_dst_addr0 = s0->in2out.addr.as_u32;
1016 sum0 = icmp0->checksum;
1039 icmp46_header_t * icmp0,
1046 snat_session_t ** p_s0)
1048 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1049 next0, thread_index, p_s0, 0);
1050 snat_session_t * s0 = *p_s0;
1057 s0->last_heard = now;
1062 s0->per_user_index);
1064 s0->per_user_list_head_index,
1065 s0->per_user_index);
1074 u32 old_addr, new_addr = 0, ti = 0;
1092 if (clib_bihash_search_16_8 (&sm->
out2in_ed, &s_kv, &s_value))
1124 static snat_session_t *
1138 u32 old_addr, new_addr = 0;
1143 u32 elt_index, head_index, ses_index;
1146 u32 address_index = ~0;
1161 if (!clib_bihash_search_16_8 (&sm->
in2out_ed, &s_kv, &s_value))
1170 b->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
1200 if (!clib_bihash_search_8_8 (&tsm->
user_hash, &kv, &value))
1204 elt_index = head->
next;
1206 ses_index = elt->
value;
1207 while (ses_index != ~0)
1210 elt_index = elt->
next;
1212 ses_index = elt->
value;
1217 address_index = s->outside_address_index;
1223 if (clib_bihash_search_16_8 (&sm->
out2in_ed, &s_kv, &s_value))
1236 if (clib_bihash_search_16_8 (&sm->
out2in_ed, &s_kv, &s_value))
1256 s->outside_address_index = address_index;
1257 s->out2in.addr.as_u32 = new_addr;
1259 s->in2out.addr.as_u32 = old_addr;
1260 s->in2out.fib_index = rx_fib_index;
1261 s->in2out.port = s->out2in.port = ip->
protocol;
1274 if (clib_bihash_add_del_16_8 (&sm->
in2out_ed, &s_kv, 1))
1281 if (clib_bihash_add_del_16_8 (&sm->
out2in_ed, &s_kv, 1))
1291 s->last_heard = now;
1309 static snat_session_t *
1323 snat_session_t *s = 0;
1325 u32 old_addr, new_addr;
1326 u16 new_port, old_port;
1343 if (!clib_bihash_search_16_8 (&sm->
in2out_ed, &s_kv, &s_value))
1345 if (s_value.
value == ~0ULL)
1353 b->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
1382 s->outside_address_index = ~0;
1390 if (clib_bihash_add_del_16_8 (&sm->
in2out_ed, &s_kv, 1))
1398 if (clib_bihash_add_del_16_8 (&sm->
out2in_ed, &s_kv, 1))
1414 old_port = tcp->src_port;
1415 tcp->src_port = s->out2in.port;
1416 new_port = tcp->src_port;
1418 sum = tcp->checksum;
1428 tcp->dst_port = s->ext_host_port;
1448 s->last_heard = now;
1462 int is_output_feature)
1464 u32 n_left_from, * from, * to_next;
1466 u32 pkts_processed = 0;
1469 u32 stats_node_index;
1479 while (n_left_from > 0)
1484 to_next, n_left_to_next);
1486 while (n_left_from >= 4 && n_left_to_next >= 2)
1491 u32 sw_if_index0, sw_if_index1;
1494 u32 new_addr0, old_addr0, new_addr1, old_addr1;
1495 u16 old_port0, new_port0, old_port1, new_port1;
1498 icmp46_header_t * icmp0, * icmp1;
1500 u32 rx_fib_index0, rx_fib_index1;
1502 snat_session_t * s0 = 0, * s1 = 0;
1504 u32 iph_offset0 = 0, iph_offset1 = 0;
1521 to_next[0] = bi0 = from[0];
1522 to_next[1] = bi1 = from[1];
1526 n_left_to_next -= 2;
1531 if (is_output_feature)
1532 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
1539 icmp0 = (icmp46_header_t *) udp0;
1551 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1565 thread_index, now, vm, node);
1574 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
1575 node, next0, now, thread_index, &s0);
1581 if (is_output_feature)
1587 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
1612 if (is_output_feature)
1621 ip0, proto0, rx_fib_index0, thread_index)))
1625 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
1626 &s0, node, next0, thread_index);
1643 thread_index, now, vm, node);
1662 b0->
flags |= VNET_BUFFER_F_IS_NATED;
1667 if (!is_output_feature)
1678 old_port0 = tcp0->src_port;
1679 tcp0->src_port = s0->out2in.port;
1680 new_port0 = tcp0->src_port;
1682 sum0 = tcp0->checksum;
1699 s0->last_heard = now;
1704 s0->per_user_index);
1706 s0->per_user_list_head_index,
1707 s0->per_user_index);
1725 if (is_output_feature)
1726 iph_offset1 =
vnet_buffer (b1)->ip.save_rewrite_length;
1733 icmp1 = (icmp46_header_t *) udp1;
1743 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1757 thread_index, now, vm, node);
1766 (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
1767 next1, now, thread_index, &s1);
1773 if (is_output_feature)
1779 if (
PREDICT_FALSE (proto1 == ~0 || proto1 == SNAT_PROTOCOL_ICMP))
1804 if (is_output_feature)
1813 ip1, proto1, rx_fib_index1, thread_index)))
1817 next1 =
slow_path (sm, b1, ip1, rx_fib_index1, &key1,
1818 &s1, node, next1, thread_index);
1835 thread_index, now, vm, node);
1854 b1->
flags |= VNET_BUFFER_F_IS_NATED;
1859 if (!is_output_feature)
1870 old_port1 = tcp1->src_port;
1871 tcp1->src_port = s1->out2in.port;
1872 new_port1 = tcp1->src_port;
1874 sum1 = tcp1->checksum;
1891 s1->last_heard = now;
1896 s1->per_user_index);
1898 s1->per_user_list_head_index,
1899 s1->per_user_index);
1918 to_next, n_left_to_next,
1919 bi0, bi1, next0, next1);
1922 while (n_left_from > 0 && n_left_to_next > 0)
1930 u32 new_addr0, old_addr0;
1931 u16 old_port0, new_port0;
1934 icmp46_header_t * icmp0;
1938 snat_session_t * s0 = 0;
1940 u32 iph_offset0 = 0;
1948 n_left_to_next -= 1;
1953 if (is_output_feature)
1954 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
1961 icmp0 = (icmp46_header_t *) udp0;
1971 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1985 thread_index, now, vm, node);
1994 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1995 next0, now, thread_index, &s0);
2001 if (is_output_feature)
2007 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
2032 if (is_output_feature)
2041 ip0, proto0, rx_fib_index0, thread_index)))
2045 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
2046 &s0, node, next0, thread_index);
2064 thread_index, now, vm, node);
2083 b0->
flags |= VNET_BUFFER_F_IS_NATED;
2088 if (!is_output_feature)
2099 old_port0 = tcp0->src_port;
2100 tcp0->src_port = s0->out2in.port;
2101 new_port0 = tcp0->src_port;
2103 sum0 = tcp0->checksum;
2120 s0->last_heard = now;
2125 s0->per_user_index);
2127 s0->per_user_list_head_index,
2128 s0->per_user_index);
2148 to_next, n_left_to_next,
2156 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
2171 .name =
"nat44-in2out",
2172 .vector_size =
sizeof (
u32),
2205 .name =
"nat44-in2out-output",
2206 .vector_size =
sizeof (
u32),
2240 .name =
"nat44-in2out-slowpath",
2241 .vector_size =
sizeof (
u32),
2275 .name =
"nat44-in2out-output-slowpath",
2276 .vector_size =
sizeof (
u32),
2307 u32 n_left_from, * from, * to_next;
2309 u32 pkts_processed = 0;
2319 while (n_left_from > 0)
2324 to_next, n_left_to_next);
2326 while (n_left_from > 0 && n_left_to_next > 0)
2342 n_left_to_next -= 1;
2361 to_next, n_left_to_next,
2369 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
2376 .name =
"nat44-hairpinning",
2377 .vector_size =
sizeof (
u32),
2400 snat_session_t * s0;
2403 u32 new_dst_addr0 = 0, old_dst_addr0, ti = 0, si;
2404 u16 new_dst_port0, old_dst_port0;
2420 new_dst_port0 = sm0.
port;
2435 new_dst_addr0 = s0->in2out.addr.as_u32;
2436 new_dst_port0 = s0->in2out.port;
2451 old_dst_port0 = dport;
2458 tcp0->dst = new_dst_port0;
2459 sum0 = tcp0->checksum;
2477 sum0 = tcp0->checksum;
2491 u32 n_left_from, *from, *to_next;
2493 u32 pkts_processed = 0;
2499 u32 *fragments_to_drop = 0;
2500 u32 *fragments_to_loopback = 0;
2506 while (n_left_from > 0)
2512 while (n_left_from > 0 && n_left_to_next > 0)
2514 u32 bi0, sw_if_index0, proto0, rx_fib_index0, new_addr0, old_addr0;
2519 nat_reass_ip4_t *reass0;
2524 snat_session_t * s0 = 0;
2525 u16 old_port0, new_port0;
2534 n_left_to_next -= 1;
2546 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
2560 &fragments_to_drop);
2565 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_REASS];
2577 if (clib_bihash_search_8_8 (&per_thread_data->
in2out, &kv0, &value0))
2580 ip0, proto0, rx_fib_index0, thread_index)))
2583 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
2584 &s0, node, next0, thread_index);
2589 reass0->sess_index = s0 - per_thread_data->
sessions;
2595 reass0->sess_index = value0.
value;
2605 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_FRAG];
2613 reass0->sess_index);
2631 old_port0 = tcp0->src_port;
2632 tcp0->src_port = s0->out2in.port;
2633 new_port0 = tcp0->src_port;
2635 sum0 = tcp0->checksum;
2654 s0->ext_host_port, proto0);
2657 s0->last_heard = now;
2662 s0->per_user_index);
2664 s0->per_user_list_head_index,
2665 s0->per_user_index);
2689 to_next, n_left_to_next,
2693 if (n_left_from == 0 &&
vec_len (fragments_to_loopback))
2718 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
2722 &node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT],
2732 .name =
"nat44-in2out-reass",
2733 .vector_size =
sizeof (
u32),
2761 u32 n_left_from, * from, * to_next;
2763 u32 pkts_processed = 0;
2772 while (n_left_from > 0)
2777 to_next, n_left_to_next);
2779 while (n_left_from >= 4 && n_left_to_next >= 2)
2784 u32 sw_if_index0, sw_if_index1;
2788 u16 old_port0, new_port0, lo_port0, i0;
2789 u16 old_port1, new_port1, lo_port1, i1;
2796 u32 rx_fib_index0, rx_fib_index1;
2797 icmp46_header_t * icmp0, * icmp1;
2814 to_next[0] = bi0 = from[0];
2815 to_next[1] = bi1 = from[1];
2819 n_left_to_next -= 2;
2837 ICMP4_time_exceeded_ttl_exceeded_in_transit,
2848 icmp0 = (icmp46_header_t *) udp0;
2850 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
2851 rx_fib_index0, node, next0, thread_index,
2862 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
2876 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
2877 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
2891 ICMP4_destination_unreachable_destination_unreachable_host,
2913 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
2914 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
2915 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
2916 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
2917 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
2918 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
2920 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
2921 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
2922 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
2923 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
2925 old_port0 = tcp0->src;
2926 tcp0->src = new_port0;
2928 sum0 = tcp0->checksum;
2939 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
2947 case SNAT_SESSION_UDP_ACTIVE:
2950 case SNAT_SESSION_TCP_SYN_SENT:
2951 case SNAT_SESSION_TCP_FIN_WAIT:
2952 case SNAT_SESSION_TCP_CLOSE_WAIT:
2953 case SNAT_SESSION_TCP_LAST_ACK:
2956 case SNAT_SESSION_TCP_ESTABLISHED:
2987 ICMP4_time_exceeded_ttl_exceeded_in_transit,
2998 icmp1 = (icmp46_header_t *) udp1;
3000 next1 =
icmp_in2out(sm, b1, ip1, icmp1, sw_if_index1,
3001 rx_fib_index1, node, next1, thread_index,
3012 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
3026 key1.
out_port = clib_host_to_net_u16 (lo_port1 +
3027 ((i1 + clib_net_to_host_u16 (tcp1->src)) % dm1->
ports_per_host));
3041 ICMP4_destination_unreachable_destination_unreachable_host,
3048 new_port1 = ses1->out.out_port;
3063 ses1->state = SNAT_SESSION_TCP_SYN_SENT;
3064 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_SYN_SENT)
3065 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
3066 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_ESTABLISHED)
3067 ses1->state = SNAT_SESSION_TCP_FIN_WAIT;
3068 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_FIN_WAIT)
3070 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_CLOSE_WAIT)
3071 ses1->state = SNAT_SESSION_TCP_LAST_ACK;
3072 else if (tcp1->flags == 0 && ses1->state == SNAT_SESSION_UNKNOWN)
3073 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
3075 old_port1 = tcp1->src;
3076 tcp1->src = new_port1;
3078 sum1 = tcp1->checksum;
3089 ses1->state = SNAT_SESSION_UDP_ACTIVE;
3097 case SNAT_SESSION_UDP_ACTIVE:
3100 case SNAT_SESSION_TCP_SYN_SENT:
3101 case SNAT_SESSION_TCP_FIN_WAIT:
3102 case SNAT_SESSION_TCP_CLOSE_WAIT:
3103 case SNAT_SESSION_TCP_LAST_ACK:
3106 case SNAT_SESSION_TCP_ESTABLISHED:
3129 to_next, n_left_to_next,
3130 bi0, bi1, next0, next1);
3133 while (n_left_from > 0 && n_left_to_next > 0)
3142 u16 old_port0, new_port0, lo_port0, i0;
3150 icmp46_header_t * icmp0;
3158 n_left_to_next -= 1;
3173 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3184 icmp0 = (icmp46_header_t *) udp0;
3186 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
3187 rx_fib_index0, node, next0, thread_index,
3198 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
3212 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
3213 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
3227 ICMP4_destination_unreachable_destination_unreachable_host,
3249 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
3250 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
3251 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
3252 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
3253 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
3254 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
3256 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
3257 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
3258 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
3259 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
3261 old_port0 = tcp0->src;
3262 tcp0->src = new_port0;
3264 sum0 = tcp0->checksum;
3275 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
3283 case SNAT_SESSION_UDP_ACTIVE:
3286 case SNAT_SESSION_TCP_SYN_SENT:
3287 case SNAT_SESSION_TCP_FIN_WAIT:
3288 case SNAT_SESSION_TCP_CLOSE_WAIT:
3289 case SNAT_SESSION_TCP_LAST_ACK:
3292 case SNAT_SESSION_TCP_ESTABLISHED:
3315 to_next, n_left_to_next,
3323 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
3330 .name =
"nat44-det-in2out",
3331 .vector_size =
sizeof (
u32),
3370 u8 *p_dont_translate,
void *d,
void *e)
3372 icmp46_header_t *icmp0;
3377 u8 dont_translate = 0;
3381 void *l4_header = 0;
3382 icmp46_header_t *inner_icmp0;
3397 protocol = SNAT_PROTOCOL_ICMP;
3409 case SNAT_PROTOCOL_ICMP:
3410 inner_icmp0 = (icmp46_header_t*)l4_header;
3414 case SNAT_PROTOCOL_UDP:
3415 case SNAT_PROTOCOL_TCP:
3419 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
3431 IP_PROTOCOL_ICMP, rx_fib_index0)))
3437 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
3450 IP_PROTOCOL_ICMP, rx_fib_index0)))
3455 if (icmp0->type != ICMP4_echo_request)
3457 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
3463 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
3475 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
3483 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
3490 ses0->
state = SNAT_SESSION_ICMP_ACTIVE;
3494 *p_proto = protocol;
3497 p_value->
addr = new_addr0;
3501 *p_dont_translate = dont_translate;
3520 u32 n_left_from, *from, *to_next = 0;
3527 u32 n_left_to_next_worker = 0, *to_next_worker = 0;
3528 u32 next_worker_index = 0;
3529 u32 current_worker_index = ~0;
3559 while (n_left_from > 0)
3585 if (next_worker_index != current_worker_index)
3592 handoff_queue_elt_by_worker_index);
3596 current_worker_index = next_worker_index;
3600 to_next_worker[0] = bi0;
3602 n_left_to_next_worker--;
3604 if (n_left_to_next_worker == 0)
3608 current_worker_index = ~0;
3609 handoff_queue_elt_by_worker_index[next_worker_index] = 0;
3645 for (i = 0; i <
vec_len (handoff_queue_elt_by_worker_index); i++)
3647 if (handoff_queue_elt_by_worker_index[i])
3649 hf = handoff_queue_elt_by_worker_index[
i];
3657 handoff_queue_elt_by_worker_index[
i] = 0;
3662 congested_handoff_queue_by_worker_index[
i] =
3666 current_worker_index = ~0;
3680 .name =
"nat44-in2out-worker-handoff",
3681 .vector_size =
sizeof (
u32),
3705 .name =
"nat44-in2out-output-worker-handoff",
3706 .vector_size =
sizeof (
u32),
3749 u32 n_left_from, * from, * to_next;
3751 u32 pkts_processed = 0;
3758 while (n_left_from > 0)
3763 to_next, n_left_to_next);
3765 while (n_left_from > 0 && n_left_to_next > 0)
3779 n_left_to_next -= 1;
3790 if (proto0 == SNAT_PROTOCOL_TCP || proto0 == SNAT_PROTOCOL_UDP)
3797 else if (proto0 == SNAT_PROTOCOL_ICMP)
3815 to_next, n_left_to_next,
3823 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
3830 .name =
"nat44-hairpin-dst",
3831 .vector_size =
sizeof (
u32),
3850 u32 n_left_from, * from, * to_next;
3852 u32 pkts_processed = 0;
3859 while (n_left_from > 0)
3864 to_next, n_left_to_next);
3866 while (n_left_from > 0 && n_left_to_next > 0)
3880 n_left_to_next -= 1;
3889 if ((nat_interface_is_inside(i)) && (sw_if_index0 == i->sw_if_index))
3891 if (PREDICT_FALSE ((vnet_buffer (b0)->snat.flags) &
3892 SNAT_FLAG_HAIRPINNING))
3894 if (PREDICT_TRUE (sm->num_workers > 1))
3895 next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH;
3897 next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT;
3907 to_next, n_left_to_next,
3915 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
3917 return frame->n_vectors;
3922 .name =
"nat44-hairpin-src",
3923 .vector_size =
sizeof (
u32),
3944 u32 n_left_from, * from, * to_next;
3946 u32 pkts_processed = 0;
3948 u32 stats_node_index;
3956 while (n_left_from > 0)
3961 to_next, n_left_to_next);
3963 while (n_left_from > 0 && n_left_to_next > 0)
3971 u32 new_addr0, old_addr0;
3972 u16 old_port0, new_port0;
3975 icmp46_header_t * icmp0;
3986 n_left_to_next -= 1;
3994 icmp0 = (icmp46_header_t *) udp0;
4003 ICMP4_time_exceeded_ttl_exceeded_in_transit,
4016 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
4017 rx_fib_index0, node, next0, ~0, 0, 0);
4028 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
4034 new_port0 = sm0.
port;
4049 old_port0 = tcp0->src_port;
4050 tcp0->src_port = new_port0;
4052 sum0 = tcp0->checksum;
4072 sum0 = tcp0->checksum;
4097 to_next, n_left_to_next,
4105 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
4113 .name =
"nat44-in2out-fast",
4114 .vector_size =
sizeof (
u32),
ip4_address_t external_addr
vnet_config_main_t config_main
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
static snat_session_t * snat_in2out_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index, u32 thread_index, f64 now, vlib_main_t *vm, vlib_node_runtime_t *node)
fib_protocol_t fp_proto
protocol type
u32 sessions_per_user_list_head_index
static u8 * format_snat_in2out_trace(u8 *s, va_list *args)
clib_bihash_16_8_t out2in_ed
sll srl srl sll sra u16x4 i
static uword snat_in2out_slow_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
static int nat_not_translate_output_feature(snat_main_t *sm, ip4_header_t *ip0, u32 proto0, u16 src_port, u16 dst_port, u32 thread_index, u32 sw_if_index)
u32 fq_in2out_output_index
static u8 * format_snat_in2out_fast_trace(u8 *s, va_list *args)
static uword snat_in2out_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_slow_path, int is_output_feature)
static int ip4_header_bytes(ip4_header_t *i)
static f64 vlib_time_now(vlib_main_t *vm)
static char * snat_in2out_error_strings[]
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
int nat_ip4_reass_add_fragment(nat_reass_ip4_t *reass, u32 bi)
Cache fragment.
static uword snat_in2out_worker_handoff_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static void snat_icmp_hairpinning(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0)
static void snat_det_ses_close(snat_det_map_t *dm, snat_det_session_t *ses)
struct _vlib_node_registration vlib_node_registration_t
static snat_det_session_t * snat_det_find_ses_by_in(snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port, snat_det_out_key_t out_key)
static void snat_det_forward(snat_det_map_t *dm, ip4_address_t *in_addr, ip4_address_t *out_addr, u16 *lo_port)
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
clib_bihash_16_8_t in2out_ed
int snat_static_mapping_match(snat_main_t *sm, snat_session_key_t match, snat_session_key_t *mapping, u8 by_external, u8 *is_addr_only, u8 *twice_nat)
Match NAT44 static mapping.
u32 buffer_index[VLIB_FRAME_SIZE]
vlib_error_t * errors
Vector of errors for this node.
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
VLIB_NODE_FUNCTION_MULTIARCH(snat_in2out_node, snat_in2out_fast_path_fn)
u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation.
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
clib_bihash_8_8_t user_hash
vlib_node_registration_t snat_hairpin_dst_node
(constructor) VLIB_REGISTER_NODE (snat_hairpin_dst_node)
static uword snat_in2out_output_slow_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vlib_node_registration_t snat_in2out_output_slowpath_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_output_slowpath_node)
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
u32 in2out_output_node_index
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
#define static_always_inline
static uword ip4_header_checksum_is_valid(ip4_header_t *i)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
vlib_node_registration_t snat_in2out_output_worker_handoff_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_output_worker_handoff_node)
ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
vlib_node_registration_t snat_in2out_fast_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_fast_node)
static uword snat_in2out_output_worker_handoff_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
ip4_address_t ext_host_addr
static int snat_not_translate(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, ip4_header_t *ip0, u32 proto0, u32 rx_fib_index0, u32 thread_index)
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
static uword snat_det_in2out_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Aggregrate type for a prefix.
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
static u8 * format_snat_in2out_worker_handoff_trace(u8 *s, va_list *args)
static void * ip4_next_header(ip4_header_t *i)
static u32 slow_path(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, u32 rx_fib_index0, snat_session_key_t *key0, snat_session_t **sessionp, vlib_node_runtime_t *node, u32 next0, u32 thread_index)
vlib_node_registration_t snat_in2out_slowpath_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_slowpath_node)
static uword snat_in2out_worker_handoff_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u8 is_output)
fib_node_index_t fib_table_lookup(u32 fib_index, const fib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
static u8 * format_nat44_in2out_reass_trace(u8 *s, va_list *args)
#define foreach_snat_in2out_error
static int ip4_is_fragment(ip4_header_t *i)
static void nat44_reass_hairpinning(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, u16 sport, u16 dport, u32 proto0)
snat_user_t * nat_user_get_or_create(snat_main_t *sm, ip4_address_t *addr, u32 fib_index, u32 thread_index)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
static uword nat44_in2out_reass_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
snat_det_session_t * sessions
static u32 icmp_in2out_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 clib_dlist_addtail(dlist_elt_t *pool, u32 head_index, u32 new_index)
snat_static_mapping_t * static_mappings
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
static_always_inline int icmp_get_ed_key(ip4_header_t *ip0, nat_ed_ses_key_t *p_key0)
static void * vnet_get_config_data(vnet_config_main_t *cm, u32 *config_index, u32 *next_index, u32 n_data_bytes)
void snat_ipfix_logging_nat44_ses_create(u32 src_ip, u32 nat_src_ip, snat_protocol_t snat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session create event.
static vlib_frame_queue_elt_t * vlib_get_worker_handoff_queue_elt(u32 frame_queue_index, u32 vlib_worker_index, vlib_frame_queue_elt_t **handoff_queue_elt_by_worker_index)
clib_bihash_8_8_t static_mapping_by_external
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
#define SNAT_SESSION_FLAG_UNKNOWN_PROTO
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
vlib_error_t error
Error code for buffers to be enqueued to error handler.
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
snat_interface_t * output_feature_interfaces
static void snat_hairpinning_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip)
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
static_always_inline int is_hairpinning(snat_main_t *sm, ip4_address_t *dst_addr)
vlib_node_registration_t nat44_in2out_reass_node
(constructor) VLIB_REGISTER_NODE (nat44_in2out_reass_node)
static_always_inline uword vlib_get_thread_index(void)
u8 nat_reass_is_drop_frag(u8 is_ip6)
Get status of virtual fragmentation reassembly.
#define CLIB_PREFETCH(addr, size, type)
static uword snat_in2out_output_fast_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
snat_get_worker_function_t * worker_in2out_cb
#define vec_free(V)
Free vector's memory (no header).
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
deterministic NAT definitions
#define clib_warning(format, args...)
#define VLIB_BUFFER_IS_TRACED
static int nat_not_translate_output_feature_fwd(snat_main_t *sm, ip4_header_t *ip)
#define clib_memcpy(a, b, c)
static int ip4_is_first_fragment(ip4_header_t *i)
static uword snat_in2out_fast_static_map_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
u32 fib_node_index_t
A typedef of a node index.
8 octet key, 8 octet key value pair
static_always_inline snat_in2out_error_t icmp_get_key(ip4_header_t *ip0, snat_session_key_t *p_key0)
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
u32 tcp_transitory_timeout
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
static snat_det_map_t * snat_det_map_by_user(snat_main_t *sm, ip4_address_t *user_addr)
static uword nat44_hairpinning_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
snat_get_worker_function_t * worker_out2in_cb
static u32 ip_proto_to_snat_proto(u8 ip_proto)
#define VLIB_NODE_FLAG_TRACE
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
static int snat_not_translate_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, ip4_header_t *ip0, u32 proto0, u32 rx_fib_index0)
Check if packet should be translated.
vlib_node_registration_t nat44_hairpinning_node
(constructor) VLIB_REGISTER_NODE (nat44_hairpinning_node)
snat_session_t * nat_session_alloc_or_recycle(snat_main_t *sm, snat_user_t *u, u32 thread_index)
vlib_node_registration_t snat_det_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_det_in2out_node)
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
#define vec_elt(v, i)
Get vector value at index i.
static uword snat_hairpin_src_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define FIB_NODE_INDEX_INVALID
int snat_alloc_outside_address_and_port(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u32 *address_indexp, u16 port_per_thread, u32 snat_thread_index)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_node_registration_t snat_in2out_worker_handoff_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_worker_handoff_node)
static_always_inline u8 is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr)
snat_main_per_thread_data_t * per_thread_data
#define SNAT_FLAG_HAIRPINNING
static int snat_hairpinning(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, udp_header_t *udp0, tcp_header_t *tcp0, u32 proto0)
Hairpinning.
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)
vlib_node_registration_t snat_hairpin_src_node
(constructor) VLIB_REGISTER_NODE (snat_hairpin_src_node)
static snat_session_t * snat_in2out_lb(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index, u32 thread_index, f64 now, vlib_main_t *vm, vlib_node_runtime_t *node)
nat_reass_ip4_t * nat_ip4_reass_find_or_create(ip4_address_t src, ip4_address_t dst, u16 frag_id, u8 proto, u8 reset_timeout, u32 **bi_to_drop)
Find or create reassembly.
snat_address_t * addresses
static void vlib_put_frame_queue_elt(vlib_frame_queue_elt_t *hf)
u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
struct _vnet_feature_arc_registration vnet_feature_arc_registration_t
feature registration object
vnet_feature_arc_registration_t vnet_feat_arc_ip4_local
static uword snat_in2out_fast_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static snat_det_session_t * snat_det_get_ses_by_out(snat_det_map_t *dm, ip4_address_t *in_addr, u64 out_key)
#define SNAT_SESSION_FLAG_STATIC_MAPPING
#define VLIB_REGISTER_NODE(x,...)
static vlib_thread_main_t * vlib_get_thread_main()
#define vec_foreach(var, vec)
Vector iterator.
vlib_node_registration_t snat_in2out_output_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_output_node)
static_always_inline void nat_send_all_to_node(vlib_main_t *vm, u32 *bi_vector, vlib_node_runtime_t *node, vlib_error_t *error, u32 next)
u16 flags
Copy of main node flags.
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
static uword snat_hairpin_dst_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
void nat_ip4_reass_get_frags(nat_reass_ip4_t *reass, u32 **bi)
Get cached fragments.
NAT plugin virtual fragmentation reassembly.
vnet_feature_config_main_t * feature_config_mains
feature config main objects
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
#define CLIB_CACHE_LINE_BYTES
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 snat_det_session_t * snat_det_ses_create(snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port, snat_det_out_key_t *out)
static u8 maximum_sessions_exceeded(snat_main_t *sm, u32 thread_index)
vnet_feature_main_t feature_main
snat_session_t * sessions
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
snat_icmp_match_function_t * icmp_match_in2out_cb
#define SNAT_SESSION_FLAG_LOAD_BALANCING
clib_bihash_8_8_t static_mapping_by_local
static u16 ip_csum_fold(ip_csum_t c)
snat_interface_t * interfaces
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
u32 tcp_established_timeout
static u32 icmp_in2out(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)