54 tag = t->
is_slow_path ?
"NAT44_IN2OUT_SLOW_PATH" :
"NAT44_IN2OUT_FAST_PATH";
56 s =
format (s,
"%s: sw_if_index %d, next index %d, session %d", tag,
68 s =
format (s,
"NAT44_IN2OUT_FAST: sw_if_index %d, next index %d",
82 m = t->
do_handoff ?
"next worker" :
"same worker";
100 s =
format (s,
"NAT44_IN2OUT_REASS: sw_if_index %d, next index %d, status %s",
102 t->
cached ?
"cached" :
"translated");
127 #define foreach_snat_in2out_error \ 128 _(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \ 129 _(IN2OUT_PACKETS, "Good in2out packets processed") \ 130 _(OUT_OF_PORTS, "Out of ports") \ 131 _(BAD_OUTSIDE_FIB, "Outside VRF ID not found") \ 132 _(BAD_ICMP_TYPE, "unsupported ICMP type") \ 133 _(NO_TRANSLATION, "No translation") \ 134 _(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded") \ 135 _(DROP_FRAGMENT, "Drop fragment") \ 136 _(MAX_REASS, "Maximum reassemblies exceeded") \ 137 _(MAX_FRAG, "Maximum fragments per reassembly exceeded")\ 138 _(FQ_CONGESTED, "Handoff frame queue congested") 141 #define _(sym,str) SNAT_IN2OUT_ERROR_##sym, 148 #define _(sym,string) string, 211 if (sw_if_index == ~0)
221 if ((nat_interface_is_outside(i)) && (sw_if_index == i->sw_if_index))
232 u32 rx_fib_index0,
u32 thread_index)
266 u32 thread_index,
u32 sw_if_index)
274 key0.
port = src_port;
285 key0.
port = dst_port;
295 if ((nat_interface_is_inside(i)) && (sw_if_index == i->sw_if_index))
308 snat_session_t ** sessionp,
317 u32 address_index = ~0;
318 u32 outside_fib_index;
325 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
334 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_OUTSIDE_FIB];
337 outside_fib_index = p[0];
359 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
376 s->outside_address_index = address_index;
380 s->out2in.fib_index = outside_fib_index;
386 kv0.
key = s->in2out.as_u64;
392 kv0.
key = s->out2in.as_u64;
401 s->out2in.addr.as_u32,
405 s->in2out.fib_index);
413 icmp46_header_t *icmp0;
418 icmp46_header_t *inner_icmp0;
437 case SNAT_PROTOCOL_ICMP:
438 inner_icmp0 = (icmp46_header_t*)l4_header;
442 case SNAT_PROTOCOL_UDP:
443 case SNAT_PROTOCOL_TCP:
447 return SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL;
472 u8 *p_dont_translate,
void *d,
void *e)
474 icmp46_header_t *icmp0;
478 snat_session_t *s0 = 0;
479 u8 dont_translate = 0;
514 ip0, SNAT_PROTOCOL_ICMP, rx_fib_index0, thread_index)))
523 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
528 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
529 &s0, node, next0, thread_index);
537 icmp0->type != ICMP4_echo_reply &&
540 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
552 *p_value = s0->out2in;
553 *p_dont_translate = dont_translate;
555 *(snat_session_t**)d = s0;
576 u8 *p_dont_translate,
void *d,
void *e)
578 icmp46_header_t *icmp0;
583 u8 dont_translate = 0;
604 IP_PROTOCOL_ICMP, rx_fib_index0)))
616 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
622 (icmp0->type != ICMP4_echo_reply || !is_addr_only) &&
625 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
634 *p_dont_translate = dont_translate;
641 icmp46_header_t * icmp0,
655 icmp46_header_t *inner_icmp0;
657 u32 new_addr0, old_addr0;
658 u16 old_id0, new_id0;
666 &protocol, &sm0, &dont_translate, d, e);
691 if (icmp0->checksum == 0)
692 icmp0->checksum = 0xffff;
703 sum0 = icmp0->checksum;
724 sum0 = icmp0->checksum;
731 case SNAT_PROTOCOL_ICMP:
732 inner_icmp0 = (icmp46_header_t*)l4_header;
739 sum0 = icmp0->checksum;
744 case SNAT_PROTOCOL_UDP:
745 case SNAT_PROTOCOL_TCP:
750 sum0 = icmp0->checksum;
791 u32 new_dst_addr0 = 0, old_dst_addr0, ti = 0, si;
792 u16 new_dst_port0, old_dst_port0;
805 new_dst_port0 = sm0.
port;
836 new_dst_addr0 = s0->in2out.addr.as_u32;
837 new_dst_port0 = s0->in2out.port;
851 old_dst_port0 = tcp0->dst;
856 tcp0->dst = new_dst_port0;
857 sum0 = tcp0->checksum;
874 sum0 = tcp0->checksum;
889 icmp46_header_t * icmp0,
894 u32 new_dst_addr0 = 0, old_dst_addr0, si, ti = 0;
904 key0.
port = icmp_id0;
942 new_dst_addr0 = s0->in2out.addr.as_u32;
945 sum0 = icmp0->checksum;
968 icmp46_header_t * icmp0,
975 snat_session_t ** p_s0)
977 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
978 next0, thread_index, p_s0, 0);
979 snat_session_t * s0 = *p_s0;
1001 u32 old_addr, new_addr;
1029 u32 old_addr, new_addr;
1063 int is_output_feature)
1065 u32 n_left_from, * from, * to_next;
1067 u32 pkts_processed = 0;
1070 u32 stats_node_index;
1080 while (n_left_from > 0)
1085 to_next, n_left_to_next);
1087 while (n_left_from >= 4 && n_left_to_next >= 2)
1092 u32 sw_if_index0, sw_if_index1;
1095 u32 new_addr0, old_addr0, new_addr1, old_addr1;
1096 u16 old_port0, new_port0, old_port1, new_port1;
1099 icmp46_header_t * icmp0, * icmp1;
1101 u32 rx_fib_index0, rx_fib_index1;
1103 snat_session_t * s0 = 0, * s1 = 0;
1105 u32 iph_offset0 = 0, iph_offset1 = 0;
1122 to_next[0] = bi0 = from[0];
1123 to_next[1] = bi1 = from[1];
1127 n_left_to_next -= 2;
1132 if (is_output_feature)
1133 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
1140 icmp0 = (icmp46_header_t *) udp0;
1152 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1168 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
1176 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
1177 node, next0, now, thread_index, &s0);
1183 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
1208 if (is_output_feature)
1217 ip0, proto0, rx_fib_index0, thread_index)))
1221 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
1222 &s0, node, next0, thread_index);
1236 b0->
flags |= VNET_BUFFER_F_IS_NATED;
1241 if (!is_output_feature)
1252 old_port0 = tcp0->src_port;
1253 tcp0->src_port = s0->out2in.port;
1254 new_port0 = tcp0->src_port;
1256 sum0 = tcp0->checksum;
1280 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
1294 if (is_output_feature)
1295 iph_offset1 =
vnet_buffer (b1)->ip.save_rewrite_length;
1302 icmp1 = (icmp46_header_t *) udp1;
1312 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1328 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
1336 (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
1337 next1, now, thread_index, &s1);
1343 if (
PREDICT_FALSE (proto1 == ~0 || proto1 == SNAT_PROTOCOL_ICMP))
1368 if (is_output_feature)
1377 ip1, proto1, rx_fib_index1, thread_index)))
1381 next1 =
slow_path (sm, b1, ip1, rx_fib_index1, &key1,
1382 &s1, node, next1, thread_index);
1396 b1->
flags |= VNET_BUFFER_F_IS_NATED;
1401 if (!is_output_feature)
1412 old_port1 = tcp1->src_port;
1413 tcp1->src_port = s1->out2in.port;
1414 new_port1 = tcp1->src_port;
1416 sum1 = tcp1->checksum;
1440 && (b1->
flags & VLIB_BUFFER_IS_TRACED)))
1455 to_next, n_left_to_next,
1456 bi0, bi1, next0, next1);
1459 while (n_left_from > 0 && n_left_to_next > 0)
1467 u32 new_addr0, old_addr0;
1468 u16 old_port0, new_port0;
1471 icmp46_header_t * icmp0;
1475 snat_session_t * s0 = 0;
1477 u32 iph_offset0 = 0;
1485 n_left_to_next -= 1;
1490 if (is_output_feature)
1491 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
1498 icmp0 = (icmp46_header_t *) udp0;
1508 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1524 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
1532 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1533 next0, now, thread_index, &s0);
1539 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
1564 if (is_output_feature)
1573 ip0, proto0, rx_fib_index0, thread_index)))
1577 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
1578 &s0, node, next0, thread_index);
1593 b0->
flags |= VNET_BUFFER_F_IS_NATED;
1598 if (!is_output_feature)
1609 old_port0 = tcp0->src_port;
1610 tcp0->src_port = s0->out2in.port;
1611 new_port0 = tcp0->src_port;
1613 sum0 = tcp0->checksum;
1637 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
1653 to_next, n_left_to_next,
1661 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
1676 .name =
"nat44-in2out",
1677 .vector_size =
sizeof (
u32),
1710 .name =
"nat44-in2out-output",
1711 .vector_size =
sizeof (
u32),
1745 .name =
"nat44-in2out-slowpath",
1746 .vector_size =
sizeof (
u32),
1780 .name =
"nat44-in2out-output-slowpath",
1781 .vector_size =
sizeof (
u32),
1813 u32 n_left_from, * from, * to_next, stats_node_index;
1815 u32 pkts_processed = 0;
1827 while (n_left_from > 0)
1832 to_next, n_left_to_next);
1834 while (n_left_from > 0 && n_left_to_next > 0)
1850 n_left_to_next -= 1;
1869 to_next, n_left_to_next,
1877 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
1892 .name =
"nat44-hairpinning",
1893 .vector_size =
sizeof (
u32),
1917 .name =
"nat44-ed-hairpinning",
1918 .vector_size =
sizeof (
u32),
1941 snat_session_t * s0;
1944 u32 new_dst_addr0 = 0, old_dst_addr0, ti = 0, si;
1945 u16 new_dst_port0, old_dst_port0;
1961 new_dst_port0 = sm0.
port;
1976 new_dst_addr0 = s0->in2out.addr.as_u32;
1977 new_dst_port0 = s0->in2out.port;
1992 old_dst_port0 = dport;
1999 tcp0->dst = new_dst_port0;
2000 sum0 = tcp0->checksum;
2018 sum0 = tcp0->checksum;
2032 u32 n_left_from, *from, *to_next;
2034 u32 pkts_processed = 0;
2040 u32 *fragments_to_drop = 0;
2041 u32 *fragments_to_loopback = 0;
2047 while (n_left_from > 0)
2053 while (n_left_from > 0 && n_left_to_next > 0)
2055 u32 bi0, sw_if_index0, proto0, rx_fib_index0, new_addr0, old_addr0;
2060 nat_reass_ip4_t *reass0;
2065 snat_session_t * s0 = 0;
2066 u16 old_port0, new_port0;
2075 n_left_to_next -= 1;
2087 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
2101 &fragments_to_drop);
2106 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_REASS];
2119 if (clib_bihash_search_8_8 (&per_thread_data->
in2out, &kv0, &value0))
2122 ip0, proto0, rx_fib_index0, thread_index)))
2125 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
2126 &s0, node, next0, thread_index);
2131 reass0->sess_index = s0 - per_thread_data->
sessions;
2137 reass0->sess_index = value0.
value;
2147 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_FRAG];
2156 reass0->sess_index);
2174 old_port0 = tcp0->src_port;
2175 tcp0->src_port = s0->out2in.port;
2176 new_port0 = tcp0->src_port;
2178 sum0 = tcp0->checksum;
2197 s0->ext_host_port, proto0);
2207 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
2227 to_next, n_left_to_next,
2231 if (n_left_from == 0 &&
vec_len (fragments_to_loopback))
2256 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
2260 &node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT],
2270 .name =
"nat44-in2out-reass",
2271 .vector_size =
sizeof (
u32),
2298 icmp46_header_t *icmp0;
2302 void *l4_header = 0;
2303 icmp46_header_t *inner_icmp0;
2310 key0.
proto = IP_PROTOCOL_ICMP;
2325 case SNAT_PROTOCOL_ICMP:
2326 inner_icmp0 = (icmp46_header_t*)l4_header;
2331 case SNAT_PROTOCOL_UDP:
2332 case SNAT_PROTOCOL_TCP:
2337 return SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL;
2349 snat_session_t ** sessionp,
2357 u8 lb = 0, is_sm = 0;
2358 u32 address_index = ~0;
2365 b->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
2381 thread_index, &key1,
2387 b->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
2414 s->outside_address_index = address_index;
2415 s->ext_host_addr = key->
r_addr;
2416 s->ext_host_port = key->
r_port;
2423 if (clib_bihash_add_del_16_8 (&tsm->
in2out_ed, kv, 1))
2429 if (clib_bihash_add_del_16_8 (&tsm->
out2in_ed, kv, 1))
2436 s->out2in.addr.as_u32,
2440 s->in2out.fib_index);
2447 u32 rx_fib_index,
u32 thread_index)
2459 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &kv, &value))
2480 u32 thread_index,
f64 now,
2486 snat_session_t *s = 0;
2492 if (ip->
protocol == IP_PROTOCOL_ICMP)
2501 else if (ip->
protocol == IP_PROTOCOL_UDP || ip->
protocol == IP_PROTOCOL_TCP)
2513 if (!clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv, &value))
2518 if (ip->
protocol == IP_PROTOCOL_TCP)
2540 u8 proto,
u16 src_port,
u16 dst_port,
2541 u32 thread_index,
u32 sw_if_index)
2550 if (!clib_bihash_search_16_8 (&tsm->
out2in_ed, &kv, &value))
2556 if (!clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv, &value))
2561 if ((nat_interface_is_inside(i)) && (sw_if_index == i->sw_if_index))
2574 u8 *p_dont_translate,
void *d,
void *e)
2576 icmp46_header_t *icmp;
2580 snat_session_t *s = 0;
2581 u8 dont_translate = 0;
2604 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv, &value))
2618 ip, SNAT_PROTOCOL_ICMP, rx_fib_index, thread_index)))
2627 b->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
2632 next =
slow_path_ed (sm, b, rx_fib_index, &kv, &s, node, next,
2641 icmp->type != ICMP4_echo_reply &&
2644 b->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
2655 *p_value = s->out2in;
2656 *p_dont_translate = dont_translate;
2658 *(snat_session_t**)d = s;
2667 u32 old_addr, new_addr = 0, ti = 0;
2684 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &s_kv, &s_value))
2707 static snat_session_t *
2720 u32 old_addr, new_addr = 0;
2725 u32 elt_index, head_index, ses_index;
2727 u32 address_index = ~0;
2734 rx_fib_index, 0, 0);
2736 if (!clib_bihash_search_16_8 (&tsm->
in2out_ed, &s_kv, &s_value))
2745 b->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
2775 elt_index = head->
next;
2781 ses_index = elt->
value;
2784 while (ses_index != ~0)
2787 elt_index = elt->
next;
2789 ses_index = elt->
value;
2794 address_index = s->outside_address_index;
2798 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &s_kv, &s_value))
2809 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &s_kv, &s_value))
2831 s->outside_address_index = address_index;
2832 s->out2in.addr.as_u32 = new_addr;
2834 s->in2out.addr.as_u32 = old_addr;
2835 s->in2out.fib_index = rx_fib_index;
2836 s->in2out.port = s->out2in.port = ip->
protocol;
2843 rx_fib_index, 0, 0);
2845 if (clib_bihash_add_del_16_8 (&tsm->
in2out_ed, &s_kv, 1))
2851 if (clib_bihash_add_del_16_8 (&tsm->
out2in_ed, &s_kv, 1))
2879 int is_output_feature)
2881 u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
2895 while (n_left_from > 0)
2901 while (n_left_from >= 4 && n_left_to_next >= 2)
2905 u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
2906 new_addr0, old_addr0;
2907 u32 next1, sw_if_index1, rx_fib_index1, iph_offset1 = 0, proto1,
2908 new_addr1, old_addr1;
2909 u16 old_port0, new_port0, old_port1, new_port1;
2913 icmp46_header_t *icmp0, *icmp1;
2914 snat_session_t *s0 = 0, *s1 = 0;
2933 to_next[0] = bi0 = from[0];
2934 to_next[1] = bi1 = from[1];
2938 n_left_to_next -= 2;
2945 if (is_output_feature)
2946 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
2959 ICMP4_time_exceeded_ttl_exceeded_in_transit,
2967 icmp0 = (icmp46_header_t *) udp0;
2976 thread_index, now, vm,
2986 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
2987 next0, now, thread_index, &s0);
2993 if (is_output_feature)
2996 sm, ip0, thread_index, now, vm, b0)))
3000 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
3008 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
3017 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv0, &value0))
3021 if (is_output_feature)
3025 udp0->
dst_port, thread_index, sw_if_index0)))
3031 sw_if_index0, ip0, proto0, rx_fib_index0,
3036 next0 =
slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
3037 next0, thread_index);
3053 b0->
flags |= VNET_BUFFER_F_IS_NATED;
3055 if (!is_output_feature)
3071 old_port0 = tcp0->src_port;
3072 new_port0 = tcp0->src_port = s0->out2in.port;
3074 sum0 = tcp0->checksum;
3082 s0->ext_host_addr.as_u32,
3087 tcp0->dst_port = s0->ext_host_port;
3100 udp0->
dst_port = s0->ext_host_port;
3113 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
3130 if (is_output_feature)
3131 iph_offset1 =
vnet_buffer (b1)->ip.save_rewrite_length;
3144 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3152 icmp1 = (icmp46_header_t *) udp1;
3161 thread_index, now, vm,
3171 (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
3172 next1, now, thread_index, &s1);
3178 if (is_output_feature)
3181 sm, ip1, thread_index, now, vm, b1)))
3185 if (
PREDICT_FALSE (proto1 == ~0 || proto1 == SNAT_PROTOCOL_ICMP))
3193 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
3202 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv1, &value1))
3206 if (is_output_feature)
3210 udp1->
dst_port, thread_index, sw_if_index1)))
3216 sw_if_index1, ip1, proto1, rx_fib_index1,
3221 next1 =
slow_path_ed (sm, b1, rx_fib_index1, &kv1, &s1, node,
3222 next1, thread_index);
3238 b1->
flags |= VNET_BUFFER_F_IS_NATED;
3240 if (!is_output_feature)
3256 old_port1 = tcp1->src_port;
3257 new_port1 = tcp1->src_port = s1->out2in.port;
3259 sum1 = tcp1->checksum;
3267 s1->ext_host_addr.as_u32,
3272 tcp1->dst_port = s1->ext_host_port;
3285 udp1->
dst_port = s1->ext_host_port;
3298 && (b1->
flags & VLIB_BUFFER_IS_TRACED)))
3314 to_next, n_left_to_next,
3315 bi0, bi1, next0, next1);
3318 while (n_left_from > 0 && n_left_to_next > 0)
3322 u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
3323 new_addr0, old_addr0;
3324 u16 old_port0, new_port0;
3328 icmp46_header_t * icmp0;
3329 snat_session_t *s0 = 0;
3339 n_left_to_next -= 1;
3344 if (is_output_feature)
3345 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
3358 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3366 icmp0 = (icmp46_header_t *) udp0;
3375 thread_index, now, vm,
3385 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
3386 next0, now, thread_index, &s0);
3392 if (is_output_feature)
3395 sm, ip0, thread_index, now, vm, b0)))
3399 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
3407 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
3416 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv0, &value0))
3420 if (is_output_feature)
3424 udp0->
dst_port, thread_index, sw_if_index0)))
3430 sw_if_index0, ip0, proto0, rx_fib_index0,
3435 next0 =
slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
3436 next0, thread_index);
3452 b0->
flags |= VNET_BUFFER_F_IS_NATED;
3454 if (!is_output_feature)
3470 old_port0 = tcp0->src_port;
3471 new_port0 = tcp0->src_port = s0->out2in.port;
3473 sum0 = tcp0->checksum;
3481 s0->ext_host_addr.as_u32,
3486 tcp0->dst_port = s0->ext_host_port;
3499 udp0->
dst_port = s0->ext_host_port;
3512 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
3528 to_next, n_left_to_next,
3536 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
3551 .name =
"nat44-ed-in2out",
3552 .vector_size =
sizeof (
u32),
3585 .name =
"nat44-ed-in2out-output",
3586 .vector_size =
sizeof (
u32),
3620 .name =
"nat44-ed-in2out-slowpath",
3621 .vector_size =
sizeof (
u32),
3655 .name =
"nat44-ed-in2out-output-slowpath",
3656 .vector_size =
sizeof (
u32),
3688 u32 n_left_from, * from, * to_next;
3690 u32 pkts_processed = 0;
3699 while (n_left_from > 0)
3704 to_next, n_left_to_next);
3706 while (n_left_from >= 4 && n_left_to_next >= 2)
3711 u32 sw_if_index0, sw_if_index1;
3715 u16 old_port0, new_port0, lo_port0, i0;
3716 u16 old_port1, new_port1, lo_port1, i1;
3723 u32 rx_fib_index0, rx_fib_index1;
3724 icmp46_header_t * icmp0, * icmp1;
3741 to_next[0] = bi0 = from[0];
3742 to_next[1] = bi1 = from[1];
3746 n_left_to_next -= 2;
3764 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3775 icmp0 = (icmp46_header_t *) udp0;
3777 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
3778 rx_fib_index0, node, next0, thread_index,
3789 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
3803 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
3804 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
3818 ICMP4_destination_unreachable_destination_unreachable_host,
3840 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
3841 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
3842 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
3843 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
3844 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
3845 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
3847 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
3848 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
3849 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
3850 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
3852 old_port0 = tcp0->src;
3853 tcp0->src = new_port0;
3855 sum0 = tcp0->checksum;
3866 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
3874 case SNAT_SESSION_UDP_ACTIVE:
3877 case SNAT_SESSION_TCP_SYN_SENT:
3878 case SNAT_SESSION_TCP_FIN_WAIT:
3879 case SNAT_SESSION_TCP_CLOSE_WAIT:
3880 case SNAT_SESSION_TCP_LAST_ACK:
3883 case SNAT_SESSION_TCP_ESTABLISHED:
3890 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
3914 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3925 icmp1 = (icmp46_header_t *) udp1;
3927 next1 =
icmp_in2out(sm, b1, ip1, icmp1, sw_if_index1,
3928 rx_fib_index1, node, next1, thread_index,
3939 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
3953 key1.
out_port = clib_host_to_net_u16 (lo_port1 +
3954 ((i1 + clib_net_to_host_u16 (tcp1->src)) % dm1->
ports_per_host));
3968 ICMP4_destination_unreachable_destination_unreachable_host,
3975 new_port1 = ses1->out.out_port;
3990 ses1->state = SNAT_SESSION_TCP_SYN_SENT;
3991 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_SYN_SENT)
3992 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
3993 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_ESTABLISHED)
3994 ses1->state = SNAT_SESSION_TCP_FIN_WAIT;
3995 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_FIN_WAIT)
3997 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_CLOSE_WAIT)
3998 ses1->state = SNAT_SESSION_TCP_LAST_ACK;
3999 else if (tcp1->flags == 0 && ses1->state == SNAT_SESSION_UNKNOWN)
4000 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
4002 old_port1 = tcp1->src;
4003 tcp1->src = new_port1;
4005 sum1 = tcp1->checksum;
4016 ses1->state = SNAT_SESSION_UDP_ACTIVE;
4024 case SNAT_SESSION_UDP_ACTIVE:
4027 case SNAT_SESSION_TCP_SYN_SENT:
4028 case SNAT_SESSION_TCP_FIN_WAIT:
4029 case SNAT_SESSION_TCP_CLOSE_WAIT:
4030 case SNAT_SESSION_TCP_LAST_ACK:
4033 case SNAT_SESSION_TCP_ESTABLISHED:
4040 && (b1->
flags & VLIB_BUFFER_IS_TRACED)))
4056 to_next, n_left_to_next,
4057 bi0, bi1, next0, next1);
4060 while (n_left_from > 0 && n_left_to_next > 0)
4069 u16 old_port0, new_port0, lo_port0, i0;
4077 icmp46_header_t * icmp0;
4085 n_left_to_next -= 1;
4100 ICMP4_time_exceeded_ttl_exceeded_in_transit,
4111 icmp0 = (icmp46_header_t *) udp0;
4113 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
4114 rx_fib_index0, node, next0, thread_index,
4125 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
4139 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
4140 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
4154 ICMP4_destination_unreachable_destination_unreachable_host,
4176 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
4177 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
4178 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
4179 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
4180 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
4181 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
4183 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
4184 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
4185 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
4186 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
4188 old_port0 = tcp0->src;
4189 tcp0->src = new_port0;
4191 sum0 = tcp0->checksum;
4202 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
4210 case SNAT_SESSION_UDP_ACTIVE:
4213 case SNAT_SESSION_TCP_SYN_SENT:
4214 case SNAT_SESSION_TCP_FIN_WAIT:
4215 case SNAT_SESSION_TCP_CLOSE_WAIT:
4216 case SNAT_SESSION_TCP_LAST_ACK:
4219 case SNAT_SESSION_TCP_ESTABLISHED:
4226 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
4242 to_next, n_left_to_next,
4250 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
4257 .name =
"nat44-det-in2out",
4258 .vector_size =
sizeof (
u32),
4297 u8 *p_dont_translate,
void *d,
void *e)
4299 icmp46_header_t *icmp0;
4304 u8 dont_translate = 0;
4308 void *l4_header = 0;
4309 icmp46_header_t *inner_icmp0;
4324 protocol = SNAT_PROTOCOL_ICMP;
4336 case SNAT_PROTOCOL_ICMP:
4337 inner_icmp0 = (icmp46_header_t*)l4_header;
4341 case SNAT_PROTOCOL_UDP:
4342 case SNAT_PROTOCOL_TCP:
4346 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
4358 IP_PROTOCOL_ICMP, rx_fib_index0)))
4364 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
4377 IP_PROTOCOL_ICMP, rx_fib_index0)))
4382 if (icmp0->type != ICMP4_echo_request)
4384 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
4390 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
4402 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
4410 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
4417 ses0->
state = SNAT_SESSION_ICMP_ACTIVE;
4421 *p_proto = protocol;
4424 p_value->
addr = new_addr0;
4428 *p_dont_translate = dont_translate;
4447 u32 n_left_from, *from, *to_next = 0, *to_next_drop = 0;
4455 u32 n_left_to_next_worker = 0, *to_next_worker = 0;
4456 u32 next_worker_index = 0;
4457 u32 current_worker_index = ~0;
4488 while (n_left_from > 0)
4514 if (next_worker_index != current_worker_index)
4518 congested_handoff_queue_by_worker_index);
4529 to_next_drop[0] = bi0;
4532 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_FQ_CONGESTED];
4541 handoff_queue_elt_by_worker_index);
4545 current_worker_index = next_worker_index;
4549 to_next_worker[0] = bi0;
4551 n_left_to_next_worker--;
4553 if (n_left_to_next_worker == 0)
4557 current_worker_index = ~0;
4558 handoff_queue_elt_by_worker_index[next_worker_index] = 0;
4579 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
4598 for (i = 0; i <
vec_len (handoff_queue_elt_by_worker_index); i++)
4600 if (handoff_queue_elt_by_worker_index[i])
4602 hf = handoff_queue_elt_by_worker_index[
i];
4610 handoff_queue_elt_by_worker_index[
i] = 0;
4615 congested_handoff_queue_by_worker_index[
i] =
4619 current_worker_index = ~0;
4633 .name =
"nat44-in2out-worker-handoff",
4634 .vector_size =
sizeof (
u32),
4661 .name =
"nat44-in2out-output-worker-handoff",
4662 .vector_size =
sizeof (
u32),
4706 u32 n_left_from, * from, * to_next, stats_node_index;
4708 u32 pkts_processed = 0;
4718 while (n_left_from > 0)
4723 to_next, n_left_to_next);
4725 while (n_left_from > 0 && n_left_to_next > 0)
4739 n_left_to_next -= 1;
4750 if (proto0 == SNAT_PROTOCOL_TCP || proto0 == SNAT_PROTOCOL_UDP)
4757 else if (proto0 == SNAT_PROTOCOL_ICMP)
4778 to_next, n_left_to_next,
4786 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
4801 .name =
"nat44-hairpin-dst",
4802 .vector_size =
sizeof (
u32),
4826 .name =
"nat44-ed-hairpin-dst",
4827 .vector_size =
sizeof (
u32),
4847 u32 n_left_from, * from, * to_next, stats_node_index;
4849 u32 pkts_processed = 0;
4859 while (n_left_from > 0)
4864 to_next, n_left_to_next);
4866 while (n_left_from > 0 && n_left_to_next > 0)
4880 n_left_to_next -= 1;
4889 if ((nat_interface_is_inside(i)) && (sw_if_index0 == i->sw_if_index))
4891 if (PREDICT_FALSE ((vnet_buffer (b0)->snat.flags) &
4892 SNAT_FLAG_HAIRPINNING))
4894 if (PREDICT_TRUE (sm->num_workers > 1))
4895 next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH;
4897 next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT;
4907 to_next, n_left_to_next,
4915 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
4917 return frame->n_vectors;
4930 .name =
"nat44-hairpin-src",
4931 .vector_size =
sizeof (
u32),
4957 .name =
"nat44-ed-hairpin-src",
4958 .vector_size =
sizeof (
u32),
4979 u32 n_left_from, * from, * to_next;
4981 u32 pkts_processed = 0;
4983 u32 stats_node_index;
4991 while (n_left_from > 0)
4996 to_next, n_left_to_next);
4998 while (n_left_from > 0 && n_left_to_next > 0)
5006 u32 new_addr0, old_addr0;
5007 u16 old_port0, new_port0;
5010 icmp46_header_t * icmp0;
5021 n_left_to_next -= 1;
5029 icmp0 = (icmp46_header_t *) udp0;
5038 ICMP4_time_exceeded_ttl_exceeded_in_transit,
5051 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
5052 rx_fib_index0, node, next0, ~0, 0, 0);
5063 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
5069 new_port0 = sm0.
port;
5084 old_port0 = tcp0->src_port;
5085 tcp0->src_port = new_port0;
5087 sum0 = tcp0->checksum;
5107 sum0 = tcp0->checksum;
5120 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
5132 to_next, n_left_to_next,
5140 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
5148 .name =
"nat44-in2out-fast",
5149 .vector_size =
sizeof (
u32),
ip4_address_t external_addr
void nat_ipfix_logging_max_sessions(u32 limit)
Generate maximum session entries exceeded event.
vnet_config_main_t config_main
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
fib_protocol_t fp_proto
protocol type
#define nat_log_info(...)
static uword nat44_ed_hairpinning_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
u32 sessions_per_user_list_head_index
static u8 * format_snat_in2out_trace(u8 *s, va_list *args)
static u32 slow_path_ed(snat_main_t *sm, vlib_buffer_t *b, u32 rx_fib_index, clib_bihash_kv_16_8_t *kv, snat_session_t **sessionp, vlib_node_runtime_t *node, u32 next, u32 thread_index)
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)
vlib_node_registration_t nat44_ed_in2out_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_node)
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
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.
static void make_sm_kv(clib_bihash_kv_8_8_t *kv, ip4_address_t *addr, u8 proto, u32 fib_index, u16 port)
int nat_ip4_reass_add_fragment(nat_reass_ip4_t *reass, u32 bi)
Cache fragment.
static uword snat_hairpin_dst_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_ed)
static uword snat_in2out_worker_handoff_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define nat_log_warn(...)
static void snat_det_ses_close(snat_det_map_t *dm, snat_det_session_t *ses)
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)
vlib_node_registration_t nat44_ed_in2out_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_node)
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
static uword nat44_ed_hairpin_src_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
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.
static vlib_frame_queue_t * is_vlib_frame_queue_congested(u32 frame_queue_index, u32 index, u32 queue_hi_thresh, vlib_frame_queue_t **handoff_queue_by_worker_index)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
vlib_node_registration_t snat_hairpin_dst_node
(constructor) VLIB_REGISTER_NODE (snat_hairpin_dst_node)
static void snat_icmp_hairpinning(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0, int is_ed)
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)
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)
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)
static_always_inline int nat44_ed_not_translate(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index, ip4_header_t *ip, u32 proto, u32 rx_fib_index, 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)
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, twice_nat_type_t *twice_nat, u8 *lb)
Match NAT44 static mapping.
Aggregrate type for a prefix.
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
#define is_fwd_bypass_session(s)
Check if NAT session is forwarding bypass.
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)
static uword nat44_hairpinning_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_ed)
vlib_node_registration_t snat_in2out_slowpath_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_slowpath_node)
vlib_node_registration_t nat44_ed_in2out_output_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_output_slowpath_node)
static void nat_hairpinning_sm_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip)
static uword snat_in2out_worker_handoff_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u8 is_output)
static_always_inline int nat44_ed_not_translate_output_feature(snat_main_t *sm, ip4_header_t *ip, u8 proto, u16 src_port, u16 dst_port, u32 thread_index, u32 sw_if_index)
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.
vlib_node_registration_t nat44_ed_hairpin_dst_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_hairpin_dst_node)
static u8 maximum_sessions_exceeded(snat_main_t *sm, u32 thread_index)
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_always_inline int nat_not_translate_output_feature_fwd(snat_main_t *sm, ip4_header_t *ip, u32 thread_index, f64 now, vlib_main_t *vm, vlib_buffer_t *b)
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.
clib_bihash_16_8_t out2in_ed
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 uword nat44_ed_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)
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
static snat_session_t * nat44_ed_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)
vlib_node_registration_t nat44_ed_hairpin_src_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_hairpin_src_node)
static uword nat44_ed_in2out_fast_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#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).
static void nat44_ed_hairpinning_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip)
#define nat_log_notice(...)
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
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)
static int nat_in2out_sm_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index)
vlib_node_registration_t nat44_in2out_reass_node
(constructor) VLIB_REGISTER_NODE (nat44_in2out_reass_node)
#define VLIB_REGISTER_NODE(x,...)
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
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
#define clib_memcpy(a, b, c)
static int ip4_is_first_fragment(ip4_header_t *i)
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes)
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.
static uword nat44_ed_in2out_output_fast_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
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.
static void make_ed_kv(clib_bihash_kv_16_8_t *kv, ip4_address_t *l_addr, ip4_address_t *r_addr, u8 proto, u32 fib_index, u16 l_port, u16 r_port)
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
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, int is_ed)
Hairpinning.
static int nat44_set_tcp_session_state_i2o(snat_main_t *sm, snat_session_t *ses, tcp_header_t *tcp, u32 thread_index)
Set TCP session state.
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)
static uword nat44_ed_hairpin_dst_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
snat_get_worker_function_t * worker_out2in_cb
static void nat44_session_update_lru(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Per-user LRU list maintenance.
#define SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT
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.
struct _vlib_node_registration vlib_node_registration_t
static uword snat_hairpin_src_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_ed)
static uword snat_hairpin_src_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static u32 ip_proto_to_snat_proto(u8 ip_proto)
The NAT inline functions.
#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)
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
vlib_node_registration_t nat44_ed_hairpinning_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_hairpinning_node)
#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)
snat_main_per_thread_data_t * per_thread_data
#define SNAT_FLAG_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)
static u8 is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr)
vlib_node_registration_t snat_hairpin_src_node
(constructor) VLIB_REGISTER_NODE (snat_hairpin_src_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
u32 icmp_match_in2out_ed(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b, ip4_header_t *ip, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
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)
u16 flags
Copy of main node flags.
static void nat_send_all_to_node(vlib_main_t *vm, u32 *bi_vector, vlib_node_runtime_t *node, vlib_error_t *error, u32 next)
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
clib_bihash_16_8_t in2out_ed
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.
#define VLIB_NODE_FLAG_TRACE
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.
vlib_node_registration_t nat44_ed_in2out_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ed_in2out_slowpath_node)
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)
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 uword nat44_ed_in2out_output_slow_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static uword nat44_ed_in2out_slow_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
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)