53 tag = t->
is_slow_path ?
"NAT44_IN2OUT_SLOW_PATH" :
"NAT44_IN2OUT_FAST_PATH";
55 s =
format (s,
"%s: sw_if_index %d, next index %d, session %d", tag,
67 s =
format (s,
"NAT44_IN2OUT_FAST: sw_if_index %d, next index %d",
81 m = t->
do_handoff ?
"next worker" :
"same worker";
99 s =
format (s,
"NAT44_IN2OUT_REASS: sw_if_index %d, next index %d, status %s",
101 t->
cached ?
"cached" :
"translated");
120 #define foreach_snat_in2out_error \ 121 _(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \ 122 _(IN2OUT_PACKETS, "Good in2out packets processed") \ 123 _(OUT_OF_PORTS, "Out of ports") \ 124 _(BAD_OUTSIDE_FIB, "Outside VRF ID not found") \ 125 _(BAD_ICMP_TYPE, "unsupported ICMP type") \ 126 _(NO_TRANSLATION, "No translation") \ 127 _(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded") \ 128 _(DROP_FRAGMENT, "Drop fragment") \ 129 _(MAX_REASS, "Maximum reassemblies exceeded") \ 130 _(MAX_FRAG, "Maximum fragments per reassembly exceeded") 133 #define _(sym,str) SNAT_IN2OUT_ERROR_##sym, 140 #define _(sym,string) string, 200 if (sw_if_index == ~0)
210 if ((nat_interface_is_outside(i)) && (sw_if_index == i->sw_if_index))
221 u32 rx_fib_index0,
u32 thread_index)
256 snat_session_t ** sessionp,
265 u32 address_index = ~0;
266 u32 outside_fib_index;
272 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
279 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_OUTSIDE_FIB];
282 outside_fib_index = p[0];
311 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
322 s->outside_address_index = address_index;
326 s->out2in.fib_index = outside_fib_index;
332 kv0.
key = s->in2out.as_u64;
338 kv0.
key = s->out2in.as_u64;
347 s->out2in.addr.as_u32,
351 s->in2out.fib_index);
359 icmp46_header_t *icmp0;
364 icmp46_header_t *inner_icmp0;
383 case SNAT_PROTOCOL_ICMP:
384 inner_icmp0 = (icmp46_header_t*)l4_header;
388 case SNAT_PROTOCOL_UDP:
389 case SNAT_PROTOCOL_TCP:
393 return SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL;
418 u8 *p_dont_translate,
void *d,
void *e)
420 icmp46_header_t *icmp0;
424 snat_session_t *s0 = 0;
425 u8 dont_translate = 0;
449 IP_PROTOCOL_ICMP, rx_fib_index0, thread_index) &&
458 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
463 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
464 &s0, node, next0, thread_index);
472 icmp0->type != ICMP4_echo_reply &&
475 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
487 *p_value = s0->out2in;
488 *p_dont_translate = dont_translate;
490 *(snat_session_t**)d = s0;
511 u8 *p_dont_translate,
void *d,
void *e)
513 icmp46_header_t *icmp0;
518 u8 dont_translate = 0;
539 IP_PROTOCOL_ICMP, rx_fib_index0)))
551 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
557 (icmp0->type != ICMP4_echo_reply || !is_addr_only) &&
560 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
569 *p_dont_translate = dont_translate;
576 icmp46_header_t * icmp0,
590 icmp46_header_t *inner_icmp0;
592 u32 new_addr0, old_addr0;
593 u16 old_id0, new_id0;
601 &protocol, &sm0, &dont_translate, d, e);
635 sum0 = icmp0->checksum;
656 sum0 = icmp0->checksum;
663 case SNAT_PROTOCOL_ICMP:
664 inner_icmp0 = (icmp46_header_t*)l4_header;
671 sum0 = icmp0->checksum;
676 case SNAT_PROTOCOL_UDP:
677 case SNAT_PROTOCOL_TCP:
682 sum0 = icmp0->checksum;
722 u32 new_dst_addr0 = 0, old_dst_addr0, ti = 0, si;
723 u16 new_dst_port0, old_dst_port0;
735 new_dst_port0 = sm0.
port;
751 new_dst_addr0 = s0->in2out.addr.as_u32;
752 new_dst_port0 = s0->in2out.port;
767 old_dst_port0 = tcp0->dst;
772 tcp0->dst = new_dst_port0;
773 sum0 = tcp0->checksum;
790 sum0 = tcp0->checksum;
805 icmp46_header_t * icmp0)
809 u32 new_dst_addr0 = 0, old_dst_addr0, si, ti = 0;
818 key0.
port = icmp_id0;
844 new_dst_addr0 = s0->in2out.addr.as_u32;
847 sum0 = icmp0->checksum;
870 icmp46_header_t * icmp0,
877 snat_session_t ** p_s0)
879 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
880 next0, thread_index, p_s0, 0);
881 snat_session_t * s0 = *p_s0;
888 s0->last_heard = now;
895 s0->per_user_list_head_index,
905 u32 old_addr, new_addr = 0, ti = 0;
923 if (clib_bihash_search_16_8 (&sm->
out2in_ed, &s_kv, &s_value))
955 static snat_session_t *
969 u32 old_addr, new_addr = 0;
974 u32 elt_index, head_index, ses_index;
977 u32 address_index = ~0;
992 if (!clib_bihash_search_16_8 (&sm->
in2out_ed, &s_kv, &s_value))
1001 b->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
1031 if (!clib_bihash_search_8_8 (&tsm->
user_hash, &kv, &value))
1035 elt_index = head->
next;
1037 ses_index = elt->
value;
1038 while (ses_index != ~0)
1041 elt_index = elt->
next;
1043 ses_index = elt->
value;
1048 address_index = s->outside_address_index;
1054 if (clib_bihash_search_16_8 (&sm->
out2in_ed, &s_kv, &s_value))
1067 if (clib_bihash_search_16_8 (&sm->
out2in_ed, &s_kv, &s_value))
1087 s->outside_address_index = address_index;
1088 s->out2in.addr.as_u32 = new_addr;
1090 s->in2out.addr.as_u32 = old_addr;
1091 s->in2out.fib_index = rx_fib_index;
1092 s->in2out.port = s->out2in.port = ip->
protocol;
1111 if (clib_bihash_add_del_16_8 (&sm->
in2out_ed, &s_kv, 1))
1118 if (clib_bihash_add_del_16_8 (&sm->
out2in_ed, &s_kv, 1))
1128 s->last_heard = now;
1146 static snat_session_t *
1160 snat_session_t *s = 0;
1162 u32 old_addr, new_addr;
1163 u16 new_port, old_port;
1180 if (!clib_bihash_search_16_8 (&sm->
in2out_ed, &s_kv, &s_value))
1188 b->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
1217 s->outside_address_index = ~0;
1224 if (clib_bihash_add_del_16_8 (&sm->
in2out_ed, &s_kv, 1))
1232 if (clib_bihash_add_del_16_8 (&sm->
out2in_ed, &s_kv, 1))
1248 old_port = tcp->src_port;
1249 tcp->src_port = s->out2in.port;
1250 new_port = tcp->src_port;
1252 sum = tcp->checksum;
1262 tcp->dst_port = s->ext_host_port;
1282 s->last_heard = now;
1296 int is_output_feature)
1298 u32 n_left_from, * from, * to_next;
1300 u32 pkts_processed = 0;
1303 u32 stats_node_index;
1313 while (n_left_from > 0)
1318 to_next, n_left_to_next);
1320 while (n_left_from >= 4 && n_left_to_next >= 2)
1325 u32 sw_if_index0, sw_if_index1;
1328 u32 new_addr0, old_addr0, new_addr1, old_addr1;
1329 u16 old_port0, new_port0, old_port1, new_port1;
1332 icmp46_header_t * icmp0, * icmp1;
1334 u32 rx_fib_index0, rx_fib_index1;
1336 snat_session_t * s0 = 0, * s1 = 0;
1338 u32 iph_offset0 = 0, iph_offset1 = 0;
1355 to_next[0] = bi0 = from[0];
1356 to_next[1] = bi1 = from[1];
1360 n_left_to_next -= 2;
1365 if (is_output_feature)
1366 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
1373 icmp0 = (icmp46_header_t *) udp0;
1385 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1399 thread_index, now, vm, node);
1408 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
1409 node, next0, now, thread_index, &s0);
1415 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
1441 ip0, proto0, rx_fib_index0, thread_index)) && !is_output_feature)
1444 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
1445 &s0, node, next0, thread_index);
1462 thread_index, now, vm, node);
1481 b0->
flags |= VNET_BUFFER_F_IS_NATED;
1486 if (!is_output_feature)
1497 old_port0 = tcp0->src_port;
1498 tcp0->src_port = s0->out2in.port;
1499 new_port0 = tcp0->src_port;
1501 sum0 = tcp0->checksum;
1518 s0->last_heard = now;
1523 s0->per_user_index);
1525 s0->per_user_list_head_index,
1526 s0->per_user_index);
1544 if (is_output_feature)
1545 iph_offset1 =
vnet_buffer (b1)->ip.save_rewrite_length;
1552 icmp1 = (icmp46_header_t *) udp1;
1562 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1576 thread_index, now, vm, node);
1585 (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
1586 next1, now, thread_index, &s1);
1592 if (
PREDICT_FALSE (proto1 == ~0 || proto1 == SNAT_PROTOCOL_ICMP))
1605 b1->
flags |= VNET_BUFFER_F_IS_NATED;
1620 ip1, proto1, rx_fib_index1, thread_index)) && !is_output_feature)
1623 next1 =
slow_path (sm, b1, ip1, rx_fib_index1, &key1,
1624 &s1, node, next1, thread_index);
1641 thread_index, now, vm, node);
1663 if (!is_output_feature)
1674 old_port1 = tcp1->src_port;
1675 tcp1->src_port = s1->out2in.port;
1676 new_port1 = tcp1->src_port;
1678 sum1 = tcp1->checksum;
1695 s1->last_heard = now;
1700 s1->per_user_index);
1702 s1->per_user_list_head_index,
1703 s1->per_user_index);
1722 to_next, n_left_to_next,
1723 bi0, bi1, next0, next1);
1726 while (n_left_from > 0 && n_left_to_next > 0)
1734 u32 new_addr0, old_addr0;
1735 u16 old_port0, new_port0;
1738 icmp46_header_t * icmp0;
1742 snat_session_t * s0 = 0;
1744 u32 iph_offset0 = 0;
1752 n_left_to_next -= 1;
1757 if (is_output_feature)
1758 iph_offset0 =
vnet_buffer (b0)->ip.save_rewrite_length;
1765 icmp0 = (icmp46_header_t *) udp0;
1775 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1789 thread_index, now, vm, node);
1798 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1799 next0, now, thread_index, &s0);
1805 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
1831 ip0, proto0, rx_fib_index0, thread_index)) && !is_output_feature)
1834 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
1835 &s0, node, next0, thread_index);
1853 thread_index, now, vm, node);
1872 b0->
flags |= VNET_BUFFER_F_IS_NATED;
1877 if (!is_output_feature)
1888 old_port0 = tcp0->src_port;
1889 tcp0->src_port = s0->out2in.port;
1890 new_port0 = tcp0->src_port;
1892 sum0 = tcp0->checksum;
1909 s0->last_heard = now;
1914 s0->per_user_index);
1916 s0->per_user_list_head_index,
1917 s0->per_user_index);
1937 to_next, n_left_to_next,
1945 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
1960 .name =
"nat44-in2out",
1961 .vector_size =
sizeof (
u32),
1994 .name =
"nat44-in2out-output",
1995 .vector_size =
sizeof (
u32),
2029 .name =
"nat44-in2out-slowpath",
2030 .vector_size =
sizeof (
u32),
2064 .name =
"nat44-in2out-output-slowpath",
2065 .vector_size =
sizeof (
u32),
2096 u32 n_left_from, * from, * to_next;
2098 u32 pkts_processed = 0;
2108 while (n_left_from > 0)
2113 to_next, n_left_to_next);
2115 while (n_left_from > 0 && n_left_to_next > 0)
2131 n_left_to_next -= 1;
2150 to_next, n_left_to_next,
2158 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
2165 .name =
"nat44-hairpinning",
2166 .vector_size =
sizeof (
u32),
2189 snat_session_t * s0;
2192 u32 new_dst_addr0 = 0, old_dst_addr0, ti = 0, si;
2193 u16 new_dst_port0, old_dst_port0;
2209 new_dst_port0 = sm0.
port;
2224 new_dst_addr0 = s0->in2out.addr.as_u32;
2225 new_dst_port0 = s0->in2out.port;
2240 old_dst_port0 = dport;
2247 tcp0->dst = new_dst_port0;
2248 sum0 = tcp0->checksum;
2266 sum0 = tcp0->checksum;
2280 u32 n_left_from, *from, *to_next;
2282 u32 pkts_processed = 0;
2288 u32 *fragments_to_drop = 0;
2289 u32 *fragments_to_loopback = 0;
2295 while (n_left_from > 0)
2301 while (n_left_from > 0 && n_left_to_next > 0)
2303 u32 bi0, sw_if_index0, proto0, rx_fib_index0, new_addr0, old_addr0;
2308 nat_reass_ip4_t *reass0;
2313 snat_session_t * s0 = 0;
2314 u16 old_port0, new_port0;
2323 n_left_to_next -= 1;
2335 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT];
2349 &fragments_to_drop);
2354 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_REASS];
2366 if (clib_bihash_search_8_8 (&per_thread_data->
in2out, &kv0, &value0))
2369 ip0, proto0, rx_fib_index0, thread_index)))
2372 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
2373 &s0, node, next0, thread_index);
2378 reass0->sess_index = s0 - per_thread_data->
sessions;
2384 reass0->sess_index = value0.
value;
2394 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_MAX_FRAG];
2402 reass0->sess_index);
2420 old_port0 = tcp0->src_port;
2421 tcp0->src_port = s0->out2in.port;
2422 new_port0 = tcp0->src_port;
2424 sum0 = tcp0->checksum;
2443 s0->ext_host_port, proto0);
2446 s0->last_heard = now;
2451 s0->per_user_index);
2453 s0->per_user_list_head_index,
2454 s0->per_user_index);
2478 to_next, n_left_to_next,
2482 if (n_left_from == 0 &&
vec_len (fragments_to_loopback))
2507 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
2511 &node->
errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT],
2521 .name =
"nat44-in2out-reass",
2522 .vector_size =
sizeof (
u32),
2550 u32 n_left_from, * from, * to_next;
2552 u32 pkts_processed = 0;
2561 while (n_left_from > 0)
2566 to_next, n_left_to_next);
2568 while (n_left_from >= 4 && n_left_to_next >= 2)
2573 u32 sw_if_index0, sw_if_index1;
2577 u16 old_port0, new_port0, lo_port0, i0;
2578 u16 old_port1, new_port1, lo_port1, i1;
2585 u32 rx_fib_index0, rx_fib_index1;
2586 icmp46_header_t * icmp0, * icmp1;
2603 to_next[0] = bi0 = from[0];
2604 to_next[1] = bi1 = from[1];
2608 n_left_to_next -= 2;
2626 ICMP4_time_exceeded_ttl_exceeded_in_transit,
2637 icmp0 = (icmp46_header_t *) udp0;
2639 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
2640 rx_fib_index0, node, next0, thread_index,
2651 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
2665 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
2666 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
2680 ICMP4_destination_unreachable_destination_unreachable_host,
2702 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
2703 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
2704 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
2705 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
2706 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
2707 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
2709 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
2710 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
2711 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
2712 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
2714 old_port0 = tcp0->src;
2715 tcp0->src = new_port0;
2717 sum0 = tcp0->checksum;
2728 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
2736 case SNAT_SESSION_UDP_ACTIVE:
2739 case SNAT_SESSION_TCP_SYN_SENT:
2740 case SNAT_SESSION_TCP_FIN_WAIT:
2741 case SNAT_SESSION_TCP_CLOSE_WAIT:
2742 case SNAT_SESSION_TCP_LAST_ACK:
2745 case SNAT_SESSION_TCP_ESTABLISHED:
2776 ICMP4_time_exceeded_ttl_exceeded_in_transit,
2787 icmp1 = (icmp46_header_t *) udp1;
2789 next1 =
icmp_in2out(sm, b1, ip1, icmp1, sw_if_index1,
2790 rx_fib_index1, node, next1, thread_index,
2801 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
2815 key1.
out_port = clib_host_to_net_u16 (lo_port1 +
2816 ((i1 + clib_net_to_host_u16 (tcp1->src)) % dm1->
ports_per_host));
2830 ICMP4_destination_unreachable_destination_unreachable_host,
2837 new_port1 = ses1->out.out_port;
2852 ses1->state = SNAT_SESSION_TCP_SYN_SENT;
2853 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_SYN_SENT)
2854 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
2855 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_ESTABLISHED)
2856 ses1->state = SNAT_SESSION_TCP_FIN_WAIT;
2857 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_FIN_WAIT)
2859 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_CLOSE_WAIT)
2860 ses1->state = SNAT_SESSION_TCP_LAST_ACK;
2861 else if (tcp1->flags == 0 && ses1->state == SNAT_SESSION_UNKNOWN)
2862 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
2864 old_port1 = tcp1->src;
2865 tcp1->src = new_port1;
2867 sum1 = tcp1->checksum;
2878 ses1->state = SNAT_SESSION_UDP_ACTIVE;
2886 case SNAT_SESSION_UDP_ACTIVE:
2889 case SNAT_SESSION_TCP_SYN_SENT:
2890 case SNAT_SESSION_TCP_FIN_WAIT:
2891 case SNAT_SESSION_TCP_CLOSE_WAIT:
2892 case SNAT_SESSION_TCP_LAST_ACK:
2895 case SNAT_SESSION_TCP_ESTABLISHED:
2918 to_next, n_left_to_next,
2919 bi0, bi1, next0, next1);
2922 while (n_left_from > 0 && n_left_to_next > 0)
2931 u16 old_port0, new_port0, lo_port0, i0;
2939 icmp46_header_t * icmp0;
2947 n_left_to_next -= 1;
2962 ICMP4_time_exceeded_ttl_exceeded_in_transit,
2973 icmp0 = (icmp46_header_t *) udp0;
2975 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
2976 rx_fib_index0, node, next0, thread_index,
2987 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
3001 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
3002 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
3016 ICMP4_destination_unreachable_destination_unreachable_host,
3038 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
3039 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
3040 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
3041 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
3042 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
3043 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
3045 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
3046 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
3047 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
3048 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
3050 old_port0 = tcp0->src;
3051 tcp0->src = new_port0;
3053 sum0 = tcp0->checksum;
3064 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
3072 case SNAT_SESSION_UDP_ACTIVE:
3075 case SNAT_SESSION_TCP_SYN_SENT:
3076 case SNAT_SESSION_TCP_FIN_WAIT:
3077 case SNAT_SESSION_TCP_CLOSE_WAIT:
3078 case SNAT_SESSION_TCP_LAST_ACK:
3081 case SNAT_SESSION_TCP_ESTABLISHED:
3104 to_next, n_left_to_next,
3112 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
3119 .name =
"nat44-det-in2out",
3120 .vector_size =
sizeof (
u32),
3159 u8 *p_dont_translate,
void *d,
void *e)
3161 icmp46_header_t *icmp0;
3166 u8 dont_translate = 0;
3170 void *l4_header = 0;
3171 icmp46_header_t *inner_icmp0;
3186 protocol = SNAT_PROTOCOL_ICMP;
3198 case SNAT_PROTOCOL_ICMP:
3199 inner_icmp0 = (icmp46_header_t*)l4_header;
3203 case SNAT_PROTOCOL_UDP:
3204 case SNAT_PROTOCOL_TCP:
3208 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
3220 IP_PROTOCOL_ICMP, rx_fib_index0)))
3226 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
3239 IP_PROTOCOL_ICMP, rx_fib_index0)))
3244 if (icmp0->type != ICMP4_echo_request)
3246 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
3252 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
3264 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
3272 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
3279 ses0->
state = SNAT_SESSION_ICMP_ACTIVE;
3283 *p_proto = protocol;
3286 p_value->
addr = new_addr0;
3290 *p_dont_translate = dont_translate;
3309 u32 n_left_from, *from, *to_next = 0;
3316 u32 n_left_to_next_worker = 0, *to_next_worker = 0;
3317 u32 next_worker_index = 0;
3318 u32 current_worker_index = ~0;
3348 while (n_left_from > 0)
3374 if (next_worker_index != current_worker_index)
3381 handoff_queue_elt_by_worker_index);
3385 current_worker_index = next_worker_index;
3389 to_next_worker[0] = bi0;
3391 n_left_to_next_worker--;
3393 if (n_left_to_next_worker == 0)
3397 current_worker_index = ~0;
3398 handoff_queue_elt_by_worker_index[next_worker_index] = 0;
3434 for (i = 0; i <
vec_len (handoff_queue_elt_by_worker_index); i++)
3436 if (handoff_queue_elt_by_worker_index[i])
3438 hf = handoff_queue_elt_by_worker_index[
i];
3446 handoff_queue_elt_by_worker_index[
i] = 0;
3451 congested_handoff_queue_by_worker_index[
i] =
3455 current_worker_index = ~0;
3469 .name =
"nat44-in2out-worker-handoff",
3470 .vector_size =
sizeof (
u32),
3494 .name =
"nat44-in2out-output-worker-handoff",
3495 .vector_size =
sizeof (
u32),
3538 u32 n_left_from, * from, * to_next;
3540 u32 pkts_processed = 0;
3547 while (n_left_from > 0)
3552 to_next, n_left_to_next);
3554 while (n_left_from > 0 && n_left_to_next > 0)
3568 n_left_to_next -= 1;
3579 if (proto0 == SNAT_PROTOCOL_TCP || proto0 == SNAT_PROTOCOL_UDP)
3586 else if (proto0 == SNAT_PROTOCOL_ICMP)
3604 to_next, n_left_to_next,
3612 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
3619 .name =
"nat44-hairpin-dst",
3620 .vector_size =
sizeof (
u32),
3639 u32 n_left_from, * from, * to_next;
3641 u32 pkts_processed = 0;
3648 while (n_left_from > 0)
3653 to_next, n_left_to_next);
3655 while (n_left_from > 0 && n_left_to_next > 0)
3669 n_left_to_next -= 1;
3678 if ((nat_interface_is_inside(i)) && (sw_if_index0 == i->sw_if_index))
3680 if (PREDICT_FALSE ((vnet_buffer (b0)->snat.flags) &
3681 SNAT_FLAG_HAIRPINNING))
3683 if (PREDICT_TRUE (sm->num_workers > 1))
3684 next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH;
3686 next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT;
3696 to_next, n_left_to_next,
3704 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
3706 return frame->n_vectors;
3711 .name =
"nat44-hairpin-src",
3712 .vector_size =
sizeof (
u32),
3733 u32 n_left_from, * from, * to_next;
3735 u32 pkts_processed = 0;
3737 u32 stats_node_index;
3745 while (n_left_from > 0)
3750 to_next, n_left_to_next);
3752 while (n_left_from > 0 && n_left_to_next > 0)
3760 u32 new_addr0, old_addr0;
3761 u16 old_port0, new_port0;
3764 icmp46_header_t * icmp0;
3775 n_left_to_next -= 1;
3783 icmp0 = (icmp46_header_t *) udp0;
3792 ICMP4_time_exceeded_ttl_exceeded_in_transit,
3805 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
3806 rx_fib_index0, node, next0, ~0, 0, 0);
3817 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
3823 new_port0 = sm0.
port;
3838 old_port0 = tcp0->src_port;
3839 tcp0->src_port = new_port0;
3841 sum0 = tcp0->checksum;
3861 sum0 = tcp0->checksum;
3886 to_next, n_left_to_next,
3894 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
3902 .name =
"nat44-in2out-fast",
3903 .vector_size =
sizeof (
u32),
ip4_address_t external_addr
vnet_config_main_t config_main
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
static snat_session_t * snat_in2out_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index, u32 thread_index, f64 now, vlib_main_t *vm, vlib_node_runtime_t *node)
fib_protocol_t fp_proto
protocol type
u32 sessions_per_user_list_head_index
static u8 * format_snat_in2out_trace(u8 *s, va_list *args)
clib_bihash_16_8_t out2in_ed
sll srl srl sll sra u16x4 i
static uword snat_in2out_slow_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
u32 fq_in2out_output_index
static u8 * format_snat_in2out_fast_trace(u8 *s, va_list *args)
static uword snat_in2out_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_slow_path, int is_output_feature)
static int ip4_header_bytes(ip4_header_t *i)
static f64 vlib_time_now(vlib_main_t *vm)
static char * snat_in2out_error_strings[]
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
int nat_ip4_reass_add_fragment(nat_reass_ip4_t *reass, u32 bi)
Cache fragment.
static uword snat_in2out_worker_handoff_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static void snat_icmp_hairpinning(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0)
static void snat_det_ses_close(snat_det_map_t *dm, snat_det_session_t *ses)
struct _vlib_node_registration vlib_node_registration_t
static snat_det_session_t * snat_det_find_ses_by_in(snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port, snat_det_out_key_t out_key)
static void snat_det_forward(snat_det_map_t *dm, ip4_address_t *in_addr, ip4_address_t *out_addr, u16 *lo_port)
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
clib_bihash_16_8_t in2out_ed
int snat_static_mapping_match(snat_main_t *sm, snat_session_key_t match, snat_session_key_t *mapping, u8 by_external, u8 *is_addr_only, u8 *twice_nat)
Match NAT44 static mapping.
u32 buffer_index[VLIB_FRAME_SIZE]
vlib_error_t * errors
Vector of errors for this node.
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
struct _tcp_header tcp_header_t
VLIB_NODE_FUNCTION_MULTIARCH(snat_in2out_node, snat_in2out_fast_path_fn)
u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation.
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
clib_bihash_8_8_t user_hash
vlib_node_registration_t snat_hairpin_dst_node
(constructor) VLIB_REGISTER_NODE (snat_hairpin_dst_node)
static uword snat_in2out_output_slow_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vlib_node_registration_t snat_in2out_output_slowpath_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_output_slowpath_node)
u32 in2out_output_node_index
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
#define static_always_inline
static uword ip4_header_checksum_is_valid(ip4_header_t *i)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
vlib_node_registration_t snat_in2out_output_worker_handoff_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_output_worker_handoff_node)
ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
vlib_node_registration_t snat_in2out_fast_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_fast_node)
static uword snat_in2out_output_worker_handoff_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
ip4_address_t ext_host_addr
static int snat_not_translate(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, ip4_header_t *ip0, u32 proto0, u32 rx_fib_index0, u32 thread_index)
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
static uword snat_det_in2out_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Aggregrate type for a prefix.
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
static u8 * format_snat_in2out_worker_handoff_trace(u8 *s, va_list *args)
static void * ip4_next_header(ip4_header_t *i)
static u32 slow_path(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, u32 rx_fib_index0, snat_session_key_t *key0, snat_session_t **sessionp, vlib_node_runtime_t *node, u32 next0, u32 thread_index)
vlib_node_registration_t snat_in2out_slowpath_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_slowpath_node)
static uword snat_in2out_worker_handoff_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u8 is_output)
fib_node_index_t fib_table_lookup(u32 fib_index, const fib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
static u8 * format_nat44_in2out_reass_trace(u8 *s, va_list *args)
#define foreach_snat_in2out_error
static int ip4_is_fragment(ip4_header_t *i)
static void nat44_reass_hairpinning(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, u16 sport, u16 dport, u32 proto0)
snat_user_t * nat_user_get_or_create(snat_main_t *sm, ip4_address_t *addr, u32 fib_index, u32 thread_index)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
static uword nat44_in2out_reass_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
snat_det_session_t * sessions
static u32 icmp_in2out_slow_path(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0, u32 sw_if_index0, u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0, f64 now, u32 thread_index, snat_session_t **p_s0)
static void clib_dlist_addtail(dlist_elt_t *pool, u32 head_index, u32 new_index)
snat_static_mapping_t * static_mappings
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
static void * vnet_get_config_data(vnet_config_main_t *cm, u32 *config_index, u32 *next_index, u32 n_data_bytes)
void snat_ipfix_logging_nat44_ses_create(u32 src_ip, u32 nat_src_ip, snat_protocol_t snat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session create event.
static vlib_frame_queue_elt_t * vlib_get_worker_handoff_queue_elt(u32 frame_queue_index, u32 vlib_worker_index, vlib_frame_queue_elt_t **handoff_queue_elt_by_worker_index)
clib_bihash_8_8_t static_mapping_by_external
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
#define SNAT_SESSION_FLAG_UNKNOWN_PROTO
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
vlib_error_t error
Error code for buffers to be enqueued to error handler.
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
snat_interface_t * output_feature_interfaces
static void snat_hairpinning_unknown_proto(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip)
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
static_always_inline int is_hairpinning(snat_main_t *sm, ip4_address_t *dst_addr)
vlib_node_registration_t nat44_in2out_reass_node
(constructor) VLIB_REGISTER_NODE (nat44_in2out_reass_node)
static_always_inline uword vlib_get_thread_index(void)
u8 nat_reass_is_drop_frag(u8 is_ip6)
Get status of virtual fragmentation reassembly.
#define CLIB_PREFETCH(addr, size, type)
static uword snat_in2out_output_fast_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
snat_get_worker_function_t * worker_in2out_cb
#define vec_free(V)
Free vector's memory (no header).
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
deterministic NAT definitions
#define clib_warning(format, args...)
#define VLIB_BUFFER_IS_TRACED
#define clib_memcpy(a, b, c)
static int ip4_is_first_fragment(ip4_header_t *i)
static uword snat_in2out_fast_static_map_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
u32 fib_node_index_t
A typedef of a node index.
8 octet key, 8 octet key value pair
static_always_inline snat_in2out_error_t icmp_get_key(ip4_header_t *ip0, snat_session_key_t *p_key0)
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
u32 tcp_transitory_timeout
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
static snat_det_map_t * snat_det_map_by_user(snat_main_t *sm, ip4_address_t *user_addr)
static uword nat44_hairpinning_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
snat_get_worker_function_t * worker_out2in_cb
static u32 ip_proto_to_snat_proto(u8 ip_proto)
#define VLIB_NODE_FLAG_TRACE
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
static int snat_not_translate_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, ip4_header_t *ip0, u32 proto0, u32 rx_fib_index0)
Check if packet should be translated.
vlib_node_registration_t nat44_hairpinning_node
(constructor) VLIB_REGISTER_NODE (nat44_hairpinning_node)
snat_session_t * nat_session_alloc_or_recycle(snat_main_t *sm, snat_user_t *u, u32 thread_index)
vlib_node_registration_t snat_det_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_det_in2out_node)
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
#define vec_elt(v, i)
Get vector value at index i.
static uword snat_hairpin_src_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define FIB_NODE_INDEX_INVALID
int snat_alloc_outside_address_and_port(snat_address_t *addresses, u32 fib_index, u32 thread_index, snat_session_key_t *k, u32 *address_indexp, u16 port_per_thread, u32 snat_thread_index)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_node_registration_t snat_in2out_worker_handoff_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_worker_handoff_node)
static_always_inline u8 is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr)
snat_main_per_thread_data_t * per_thread_data
#define SNAT_FLAG_HAIRPINNING
static int snat_hairpinning(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, udp_header_t *udp0, tcp_header_t *tcp0, u32 proto0)
Hairpinning.
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
#define ip_csum_update(sum, old, new, type, field)
vlib_node_registration_t snat_hairpin_src_node
(constructor) VLIB_REGISTER_NODE (snat_hairpin_src_node)
static snat_session_t * snat_in2out_lb(snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index, u32 thread_index, f64 now, vlib_main_t *vm, vlib_node_runtime_t *node)
nat_reass_ip4_t * nat_ip4_reass_find_or_create(ip4_address_t src, ip4_address_t dst, u16 frag_id, u8 proto, u8 reset_timeout, u32 **bi_to_drop)
Find or create reassembly.
snat_address_t * addresses
static void vlib_put_frame_queue_elt(vlib_frame_queue_elt_t *hf)
u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, u8 *p_proto, snat_session_key_t *p_value, u8 *p_dont_translate, void *d, void *e)
Get address and port values to be used for ICMP packet translation and create session if needed...
struct _vnet_feature_arc_registration vnet_feature_arc_registration_t
feature registration object
vnet_feature_arc_registration_t vnet_feat_arc_ip4_local
static uword snat_in2out_fast_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static snat_det_session_t * snat_det_get_ses_by_out(snat_det_map_t *dm, ip4_address_t *in_addr, u64 out_key)
#define SNAT_SESSION_FLAG_STATIC_MAPPING
#define VLIB_REGISTER_NODE(x,...)
static vlib_thread_main_t * vlib_get_thread_main()
#define vec_foreach(var, vec)
Vector iterator.
vlib_node_registration_t snat_in2out_output_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_output_node)
static_always_inline void nat_send_all_to_node(vlib_main_t *vm, u32 *bi_vector, vlib_node_runtime_t *node, vlib_error_t *error, u32 next)
u16 flags
Copy of main node flags.
#define is_twice_nat_session(s)
Check if NAT session is twice NAT.
static uword snat_hairpin_dst_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
void nat_ip4_reass_get_frags(nat_reass_ip4_t *reass, u32 **bi)
Get cached fragments.
NAT plugin virtual fragmentation reassembly.
vnet_feature_config_main_t * feature_config_mains
feature config main objects
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
#define CLIB_CACHE_LINE_BYTES
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
static snat_det_session_t * snat_det_ses_create(snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port, snat_det_out_key_t *out)
static u8 maximum_sessions_exceeded(snat_main_t *sm, u32 thread_index)
vnet_feature_main_t feature_main
snat_session_t * sessions
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
snat_icmp_match_function_t * icmp_match_in2out_cb
#define SNAT_SESSION_FLAG_LOAD_BALANCING
clib_bihash_8_8_t static_mapping_by_local
static u16 ip_csum_fold(ip_csum_t c)
snat_interface_t * interfaces
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
u32 tcp_established_timeout
static u32 icmp_in2out(snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0, u32 sw_if_index0, u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0, u32 thread_index, void *d, void *e)