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, 212 if (sw_if_index == ~0)
220 if (sw_if_index != ~0)
225 if (sw_if_index == ~0)
232 if ((nat_interface_is_outside(i)) && (sw_if_index == i->sw_if_index))
243 u32 rx_fib_index0,
u32 thread_index)
277 u32 thread_index,
u32 sw_if_index)
285 key0.
port = src_port;
296 key0.
port = dst_port;
305 if ((nat_interface_is_inside(i)) && (sw_if_index == i->sw_if_index))
318 snat_session_t ** sessionp,
327 u32 address_index = ~0;
342 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
368 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
385 s->outside_address_index = address_index;
406 s->out2in.fib_index = outside_fib->
fib_index;
418 kv0.
key = s->in2out.as_u64;
424 kv0.
key = s->out2in.as_u64;
433 s->out2in.addr.as_u32,
437 s->in2out.fib_index);
445 icmp46_header_t *icmp0;
450 icmp46_header_t *inner_icmp0;
469 case SNAT_PROTOCOL_ICMP:
470 inner_icmp0 = (icmp46_header_t*)l4_header;
474 case SNAT_PROTOCOL_UDP:
475 case SNAT_PROTOCOL_TCP:
479 return SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL;
504 u8 *p_dont_translate,
void *d,
void *e)
506 icmp46_header_t *icmp0;
510 snat_session_t *s0 = 0;
511 u8 dont_translate = 0;
546 ip0, SNAT_PROTOCOL_ICMP, rx_fib_index0, thread_index)))
555 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
560 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
561 &s0, node, next0, thread_index);
569 icmp0->type != ICMP4_echo_reply &&
572 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
584 *p_value = s0->out2in;
585 *p_dont_translate = dont_translate;
587 *(snat_session_t**)d = s0;
608 u8 *p_dont_translate,
void *d,
void *e)
610 icmp46_header_t *icmp0;
615 u8 dont_translate = 0;
636 IP_PROTOCOL_ICMP, rx_fib_index0)))
648 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
654 (icmp0->type != ICMP4_echo_reply || !is_addr_only) &&
657 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
666 *p_dont_translate = dont_translate;
673 icmp46_header_t * icmp0,
687 icmp46_header_t *inner_icmp0;
689 u32 new_addr0, old_addr0;
690 u16 old_id0, new_id0;
698 &protocol, &sm0, &dont_translate, d, e);
723 if (icmp0->checksum == 0)
724 icmp0->checksum = 0xffff;
735 sum0 = icmp0->checksum;
756 sum0 = icmp0->checksum;
763 case SNAT_PROTOCOL_ICMP:
764 inner_icmp0 = (icmp46_header_t*)l4_header;
771 sum0 = icmp0->checksum;
776 case SNAT_PROTOCOL_UDP:
777 case SNAT_PROTOCOL_TCP:
782 sum0 = icmp0->checksum;
823 u32 new_dst_addr0 = 0, old_dst_addr0, ti = 0, si;
824 u16 new_dst_port0, old_dst_port0;
837 new_dst_port0 = sm0.
port;
868 new_dst_addr0 = s0->in2out.addr.as_u32;
869 new_dst_port0 = s0->in2out.port;
883 old_dst_port0 = tcp0->dst;
888 tcp0->dst = new_dst_port0;
889 sum0 = tcp0->checksum;
906 sum0 = tcp0->checksum;
921 icmp46_header_t * icmp0,
926 u32 new_dst_addr0 = 0, old_dst_addr0, si, ti = 0;
936 key0.
port = icmp_id0;
974 new_dst_addr0 = s0->in2out.addr.as_u32;
977 sum0 = icmp0->checksum;
1000 icmp46_header_t * icmp0,
1007 snat_session_t ** p_s0)
1009 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1010 next0, thread_index, p_s0, 0);
1011 snat_session_t * s0 = *p_s0;
1033 u32 old_addr, new_addr;
1061 u32 old_addr, new_addr;
1095 int is_output_feature)
1097 u32 n_left_from, * from, * to_next;
1099 u32 pkts_processed = 0;
1102 u32 stats_node_index;
1112 while (n_left_from > 0)
1117 to_next, n_left_to_next);
1119 while (n_left_from >= 4 && n_left_to_next >= 2)
1124 u32 sw_if_index0, sw_if_index1;
1127 u32 new_addr0, old_addr0, new_addr1, old_addr1;
1128 u16 old_port0, new_port0, old_port1, new_port1;
1131 icmp46_header_t * icmp0, * icmp1;
1133 u32 rx_fib_index0, rx_fib_index1;
1135 snat_session_t * s0 = 0, * s1 = 0;
1137 u32 iph_offset0 = 0, iph_offset1 = 0;
1154 to_next[0] = bi0 = from[0];
1155 to_next[1] = bi1 = from[1];
1159 n_left_to_next -= 2;
1164 if (is_output_feature)
1165 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
1172 icmp0 = (icmp46_header_t *) udp0;
1184 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1200 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
1208 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
1209 node, next0, now, thread_index, &s0);
1215 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
1240 if (is_output_feature)
1249 ip0, proto0, rx_fib_index0, thread_index)))
1253 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
1254 &s0, node, next0, thread_index);
1268 b0->
flags |= VNET_BUFFER_F_IS_NATED;
1273 if (!is_output_feature)
1284 old_port0 = tcp0->src_port;
1285 tcp0->src_port = s0->out2in.port;
1286 new_port0 = tcp0->src_port;
1288 sum0 = tcp0->checksum;
1312 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
1326 if (is_output_feature)
1327 iph_offset1 =
vnet_buffer (b1)->ip.save_rewrite_length;
1334 icmp1 = (icmp46_header_t *) udp1;
1344 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1360 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
1368 (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
1369 next1, now, thread_index, &s1);
1375 if (
PREDICT_FALSE (proto1 == ~0 || proto1 == SNAT_PROTOCOL_ICMP))
1400 if (is_output_feature)
1409 ip1, proto1, rx_fib_index1, thread_index)))
1413 next1 =
slow_path (sm, b1, ip1, rx_fib_index1, &key1,
1414 &s1, node, next1, thread_index);
1428 b1->
flags |= VNET_BUFFER_F_IS_NATED;
1433 if (!is_output_feature)
1444 old_port1 = tcp1->src_port;
1445 tcp1->src_port = s1->out2in.port;
1446 new_port1 = tcp1->src_port;
1448 sum1 = tcp1->checksum;
1472 && (b1->
flags & VLIB_BUFFER_IS_TRACED)))
1487 to_next, n_left_to_next,
1488 bi0, bi1, next0, next1);
1491 while (n_left_from > 0 && n_left_to_next > 0)
1499 u32 new_addr0, old_addr0;
1500 u16 old_port0, new_port0;
1503 icmp46_header_t * icmp0;
1507 snat_session_t * s0 = 0;
1509 u32 iph_offset0 = 0;
1517 n_left_to_next -= 1;
1522 if (is_output_feature)
1523 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
1530 icmp0 = (icmp46_header_t *) udp0;
1540 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1556 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
1564 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1565 next0, now, thread_index, &s0);
1571 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
1596 if (is_output_feature)
1605 ip0, proto0, rx_fib_index0, thread_index)))
1609 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
1610 &s0, node, next0, thread_index);
1625 b0->
flags |= VNET_BUFFER_F_IS_NATED;
1630 if (!is_output_feature)
1641 old_port0 = tcp0->src_port;
1642 tcp0->src_port = s0->out2in.port;
1643 new_port0 = tcp0->src_port;
1645 sum0 = tcp0->checksum;
1669 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
1685 to_next, n_left_to_next,
1693 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
1708 .name =
"nat44-in2out",
1709 .vector_size =
sizeof (
u32),
1742 .name =
"nat44-in2out-output",
1743 .vector_size =
sizeof (
u32),
1777 .name =
"nat44-in2out-slowpath",
1778 .vector_size =
sizeof (
u32),
1812 .name =
"nat44-in2out-output-slowpath",
1813 .vector_size =
sizeof (
u32),
1845 u32 n_left_from, * from, * to_next, stats_node_index;
1847 u32 pkts_processed = 0;
1859 while (n_left_from > 0)
1864 to_next, n_left_to_next);
1866 while (n_left_from > 0 && n_left_to_next > 0)
1882 n_left_to_next -= 1;
1901 to_next, n_left_to_next,
1909 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
1924 .name =
"nat44-hairpinning",
1925 .vector_size =
sizeof (
u32),
1949 .name =
"nat44-ed-hairpinning",
1950 .vector_size =
sizeof (
u32),
1973 snat_session_t * s0;
1976 u32 new_dst_addr0 = 0, old_dst_addr0, ti = 0, si;
1977 u16 new_dst_port0, old_dst_port0;
1993 new_dst_port0 = sm0.
port;
2008 new_dst_addr0 = s0->in2out.addr.as_u32;
2009 new_dst_port0 = s0->in2out.port;
2024 old_dst_port0 = dport;
2031 tcp0->dst = new_dst_port0;
2032 sum0 = tcp0->checksum;
2050 sum0 = tcp0->checksum;
2064 u32 n_left_from, *from, *to_next;
2066 u32 pkts_processed = 0;
2072 u32 *fragments_to_drop = 0;
2073 u32 *fragments_to_loopback = 0;
2079 while (n_left_from > 0)
2085 while (n_left_from > 0 && n_left_to_next > 0)
2087 u32 bi0, sw_if_index0, proto0, rx_fib_index0, new_addr0, old_addr0;
2092 nat_reass_ip4_t *reass0;
2097 snat_session_t * s0 = 0;
2098 u16 old_port0, new_port0;
2107 n_left_to_next -= 1;
2119 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
2133 &fragments_to_drop);
2138 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_REASS];
2151 if (clib_bihash_search_8_8 (&per_thread_data->
in2out, &kv0, &value0))
2154 ip0, proto0, rx_fib_index0, thread_index)))
2157 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
2158 &s0, node, next0, thread_index);
2163 reass0->sess_index = s0 - per_thread_data->
sessions;
2169 reass0->sess_index = value0.
value;
2179 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_FRAG];
2188 reass0->sess_index);
2206 old_port0 = tcp0->src_port;
2207 tcp0->src_port = s0->out2in.port;
2208 new_port0 = tcp0->src_port;
2210 sum0 = tcp0->checksum;
2229 s0->ext_host_port, proto0);
2239 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
2259 to_next, n_left_to_next,
2263 if (n_left_from == 0 &&
vec_len (fragments_to_loopback))
2288 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
2292 &node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT],
2302 .name =
"nat44-in2out-reass",
2303 .vector_size =
sizeof (
u32),
2330 icmp46_header_t *icmp0;
2334 void *l4_header = 0;
2335 icmp46_header_t *inner_icmp0;
2342 key0.
proto = IP_PROTOCOL_ICMP;
2357 case SNAT_PROTOCOL_ICMP:
2358 inner_icmp0 = (icmp46_header_t*)l4_header;
2363 case SNAT_PROTOCOL_UDP:
2364 case SNAT_PROTOCOL_TCP:
2369 return SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL;
2381 snat_session_t ** sessionp,
2389 u8 lb = 0, is_sm = 0;
2390 u32 address_index = ~0;
2406 b->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
2422 thread_index, &key1,
2428 b->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
2455 s->outside_address_index = address_index;
2456 s->ext_host_addr = key->
r_addr;
2457 s->ext_host_port = key->
r_port;
2478 s->out2in.fib_index = outside_fib->
fib_index;
2488 if (clib_bihash_add_del_16_8 (&tsm->
in2out_ed, kv, 1))
2494 if (clib_bihash_add_del_16_8 (&tsm->
out2in_ed, kv, 1))
2501 s->out2in.addr.as_u32,
2505 s->in2out.fib_index);
2512 u32 rx_fib_index,
u32 thread_index)
2524 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &kv, &value))
2545 u32 thread_index,
f64 now,
2551 snat_session_t *s = 0;
2557 if (ip->
protocol == IP_PROTOCOL_ICMP)
2566 else if (ip->
protocol == IP_PROTOCOL_UDP || ip->
protocol == IP_PROTOCOL_TCP)
2578 if (!clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv, &value))
2583 if (ip->
protocol == IP_PROTOCOL_TCP)
2605 u8 proto,
u16 src_port,
u16 dst_port,
2606 u32 thread_index,
u32 sw_if_index)
2616 src_port, dst_port);
2617 if (!clib_bihash_search_16_8 (&tsm->
out2in_ed, &kv, &value))
2622 dst_port, src_port);
2623 if (!clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv, &value))
2632 if ((nat_interface_is_inside(i)) && (sw_if_index == i->sw_if_index))
2645 u8 *p_dont_translate,
void *d,
void *e)
2647 icmp46_header_t *icmp;
2651 snat_session_t *s = 0;
2652 u8 dont_translate = 0;
2675 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv, &value))
2689 ip, SNAT_PROTOCOL_ICMP, rx_fib_index, thread_index)))
2698 b->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
2703 next =
slow_path_ed (sm, b, rx_fib_index, &kv, &s, node, next,
2712 icmp->type != ICMP4_echo_reply &&
2715 b->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
2726 *p_value = s->out2in;
2727 *p_dont_translate = dont_translate;
2729 *(snat_session_t**)d = s;
2738 u32 old_addr, new_addr = 0, ti = 0;
2755 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &s_kv, &s_value))
2778 static snat_session_t *
2791 u32 old_addr, new_addr = 0;
2796 u32 elt_index, head_index, ses_index;
2827 outside_fib_index = outside_fib->
fib_index;
2837 rx_fib_index, 0, 0);
2839 if (!clib_bihash_search_16_8 (&tsm->
in2out_ed, &s_kv, &s_value))
2848 b->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
2878 elt_index = head->
next;
2884 ses_index = elt->
value;
2887 while (ses_index != ~0)
2890 elt_index = elt->
next;
2892 ses_index = elt->
value;
2897 address_index = s->outside_address_index;
2900 ip->
protocol, outside_fib_index, 0, 0);
2901 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &s_kv, &s_value))
2911 ip->
protocol, outside_fib_index, 0, 0);
2912 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &s_kv, &s_value))
2934 s->outside_address_index = address_index;
2935 s->out2in.addr.as_u32 = new_addr;
2936 s->out2in.fib_index = outside_fib_index;
2937 s->in2out.addr.as_u32 = old_addr;
2938 s->in2out.fib_index = rx_fib_index;
2939 s->in2out.port = s->out2in.port = ip->
protocol;
2946 rx_fib_index, 0, 0);
2948 if (clib_bihash_add_del_16_8 (&tsm->
in2out_ed, &s_kv, 1))
2952 outside_fib_index, 0, 0);
2954 if (clib_bihash_add_del_16_8 (&tsm->
out2in_ed, &s_kv, 1))
2982 int is_output_feature)
2984 u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
2998 while (n_left_from > 0)
3004 while (n_left_from >= 4 && n_left_to_next >= 2)
3008 u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
3009 new_addr0, old_addr0;
3010 u32 next1, sw_if_index1, rx_fib_index1, iph_offset1 = 0, proto1,
3011 new_addr1, old_addr1;
3012 u16 old_port0, new_port0, old_port1, new_port1;
3016 icmp46_header_t *icmp0, *icmp1;
3017 snat_session_t *s0 = 0, *s1 = 0;
3036 to_next[0] = bi0 = from[0];
3037 to_next[1] = bi1 = from[1];
3041 n_left_to_next -= 2;
3048 if (is_output_feature)
3049 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
3062 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3070 icmp0 = (icmp46_header_t *) udp0;
3079 thread_index, now, vm,
3089 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
3090 next0, now, thread_index, &s0);
3096 if (is_output_feature)
3099 sm, ip0, thread_index, now, vm, b0)))
3103 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
3111 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
3120 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv0, &value0))
3124 if (is_output_feature)
3128 udp0->
dst_port, thread_index, sw_if_index0)))
3134 sw_if_index0, ip0, proto0, rx_fib_index0,
3139 next0 =
slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
3140 next0, thread_index);
3156 b0->
flags |= VNET_BUFFER_F_IS_NATED;
3158 if (!is_output_feature)
3174 old_port0 = tcp0->src_port;
3175 new_port0 = tcp0->src_port = s0->out2in.port;
3177 sum0 = tcp0->checksum;
3185 s0->ext_host_addr.as_u32,
3190 tcp0->dst_port = s0->ext_host_port;
3203 udp0->
dst_port = s0->ext_host_port;
3216 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
3233 if (is_output_feature)
3234 iph_offset1 =
vnet_buffer (b1)->ip.save_rewrite_length;
3247 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3255 icmp1 = (icmp46_header_t *) udp1;
3264 thread_index, now, vm,
3274 (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
3275 next1, now, thread_index, &s1);
3281 if (is_output_feature)
3284 sm, ip1, thread_index, now, vm, b1)))
3288 if (
PREDICT_FALSE (proto1 == ~0 || proto1 == SNAT_PROTOCOL_ICMP))
3296 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
3305 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv1, &value1))
3309 if (is_output_feature)
3313 udp1->
dst_port, thread_index, sw_if_index1)))
3319 sw_if_index1, ip1, proto1, rx_fib_index1,
3324 next1 =
slow_path_ed (sm, b1, rx_fib_index1, &kv1, &s1, node,
3325 next1, thread_index);
3341 b1->
flags |= VNET_BUFFER_F_IS_NATED;
3343 if (!is_output_feature)
3359 old_port1 = tcp1->src_port;
3360 new_port1 = tcp1->src_port = s1->out2in.port;
3362 sum1 = tcp1->checksum;
3370 s1->ext_host_addr.as_u32,
3375 tcp1->dst_port = s1->ext_host_port;
3388 udp1->
dst_port = s1->ext_host_port;
3401 && (b1->
flags & VLIB_BUFFER_IS_TRACED)))
3417 to_next, n_left_to_next,
3418 bi0, bi1, next0, next1);
3421 while (n_left_from > 0 && n_left_to_next > 0)
3425 u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
3426 new_addr0, old_addr0;
3427 u16 old_port0, new_port0;
3431 icmp46_header_t * icmp0;
3432 snat_session_t *s0 = 0;
3442 n_left_to_next -= 1;
3447 if (is_output_feature)
3448 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
3461 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3469 icmp0 = (icmp46_header_t *) udp0;
3478 thread_index, now, vm,
3488 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
3489 next0, now, thread_index, &s0);
3495 if (is_output_feature)
3498 sm, ip0, thread_index, now, vm, b0)))
3502 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
3510 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
3519 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv0, &value0))
3523 if (is_output_feature)
3527 udp0->
dst_port, thread_index, sw_if_index0)))
3533 sw_if_index0, ip0, proto0, rx_fib_index0,
3538 next0 =
slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
3539 next0, thread_index);
3555 b0->
flags |= VNET_BUFFER_F_IS_NATED;
3557 if (!is_output_feature)
3573 old_port0 = tcp0->src_port;
3574 new_port0 = tcp0->src_port = s0->out2in.port;
3576 sum0 = tcp0->checksum;
3584 s0->ext_host_addr.as_u32,
3589 tcp0->dst_port = s0->ext_host_port;
3602 udp0->
dst_port = s0->ext_host_port;
3615 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
3631 to_next, n_left_to_next,
3639 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
3654 .name =
"nat44-ed-in2out",
3655 .vector_size =
sizeof (
u32),
3688 .name =
"nat44-ed-in2out-output",
3689 .vector_size =
sizeof (
u32),
3723 .name =
"nat44-ed-in2out-slowpath",
3724 .vector_size =
sizeof (
u32),
3758 .name =
"nat44-ed-in2out-output-slowpath",
3759 .vector_size =
sizeof (
u32),
3791 u32 n_left_from, * from, * to_next;
3793 u32 pkts_processed = 0;
3802 while (n_left_from > 0)
3807 to_next, n_left_to_next);
3809 while (n_left_from >= 4 && n_left_to_next >= 2)
3814 u32 sw_if_index0, sw_if_index1;
3818 u16 old_port0, new_port0, lo_port0, i0;
3819 u16 old_port1, new_port1, lo_port1, i1;
3826 u32 rx_fib_index0, rx_fib_index1;
3827 icmp46_header_t * icmp0, * icmp1;
3844 to_next[0] = bi0 = from[0];
3845 to_next[1] = bi1 = from[1];
3849 n_left_to_next -= 2;
3867 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3878 icmp0 = (icmp46_header_t *) udp0;
3880 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
3881 rx_fib_index0, node, next0, thread_index,
3892 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
3906 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
3907 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
3921 ICMP4_destination_unreachable_destination_unreachable_host,
3943 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
3944 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
3945 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
3946 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
3947 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
3948 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
3950 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
3951 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
3952 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
3953 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
3955 old_port0 = tcp0->src;
3956 tcp0->src = new_port0;
3958 sum0 = tcp0->checksum;
3969 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
3977 case SNAT_SESSION_UDP_ACTIVE:
3980 case SNAT_SESSION_TCP_SYN_SENT:
3981 case SNAT_SESSION_TCP_FIN_WAIT:
3982 case SNAT_SESSION_TCP_CLOSE_WAIT:
3983 case SNAT_SESSION_TCP_LAST_ACK:
3986 case SNAT_SESSION_TCP_ESTABLISHED:
3993 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
4017 ICMP4_time_exceeded_ttl_exceeded_in_transit,
4028 icmp1 = (icmp46_header_t *) udp1;
4030 next1 =
icmp_in2out(sm, b1, ip1, icmp1, sw_if_index1,
4031 rx_fib_index1, node, next1, thread_index,
4042 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
4056 key1.
out_port = clib_host_to_net_u16 (lo_port1 +
4057 ((i1 + clib_net_to_host_u16 (tcp1->src)) % dm1->
ports_per_host));
4071 ICMP4_destination_unreachable_destination_unreachable_host,
4078 new_port1 = ses1->out.out_port;
4093 ses1->state = SNAT_SESSION_TCP_SYN_SENT;
4094 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_SYN_SENT)
4095 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
4096 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_ESTABLISHED)
4097 ses1->state = SNAT_SESSION_TCP_FIN_WAIT;
4098 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_FIN_WAIT)
4100 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_CLOSE_WAIT)
4101 ses1->state = SNAT_SESSION_TCP_LAST_ACK;
4102 else if (tcp1->flags == 0 && ses1->state == SNAT_SESSION_UNKNOWN)
4103 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
4105 old_port1 = tcp1->src;
4106 tcp1->src = new_port1;
4108 sum1 = tcp1->checksum;
4119 ses1->state = SNAT_SESSION_UDP_ACTIVE;
4127 case SNAT_SESSION_UDP_ACTIVE:
4130 case SNAT_SESSION_TCP_SYN_SENT:
4131 case SNAT_SESSION_TCP_FIN_WAIT:
4132 case SNAT_SESSION_TCP_CLOSE_WAIT:
4133 case SNAT_SESSION_TCP_LAST_ACK:
4136 case SNAT_SESSION_TCP_ESTABLISHED:
4143 && (b1->
flags & VLIB_BUFFER_IS_TRACED)))
4159 to_next, n_left_to_next,
4160 bi0, bi1, next0, next1);
4163 while (n_left_from > 0 && n_left_to_next > 0)
4172 u16 old_port0, new_port0, lo_port0, i0;
4180 icmp46_header_t * icmp0;
4188 n_left_to_next -= 1;
4203 ICMP4_time_exceeded_ttl_exceeded_in_transit,
4214 icmp0 = (icmp46_header_t *) udp0;
4216 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
4217 rx_fib_index0, node, next0, thread_index,
4228 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
4242 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
4243 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
4257 ICMP4_destination_unreachable_destination_unreachable_host,
4279 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
4280 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
4281 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
4282 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
4283 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
4284 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
4286 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
4287 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
4288 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
4289 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
4291 old_port0 = tcp0->src;
4292 tcp0->src = new_port0;
4294 sum0 = tcp0->checksum;
4305 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
4313 case SNAT_SESSION_UDP_ACTIVE:
4316 case SNAT_SESSION_TCP_SYN_SENT:
4317 case SNAT_SESSION_TCP_FIN_WAIT:
4318 case SNAT_SESSION_TCP_CLOSE_WAIT:
4319 case SNAT_SESSION_TCP_LAST_ACK:
4322 case SNAT_SESSION_TCP_ESTABLISHED:
4329 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
4345 to_next, n_left_to_next,
4353 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
4360 .name =
"nat44-det-in2out",
4361 .vector_size =
sizeof (
u32),
4400 u8 *p_dont_translate,
void *d,
void *e)
4402 icmp46_header_t *icmp0;
4407 u8 dont_translate = 0;
4411 void *l4_header = 0;
4412 icmp46_header_t *inner_icmp0;
4427 protocol = SNAT_PROTOCOL_ICMP;
4439 case SNAT_PROTOCOL_ICMP:
4440 inner_icmp0 = (icmp46_header_t*)l4_header;
4444 case SNAT_PROTOCOL_UDP:
4445 case SNAT_PROTOCOL_TCP:
4449 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
4461 IP_PROTOCOL_ICMP, rx_fib_index0)))
4467 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
4480 IP_PROTOCOL_ICMP, rx_fib_index0)))
4485 if (icmp0->type != ICMP4_echo_request)
4487 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
4493 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
4505 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
4513 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
4520 ses0->
state = SNAT_SESSION_ICMP_ACTIVE;
4524 *p_proto = protocol;
4527 p_value->
addr = new_addr0;
4531 *p_dont_translate = dont_translate;
4550 u32 n_left_from, *from, *to_next = 0, *to_next_drop = 0;
4558 u32 n_left_to_next_worker = 0, *to_next_worker = 0;
4559 u32 next_worker_index = 0;
4560 u32 current_worker_index = ~0;
4591 while (n_left_from > 0)
4617 if (next_worker_index != current_worker_index)
4621 congested_handoff_queue_by_worker_index);
4632 to_next_drop[0] = bi0;
4635 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_FQ_CONGESTED];
4644 handoff_queue_elt_by_worker_index);
4648 current_worker_index = next_worker_index;
4652 to_next_worker[0] = bi0;
4654 n_left_to_next_worker--;
4656 if (n_left_to_next_worker == 0)
4660 current_worker_index = ~0;
4661 handoff_queue_elt_by_worker_index[next_worker_index] = 0;
4682 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
4701 for (i = 0; i <
vec_len (handoff_queue_elt_by_worker_index); i++)
4703 if (handoff_queue_elt_by_worker_index[i])
4705 hf = handoff_queue_elt_by_worker_index[
i];
4713 handoff_queue_elt_by_worker_index[
i] = 0;
4718 congested_handoff_queue_by_worker_index[
i] =
4722 current_worker_index = ~0;
4736 .name =
"nat44-in2out-worker-handoff",
4737 .vector_size =
sizeof (
u32),
4764 .name =
"nat44-in2out-output-worker-handoff",
4765 .vector_size =
sizeof (
u32),
4809 u32 n_left_from, * from, * to_next, stats_node_index;
4811 u32 pkts_processed = 0;
4821 while (n_left_from > 0)
4826 to_next, n_left_to_next);
4828 while (n_left_from > 0 && n_left_to_next > 0)
4842 n_left_to_next -= 1;
4853 if (proto0 == SNAT_PROTOCOL_TCP || proto0 == SNAT_PROTOCOL_UDP)
4860 else if (proto0 == SNAT_PROTOCOL_ICMP)
4881 to_next, n_left_to_next,
4889 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
4904 .name =
"nat44-hairpin-dst",
4905 .vector_size =
sizeof (
u32),
4929 .name =
"nat44-ed-hairpin-dst",
4930 .vector_size =
sizeof (
u32),
4950 u32 n_left_from, * from, * to_next, stats_node_index;
4952 u32 pkts_processed = 0;
4962 while (n_left_from > 0)
4967 to_next, n_left_to_next);
4969 while (n_left_from > 0 && n_left_to_next > 0)
4983 n_left_to_next -= 1;
4992 if ((nat_interface_is_inside(i)) && (sw_if_index0 == i->sw_if_index))
4994 if (PREDICT_FALSE ((vnet_buffer (b0)->snat.flags) &
4995 SNAT_FLAG_HAIRPINNING))
4997 if (PREDICT_TRUE (sm->num_workers > 1))
4998 next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH;
5000 next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT;
5010 to_next, n_left_to_next,
5018 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
5020 return frame->n_vectors;
5033 .name =
"nat44-hairpin-src",
5034 .vector_size =
sizeof (
u32),
5060 .name =
"nat44-ed-hairpin-src",
5061 .vector_size =
sizeof (
u32),
5082 u32 n_left_from, * from, * to_next;
5084 u32 pkts_processed = 0;
5086 u32 stats_node_index;
5094 while (n_left_from > 0)
5099 to_next, n_left_to_next);
5101 while (n_left_from > 0 && n_left_to_next > 0)
5109 u32 new_addr0, old_addr0;
5110 u16 old_port0, new_port0;
5113 icmp46_header_t * icmp0;
5124 n_left_to_next -= 1;
5132 icmp0 = (icmp46_header_t *) udp0;
5141 ICMP4_time_exceeded_ttl_exceeded_in_transit,
5154 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
5155 rx_fib_index0, node, next0, ~0, 0, 0);
5166 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
5172 new_port0 = sm0.
port;
5187 old_port0 = tcp0->src_port;
5188 tcp0->src_port = new_port0;
5190 sum0 = tcp0->checksum;
5210 sum0 = tcp0->checksum;
5223 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
5235 to_next, n_left_to_next,
5243 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
5251 .name =
"nat44-in2out-fast",
5252 .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
nat_outside_fib_t * outside_fibs
#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.
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,...)
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)