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 rx_sw_if_index,
2618 src_port, dst_port);
2619 if (!clib_bihash_search_16_8 (&tsm->
out2in_ed, &kv, &value))
2624 dst_port, src_port);
2625 if (!clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv, &value))
2634 if ((nat_interface_is_inside(i)) && (rx_sw_if_index == i->sw_if_index))
2647 u8 *p_dont_translate,
void *d,
void *e)
2649 icmp46_header_t *icmp;
2653 snat_session_t *s = 0;
2654 u8 dont_translate = 0;
2677 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv, &value))
2692 ip, SNAT_PROTOCOL_ICMP, rx_fib_index, thread_index)))
2701 b->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
2706 next =
slow_path_ed (sm, b, rx_fib_index, &kv, &s, node, next,
2715 icmp->type != ICMP4_echo_reply &&
2718 b->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
2729 *p_value = s->out2in;
2730 *p_dont_translate = dont_translate;
2732 *(snat_session_t**)d = s;
2741 u32 old_addr, new_addr = 0, ti = 0;
2758 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &s_kv, &s_value))
2781 static snat_session_t *
2794 u32 old_addr, new_addr = 0;
2799 u32 elt_index, head_index, ses_index;
2830 outside_fib_index = outside_fib->
fib_index;
2840 rx_fib_index, 0, 0);
2842 if (!clib_bihash_search_16_8 (&tsm->
in2out_ed, &s_kv, &s_value))
2851 b->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
2881 elt_index = head->
next;
2887 ses_index = elt->
value;
2890 while (ses_index != ~0)
2893 elt_index = elt->
next;
2895 ses_index = elt->
value;
2900 address_index = s->outside_address_index;
2903 ip->
protocol, outside_fib_index, 0, 0);
2904 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &s_kv, &s_value))
2914 ip->
protocol, outside_fib_index, 0, 0);
2915 if (clib_bihash_search_16_8 (&tsm->
out2in_ed, &s_kv, &s_value))
2937 s->outside_address_index = address_index;
2938 s->out2in.addr.as_u32 = new_addr;
2939 s->out2in.fib_index = outside_fib_index;
2940 s->in2out.addr.as_u32 = old_addr;
2941 s->in2out.fib_index = rx_fib_index;
2942 s->in2out.port = s->out2in.port = ip->
protocol;
2949 rx_fib_index, 0, 0);
2951 if (clib_bihash_add_del_16_8 (&tsm->
in2out_ed, &s_kv, 1))
2955 outside_fib_index, 0, 0);
2957 if (clib_bihash_add_del_16_8 (&tsm->
out2in_ed, &s_kv, 1))
2985 int is_output_feature)
2987 u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index;
3001 while (n_left_from > 0)
3007 while (n_left_from >= 4 && n_left_to_next >= 2)
3011 u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
3012 new_addr0, old_addr0;
3013 u32 next1, sw_if_index1, rx_fib_index1, iph_offset1 = 0, proto1,
3014 new_addr1, old_addr1;
3015 u16 old_port0, new_port0, old_port1, new_port1;
3019 icmp46_header_t *icmp0, *icmp1;
3020 snat_session_t *s0 = 0, *s1 = 0;
3039 to_next[0] = bi0 = from[0];
3040 to_next[1] = bi1 = from[1];
3044 n_left_to_next -= 2;
3051 if (is_output_feature)
3052 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
3065 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3073 icmp0 = (icmp46_header_t *) udp0;
3082 thread_index, now, vm,
3092 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
3093 next0, now, thread_index, &s0);
3099 if (is_output_feature)
3102 sm, ip0, thread_index, now, vm, b0)))
3106 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
3114 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
3123 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv0, &value0))
3127 if (is_output_feature)
3131 udp0->
dst_port, thread_index, sw_if_index0,
3138 sw_if_index0, ip0, proto0, rx_fib_index0,
3143 next0 =
slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
3144 next0, thread_index);
3160 b0->
flags |= VNET_BUFFER_F_IS_NATED;
3162 if (!is_output_feature)
3178 old_port0 = tcp0->src_port;
3179 new_port0 = tcp0->src_port = s0->out2in.port;
3181 sum0 = tcp0->checksum;
3189 s0->ext_host_addr.as_u32,
3194 tcp0->dst_port = s0->ext_host_port;
3207 udp0->
dst_port = s0->ext_host_port;
3220 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
3237 if (is_output_feature)
3238 iph_offset1 =
vnet_buffer (b1)->ip.save_rewrite_length;
3251 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3259 icmp1 = (icmp46_header_t *) udp1;
3268 thread_index, now, vm,
3278 (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
3279 next1, now, thread_index, &s1);
3285 if (is_output_feature)
3288 sm, ip1, thread_index, now, vm, b1)))
3292 if (
PREDICT_FALSE (proto1 == ~0 || proto1 == SNAT_PROTOCOL_ICMP))
3300 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
3309 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv1, &value1))
3313 if (is_output_feature)
3317 udp1->
dst_port, thread_index, sw_if_index1,
3324 sw_if_index1, ip1, proto1, rx_fib_index1,
3329 next1 =
slow_path_ed (sm, b1, rx_fib_index1, &kv1, &s1, node,
3330 next1, thread_index);
3346 b1->
flags |= VNET_BUFFER_F_IS_NATED;
3348 if (!is_output_feature)
3364 old_port1 = tcp1->src_port;
3365 new_port1 = tcp1->src_port = s1->out2in.port;
3367 sum1 = tcp1->checksum;
3375 s1->ext_host_addr.as_u32,
3380 tcp1->dst_port = s1->ext_host_port;
3393 udp1->
dst_port = s1->ext_host_port;
3406 && (b1->
flags & VLIB_BUFFER_IS_TRACED)))
3422 to_next, n_left_to_next,
3423 bi0, bi1, next0, next1);
3426 while (n_left_from > 0 && n_left_to_next > 0)
3430 u32 next0, sw_if_index0, rx_fib_index0, iph_offset0 = 0, proto0,
3431 new_addr0, old_addr0;
3432 u16 old_port0, new_port0;
3436 icmp46_header_t * icmp0;
3437 snat_session_t *s0 = 0;
3447 n_left_to_next -= 1;
3452 if (is_output_feature)
3453 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
3466 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3474 icmp0 = (icmp46_header_t *) udp0;
3483 thread_index, now, vm,
3493 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
3494 next0, now, thread_index, &s0);
3500 if (is_output_feature)
3503 sm, ip0, thread_index, now, vm, b0)))
3507 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
3515 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
3524 if (clib_bihash_search_16_8 (&tsm->
in2out_ed, &kv0, &value0))
3528 if (is_output_feature)
3532 udp0->
dst_port, thread_index, sw_if_index0,
3539 sw_if_index0, ip0, proto0, rx_fib_index0,
3544 next0 =
slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
3545 next0, thread_index);
3561 b0->
flags |= VNET_BUFFER_F_IS_NATED;
3563 if (!is_output_feature)
3579 old_port0 = tcp0->src_port;
3580 new_port0 = tcp0->src_port = s0->out2in.port;
3582 sum0 = tcp0->checksum;
3590 s0->ext_host_addr.as_u32,
3595 tcp0->dst_port = s0->ext_host_port;
3608 udp0->
dst_port = s0->ext_host_port;
3621 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
3637 to_next, n_left_to_next,
3645 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
3660 .name =
"nat44-ed-in2out",
3661 .vector_size =
sizeof (
u32),
3694 .name =
"nat44-ed-in2out-output",
3695 .vector_size =
sizeof (
u32),
3729 .name =
"nat44-ed-in2out-slowpath",
3730 .vector_size =
sizeof (
u32),
3764 .name =
"nat44-ed-in2out-output-slowpath",
3765 .vector_size =
sizeof (
u32),
3797 u32 n_left_from, * from, * to_next;
3799 u32 pkts_processed = 0;
3808 while (n_left_from > 0)
3813 to_next, n_left_to_next);
3815 while (n_left_from >= 4 && n_left_to_next >= 2)
3820 u32 sw_if_index0, sw_if_index1;
3824 u16 old_port0, new_port0, lo_port0, i0;
3825 u16 old_port1, new_port1, lo_port1, i1;
3832 u32 rx_fib_index0, rx_fib_index1;
3833 icmp46_header_t * icmp0, * icmp1;
3850 to_next[0] = bi0 = from[0];
3851 to_next[1] = bi1 = from[1];
3855 n_left_to_next -= 2;
3873 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3884 icmp0 = (icmp46_header_t *) udp0;
3886 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
3887 rx_fib_index0, node, next0, thread_index,
3898 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
3912 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
3913 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
3927 ICMP4_destination_unreachable_destination_unreachable_host,
3949 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
3950 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
3951 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
3952 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
3953 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
3954 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
3956 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
3957 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
3958 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
3959 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
3961 old_port0 = tcp0->src;
3962 tcp0->src = new_port0;
3964 sum0 = tcp0->checksum;
3975 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
3983 case SNAT_SESSION_UDP_ACTIVE:
3986 case SNAT_SESSION_TCP_SYN_SENT:
3987 case SNAT_SESSION_TCP_FIN_WAIT:
3988 case SNAT_SESSION_TCP_CLOSE_WAIT:
3989 case SNAT_SESSION_TCP_LAST_ACK:
3992 case SNAT_SESSION_TCP_ESTABLISHED:
3999 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
4023 ICMP4_time_exceeded_ttl_exceeded_in_transit,
4034 icmp1 = (icmp46_header_t *) udp1;
4036 next1 =
icmp_in2out(sm, b1, ip1, icmp1, sw_if_index1,
4037 rx_fib_index1, node, next1, thread_index,
4048 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
4062 key1.
out_port = clib_host_to_net_u16 (lo_port1 +
4063 ((i1 + clib_net_to_host_u16 (tcp1->src)) % dm1->
ports_per_host));
4077 ICMP4_destination_unreachable_destination_unreachable_host,
4084 new_port1 = ses1->out.out_port;
4099 ses1->state = SNAT_SESSION_TCP_SYN_SENT;
4100 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_SYN_SENT)
4101 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
4102 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_ESTABLISHED)
4103 ses1->state = SNAT_SESSION_TCP_FIN_WAIT;
4104 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_FIN_WAIT)
4106 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_CLOSE_WAIT)
4107 ses1->state = SNAT_SESSION_TCP_LAST_ACK;
4108 else if (tcp1->flags == 0 && ses1->state == SNAT_SESSION_UNKNOWN)
4109 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
4111 old_port1 = tcp1->src;
4112 tcp1->src = new_port1;
4114 sum1 = tcp1->checksum;
4125 ses1->state = SNAT_SESSION_UDP_ACTIVE;
4133 case SNAT_SESSION_UDP_ACTIVE:
4136 case SNAT_SESSION_TCP_SYN_SENT:
4137 case SNAT_SESSION_TCP_FIN_WAIT:
4138 case SNAT_SESSION_TCP_CLOSE_WAIT:
4139 case SNAT_SESSION_TCP_LAST_ACK:
4142 case SNAT_SESSION_TCP_ESTABLISHED:
4149 && (b1->
flags & VLIB_BUFFER_IS_TRACED)))
4165 to_next, n_left_to_next,
4166 bi0, bi1, next0, next1);
4169 while (n_left_from > 0 && n_left_to_next > 0)
4178 u16 old_port0, new_port0, lo_port0, i0;
4186 icmp46_header_t * icmp0;
4194 n_left_to_next -= 1;
4209 ICMP4_time_exceeded_ttl_exceeded_in_transit,
4220 icmp0 = (icmp46_header_t *) udp0;
4222 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
4223 rx_fib_index0, node, next0, thread_index,
4234 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
4248 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
4249 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
4263 ICMP4_destination_unreachable_destination_unreachable_host,
4285 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
4286 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
4287 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
4288 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
4289 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
4290 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
4292 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
4293 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
4294 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
4295 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
4297 old_port0 = tcp0->src;
4298 tcp0->src = new_port0;
4300 sum0 = tcp0->checksum;
4311 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
4319 case SNAT_SESSION_UDP_ACTIVE:
4322 case SNAT_SESSION_TCP_SYN_SENT:
4323 case SNAT_SESSION_TCP_FIN_WAIT:
4324 case SNAT_SESSION_TCP_CLOSE_WAIT:
4325 case SNAT_SESSION_TCP_LAST_ACK:
4328 case SNAT_SESSION_TCP_ESTABLISHED:
4335 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
4351 to_next, n_left_to_next,
4359 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
4366 .name =
"nat44-det-in2out",
4367 .vector_size =
sizeof (
u32),
4406 u8 *p_dont_translate,
void *d,
void *e)
4408 icmp46_header_t *icmp0;
4413 u8 dont_translate = 0;
4417 void *l4_header = 0;
4418 icmp46_header_t *inner_icmp0;
4433 protocol = SNAT_PROTOCOL_ICMP;
4445 case SNAT_PROTOCOL_ICMP:
4446 inner_icmp0 = (icmp46_header_t*)l4_header;
4450 case SNAT_PROTOCOL_UDP:
4451 case SNAT_PROTOCOL_TCP:
4455 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
4467 IP_PROTOCOL_ICMP, rx_fib_index0)))
4473 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
4486 IP_PROTOCOL_ICMP, rx_fib_index0)))
4491 if (icmp0->type != ICMP4_echo_request)
4493 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
4499 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
4511 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
4519 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
4526 ses0->
state = SNAT_SESSION_ICMP_ACTIVE;
4530 *p_proto = protocol;
4533 p_value->
addr = new_addr0;
4537 *p_dont_translate = dont_translate;
4556 u32 n_left_from, *from, *to_next = 0, *to_next_drop = 0;
4564 u32 n_left_to_next_worker = 0, *to_next_worker = 0;
4565 u32 next_worker_index = 0;
4566 u32 current_worker_index = ~0;
4597 while (n_left_from > 0)
4623 if (next_worker_index != current_worker_index)
4627 congested_handoff_queue_by_worker_index);
4638 to_next_drop[0] = bi0;
4641 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_FQ_CONGESTED];
4650 handoff_queue_elt_by_worker_index);
4654 current_worker_index = next_worker_index;
4658 to_next_worker[0] = bi0;
4660 n_left_to_next_worker--;
4662 if (n_left_to_next_worker == 0)
4666 current_worker_index = ~0;
4667 handoff_queue_elt_by_worker_index[next_worker_index] = 0;
4688 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
4707 for (i = 0; i <
vec_len (handoff_queue_elt_by_worker_index); i++)
4709 if (handoff_queue_elt_by_worker_index[i])
4711 hf = handoff_queue_elt_by_worker_index[
i];
4719 handoff_queue_elt_by_worker_index[
i] = 0;
4724 congested_handoff_queue_by_worker_index[
i] =
4728 current_worker_index = ~0;
4742 .name =
"nat44-in2out-worker-handoff",
4743 .vector_size =
sizeof (
u32),
4770 .name =
"nat44-in2out-output-worker-handoff",
4771 .vector_size =
sizeof (
u32),
4815 u32 n_left_from, * from, * to_next, stats_node_index;
4817 u32 pkts_processed = 0;
4827 while (n_left_from > 0)
4832 to_next, n_left_to_next);
4834 while (n_left_from > 0 && n_left_to_next > 0)
4848 n_left_to_next -= 1;
4859 if (proto0 == SNAT_PROTOCOL_TCP || proto0 == SNAT_PROTOCOL_UDP)
4866 else if (proto0 == SNAT_PROTOCOL_ICMP)
4887 to_next, n_left_to_next,
4895 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
4910 .name =
"nat44-hairpin-dst",
4911 .vector_size =
sizeof (
u32),
4935 .name =
"nat44-ed-hairpin-dst",
4936 .vector_size =
sizeof (
u32),
4956 u32 n_left_from, * from, * to_next, stats_node_index;
4958 u32 pkts_processed = 0;
4968 while (n_left_from > 0)
4973 to_next, n_left_to_next);
4975 while (n_left_from > 0 && n_left_to_next > 0)
4989 n_left_to_next -= 1;
4998 if ((nat_interface_is_inside(i)) && (sw_if_index0 == i->sw_if_index))
5000 if (PREDICT_FALSE ((vnet_buffer (b0)->snat.flags) &
5001 SNAT_FLAG_HAIRPINNING))
5003 if (PREDICT_TRUE (sm->num_workers > 1))
5004 next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH;
5006 next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT;
5016 to_next, n_left_to_next,
5024 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
5026 return frame->n_vectors;
5039 .name =
"nat44-hairpin-src",
5040 .vector_size =
sizeof (
u32),
5066 .name =
"nat44-ed-hairpin-src",
5067 .vector_size =
sizeof (
u32),
5088 u32 n_left_from, * from, * to_next;
5090 u32 pkts_processed = 0;
5092 u32 stats_node_index;
5100 while (n_left_from > 0)
5105 to_next, n_left_to_next);
5107 while (n_left_from > 0 && n_left_to_next > 0)
5115 u32 new_addr0, old_addr0;
5116 u16 old_port0, new_port0;
5119 icmp46_header_t * icmp0;
5130 n_left_to_next -= 1;
5138 icmp0 = (icmp46_header_t *) udp0;
5147 ICMP4_time_exceeded_ttl_exceeded_in_transit,
5160 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
5161 rx_fib_index0, node, next0, ~0, 0, 0);
5172 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
5178 new_port0 = sm0.
port;
5193 old_port0 = tcp0->src_port;
5194 tcp0->src_port = new_port0;
5196 sum0 = tcp0->checksum;
5216 sum0 = tcp0->checksum;
5229 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
5241 to_next, n_left_to_next,
5249 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
5257 .name =
"nat44-in2out-fast",
5258 .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)
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)
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_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 rx_sw_if_index, u32 tx_sw_if_index)
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()
int nat_ip4_reass_add_fragment(nat_reass_ip4_t *reass, u32 bi, u32 **bi_to_drop)
Cache fragment.
#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)