52 tag = t->
is_slow_path ?
"SNAT_IN2OUT_SLOW_PATH" :
"SNAT_IN2OUT_FAST_PATH";
54 s =
format (s,
"%s: sw_if_index %d, next index %d, session %d", tag,
66 s =
format (s,
"SANT_IN2OUT_FAST: sw_if_index %d, next index %d",
80 m = t->
do_handoff ?
"next worker" :
"same worker";
92 #define foreach_snat_in2out_error \ 93 _(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \ 94 _(IN2OUT_PACKETS, "Good in2out packets processed") \ 95 _(OUT_OF_PORTS, "Out of ports") \ 96 _(BAD_OUTSIDE_FIB, "Outside VRF ID not found") \ 97 _(BAD_ICMP_TYPE, "unsupported ICMP type") \ 98 _(NO_TRANSLATION, "No translation") 101 #define _(sym,str) SNAT_IN2OUT_ERROR_##sym, 108 #define _(sym,string) string, 177 if (clib_bihash_search_8_8 (&sm->out2in, &kv0, &value0))
190 if (sw_if_index == ~0)
200 if ((i->is_inside == 0) && (sw_if_index == i->sw_if_index))
212 snat_session_t ** sessionp,
221 u32 oldest_per_user_translation_list_index;
222 dlist_elt_t * oldest_per_user_translation_list_elt;
227 u32 address_index = ~0;
228 u32 outside_fib_index;
232 p =
hash_get (sm->ip4_main->fib_index_by_table_id, sm->outside_vrf_id);
235 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_OUTSIDE_FIB];
238 outside_fib_index = p[0];
246 if (clib_bihash_search_8_8 (&sm->user_hash, &kv0, &value0))
249 pool_get (sm->per_thread_data[cpu_index].users, u);
250 memset (u, 0,
sizeof (*u));
254 pool_get (sm->per_thread_data[cpu_index].list_pool, per_user_list_head_elt);
257 sm->per_thread_data[cpu_index].list_pool;
262 kv0.
value = u - sm->per_thread_data[cpu_index].users;
265 clib_bihash_add_del_8_8 (&sm->user_hash, &kv0, 1 );
274 if (u->
nsessions >= sm->max_translations_per_user)
278 oldest_per_user_translation_list_index =
282 ASSERT (oldest_per_user_translation_list_index != ~0);
287 oldest_per_user_translation_list_index);
289 oldest_per_user_translation_list_elt =
291 oldest_per_user_translation_list_index);
294 session_index = oldest_per_user_translation_list_elt->
value;
302 kv0.
key = s->in2out.as_u64;
303 if (clib_bihash_add_del_8_8 (&sm->in2out, &kv0, 0 ))
305 kv0.
key = s->out2in.as_u64;
306 if (clib_bihash_add_del_8_8 (&sm->out2in, &kv0, 0 ))
311 s->out2in.addr.as_u32,
315 s->in2out.fib_index);
318 (sm, &s->out2in, s->outside_address_index);
319 s->outside_address_index = ~0;
326 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
329 s->outside_address_index = address_index;
333 u8 static_mapping = 1;
343 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
349 pool_get (sm->per_thread_data[cpu_index].sessions, s);
350 memset (s, 0,
sizeof (*s));
352 s->outside_address_index = address_index;
365 pool_get (sm->per_thread_data[cpu_index].list_pool,
366 per_user_translation_list_elt);
368 per_user_translation_list_elt -
369 sm->per_thread_data[cpu_index].list_pool);
371 per_user_translation_list_elt->
value =
372 s - sm->per_thread_data[cpu_index].sessions;
373 s->per_user_index = per_user_translation_list_elt -
374 sm->per_thread_data[cpu_index].list_pool;
378 s->per_user_list_head_index,
379 per_user_translation_list_elt -
380 sm->per_thread_data[cpu_index].list_pool);
386 s->out2in.fib_index = outside_fib_index;
390 kv0.
key = s->in2out.as_u64;
391 kv0.
value = s - sm->per_thread_data[cpu_index].sessions;
392 if (clib_bihash_add_del_8_8 (&sm->in2out, &kv0, 1 ))
395 kv0.
key = s->out2in.as_u64;
396 kv0.
value = s - sm->per_thread_data[cpu_index].sessions;
398 if (clib_bihash_add_del_8_8 (&sm->out2in, &kv0, 1 ))
402 worker_by_out_key.
addr = s->out2in.addr;
403 worker_by_out_key.
port = s->out2in.port;
404 worker_by_out_key.
fib_index = s->out2in.fib_index;
406 kv0.
value = cpu_index;
407 clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv0, 1);
411 s->out2in.addr.as_u32,
415 s->in2out.fib_index);
423 icmp46_header_t *icmp0;
428 icmp46_header_t *inner_icmp0;
447 case SNAT_PROTOCOL_ICMP:
448 inner_icmp0 = (icmp46_header_t*)l4_header;
452 case SNAT_PROTOCOL_UDP:
453 case SNAT_PROTOCOL_TCP:
457 return SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL;
481 u8 *p_dont_translate,
void *d)
485 icmp46_header_t *icmp0;
489 snat_session_t *s0 = 0;
490 u8 dont_translate = 0;
512 if (clib_bihash_search_8_8 (&sm->in2out, &kv0, &value0))
515 IP_PROTOCOL_ICMP, rx_fib_index0)))
523 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
528 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
529 &s0, node, next0, cpu_index);
537 icmp0->type != ICMP4_echo_reply &&
540 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
552 *p_value = s0->out2in;
553 *p_dont_translate = dont_translate;
555 *(snat_session_t**)d = s0;
575 u8 *p_dont_translate,
void *d)
579 icmp46_header_t *icmp0;
584 u8 dont_translate = 0;
607 IP_PROTOCOL_ICMP, rx_fib_index0)))
619 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
625 (icmp0->type != ICMP4_echo_reply || !is_addr_only) &&
628 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
637 *p_dont_translate = dont_translate;
644 icmp46_header_t * icmp0,
656 icmp46_header_t *inner_icmp0;
658 u32 new_addr0, old_addr0;
659 u16 old_id0, new_id0;
666 next0_tmp = sm->icmp_match_in2out_cb(sm, node, cpu_index, b0,
667 &key0, &sm0, &dont_translate, d);
700 sum0 = icmp0->checksum;
721 sum0 = icmp0->checksum;
728 case SNAT_PROTOCOL_ICMP:
729 inner_icmp0 = (icmp46_header_t*)l4_header;
736 sum0 = icmp0->checksum;
741 case SNAT_PROTOCOL_UDP:
742 case SNAT_PROTOCOL_TCP:
747 sum0 = icmp0->checksum;
788 u32 new_dst_addr0 = 0, old_dst_addr0, ti = 0, si;
789 u16 new_dst_port0, old_dst_port0;
798 if (clib_bihash_search_8_8 (&sm->out2in, &kv0, &value0))
804 new_dst_port0 = sm0.
port;
811 if (sm->num_workers > 1)
817 if (clib_bihash_search_8_8 (&sm->worker_by_out, &kv0, &value0))
823 ti = sm->num_workers;
826 new_dst_addr0 = s0->in2out.addr.as_u32;
827 new_dst_port0 = s0->in2out.port;
841 old_dst_port0 = tcp0->dst;
846 tcp0->dst = new_dst_port0;
847 sum0 = tcp0->checksum;
866 icmp46_header_t * icmp0,
873 snat_session_t ** p_s0)
875 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
876 next0, cpu_index, p_s0);
877 snat_session_t * s0 = *p_s0;
881 s0->last_heard = now;
890 s0->per_user_list_head_index,
902 u32 n_left_from, * from, * to_next;
904 u32 pkts_processed = 0;
908 u32 stats_node_index;
918 while (n_left_from > 0)
923 to_next, n_left_to_next);
925 while (n_left_from >= 4 && n_left_to_next >= 2)
930 u32 sw_if_index0, sw_if_index1;
933 u32 new_addr0, old_addr0, new_addr1, old_addr1;
934 u16 old_port0, new_port0, old_port1, new_port1;
937 icmp46_header_t * icmp0, * icmp1;
939 u32 rx_fib_index0, rx_fib_index1;
941 snat_session_t * s0 = 0, * s1 = 0;
959 to_next[0] = bi0 = from[0];
960 to_next[1] = bi1 = from[1];
972 icmp0 = (icmp46_header_t *) udp0;
975 rx_fib_index0 =
vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
984 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1001 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
1002 node, next0, now, cpu_index, &s0);
1008 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
1022 if (
PREDICT_FALSE (clib_bihash_search_8_8 (&sm->in2out, &kv0, &value0) != 0))
1027 proto0, rx_fib_index0)))
1030 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
1031 &s0, node, next0, cpu_index);
1058 old_port0 = tcp0->src_port;
1059 tcp0->src_port = s0->out2in.port;
1060 new_port0 = tcp0->src_port;
1062 sum0 = tcp0->checksum;
1082 s0->last_heard = now;
1089 s0->per_user_index);
1091 s0->per_user_list_head_index,
1092 s0->per_user_index);
1106 t->
session_index = s0 - sm->per_thread_data[cpu_index].sessions;
1114 icmp1 = (icmp46_header_t *) udp1;
1117 rx_fib_index1 =
vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
1124 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1141 (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
1142 next1, now, cpu_index, &s1);
1148 if (
PREDICT_FALSE (proto1 == ~0 || proto1 == SNAT_PROTOCOL_ICMP))
1162 if (
PREDICT_FALSE(clib_bihash_search_8_8 (&sm->in2out, &kv1, &value1) != 0))
1167 proto1, rx_fib_index1)))
1170 next1 =
slow_path (sm, b1, ip1, rx_fib_index1, &key1,
1171 &s1, node, next1, cpu_index);
1198 old_port1 = tcp1->src_port;
1199 tcp1->src_port = s1->out2in.port;
1200 new_port1 = tcp1->src_port;
1202 sum1 = tcp1->checksum;
1222 s1->last_heard = now;
1229 s1->per_user_index);
1231 s1->per_user_list_head_index,
1232 s1->per_user_index);
1245 t->
session_index = s1 - sm->per_thread_data[cpu_index].sessions;
1252 to_next, n_left_to_next,
1253 bi0, bi1, next0, next1);
1256 while (n_left_from > 0 && n_left_to_next > 0)
1264 u32 new_addr0, old_addr0;
1265 u16 old_port0, new_port0;
1268 icmp46_header_t * icmp0;
1272 snat_session_t * s0 = 0;
1281 n_left_to_next -= 1;
1289 icmp0 = (icmp46_header_t *) udp0;
1292 rx_fib_index0 =
vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
1299 ICMP4_time_exceeded_ttl_exceeded_in_transit,
1316 (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
1317 next0, now, cpu_index, &s0);
1323 if (
PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
1337 if (clib_bihash_search_8_8 (&sm->in2out, &kv0, &value0))
1342 proto0, rx_fib_index0)))
1345 next0 =
slow_path (sm, b0, ip0, rx_fib_index0, &key0,
1346 &s0, node, next0, cpu_index);
1374 old_port0 = tcp0->src_port;
1375 tcp0->src_port = s0->out2in.port;
1376 new_port0 = tcp0->src_port;
1378 sum0 = tcp0->checksum;
1398 s0->last_heard = now;
1405 s0->per_user_index);
1407 s0->per_user_list_head_index,
1408 s0->per_user_index);
1422 t->
session_index = s0 - sm->per_thread_data[cpu_index].sessions;
1429 to_next, n_left_to_next,
1437 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
1452 .name =
"snat-in2out",
1453 .vector_size =
sizeof (
u32),
1485 .name =
"snat-in2out-slowpath",
1486 .vector_size =
sizeof (
u32),
1516 u32 n_left_from, * from, * to_next;
1518 u32 pkts_processed = 0;
1526 while (n_left_from > 0)
1531 to_next, n_left_to_next);
1533 while (n_left_from >= 4 && n_left_to_next >= 2)
1538 u32 sw_if_index0, sw_if_index1;
1542 u16 old_port0, new_port0, lo_port0, i0;
1543 u16 old_port1, new_port1, lo_port1, i1;
1566 to_next[0] = bi0 = from[0];
1567 to_next[1] = bi1 = from[1];
1571 n_left_to_next -= 2;
1591 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
1604 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
1605 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
1616 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
1637 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
1638 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
1639 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
1640 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
1641 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
1642 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
1644 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
1645 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
1646 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
1647 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
1649 old_port0 = tcp0->src;
1650 tcp0->src = new_port0;
1652 sum0 = tcp0->checksum;
1663 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
1671 case SNAT_SESSION_UDP_ACTIVE:
1674 case SNAT_SESSION_TCP_SYN_SENT:
1675 case SNAT_SESSION_TCP_FIN_WAIT:
1676 case SNAT_SESSION_TCP_CLOSE_WAIT:
1677 case SNAT_SESSION_TCP_LAST_ACK:
1680 case SNAT_SESSION_TCP_ESTABLISHED:
1713 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
1726 key1.
out_port = clib_host_to_net_u16 (lo_port1 +
1727 ((i1 + clib_net_to_host_u16 (tcp1->src)) % dm1->
ports_per_host));
1738 b1->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
1743 new_port1 = ses1->out.out_port;
1759 ses1->state = SNAT_SESSION_TCP_SYN_SENT;
1760 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_SYN_SENT)
1761 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
1762 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_ESTABLISHED)
1763 ses1->state = SNAT_SESSION_TCP_FIN_WAIT;
1764 else if (tcp1->flags &
TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_FIN_WAIT)
1766 else if (tcp1->flags &
TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_CLOSE_WAIT)
1767 ses1->state = SNAT_SESSION_TCP_LAST_ACK;
1768 else if (tcp1->flags == 0 && ses1->state == SNAT_SESSION_UNKNOWN)
1769 ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
1771 old_port1 = tcp1->src;
1772 tcp1->src = new_port1;
1774 sum1 = tcp1->checksum;
1785 ses1->state = SNAT_SESSION_UDP_ACTIVE;
1793 case SNAT_SESSION_UDP_ACTIVE:
1796 case SNAT_SESSION_TCP_SYN_SENT:
1797 case SNAT_SESSION_TCP_FIN_WAIT:
1798 case SNAT_SESSION_TCP_CLOSE_WAIT:
1799 case SNAT_SESSION_TCP_LAST_ACK:
1802 case SNAT_SESSION_TCP_ESTABLISHED:
1825 to_next, n_left_to_next,
1826 bi0, bi1, next0, next1);
1829 while (n_left_from > 0 && n_left_to_next > 0)
1838 u16 old_port0, new_port0, lo_port0, i0;
1852 n_left_to_next -= 1;
1869 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
1882 key0.
out_port = clib_host_to_net_u16 (lo_port0 +
1883 ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->
ports_per_host));
1894 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
1915 ses0->
state = SNAT_SESSION_TCP_SYN_SENT;
1916 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_SYN_SENT)
1917 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
1918 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_ESTABLISHED)
1919 ses0->
state = SNAT_SESSION_TCP_FIN_WAIT;
1920 else if (tcp0->flags &
TCP_FLAG_ACK && ses0->
state == SNAT_SESSION_TCP_FIN_WAIT)
1922 else if (tcp0->flags &
TCP_FLAG_FIN && ses0->
state == SNAT_SESSION_TCP_CLOSE_WAIT)
1923 ses0->
state = SNAT_SESSION_TCP_LAST_ACK;
1924 else if (tcp0->flags == 0 && ses0->
state == SNAT_SESSION_UNKNOWN)
1925 ses0->
state = SNAT_SESSION_TCP_ESTABLISHED;
1927 old_port0 = tcp0->src;
1928 tcp0->src = new_port0;
1930 sum0 = tcp0->checksum;
1941 ses0->
state = SNAT_SESSION_UDP_ACTIVE;
1949 case SNAT_SESSION_UDP_ACTIVE:
1952 case SNAT_SESSION_TCP_SYN_SENT:
1953 case SNAT_SESSION_TCP_FIN_WAIT:
1954 case SNAT_SESSION_TCP_CLOSE_WAIT:
1955 case SNAT_SESSION_TCP_LAST_ACK:
1958 case SNAT_SESSION_TCP_ESTABLISHED:
1981 to_next, n_left_to_next,
1989 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
1996 .name =
"snat-det-in2out",
1997 .vector_size =
sizeof (
u32),
2027 u32 n_left_from, *from, *to_next = 0;
2034 u32 n_left_to_next_worker = 0, *to_next_worker = 0;
2035 u32 next_worker_index = 0;
2036 u32 current_worker_index = ~0;
2046 sm->first_worker_index + sm->num_workers - 1,
2053 while (n_left_from > 0)
2073 next_worker_index = sm->worker_in2out_cb(ip0, rx_fib_index0);
2079 if (next_worker_index != current_worker_index)
2086 handoff_queue_elt_by_worker_index);
2090 current_worker_index = next_worker_index;
2094 to_next_worker[0] = bi0;
2096 n_left_to_next_worker--;
2098 if (n_left_to_next_worker == 0)
2102 current_worker_index = ~0;
2103 handoff_queue_elt_by_worker_index[next_worker_index] = 0;
2139 for (i = 0; i <
vec_len (handoff_queue_elt_by_worker_index); i++)
2141 if (handoff_queue_elt_by_worker_index[i])
2143 hf = handoff_queue_elt_by_worker_index[
i];
2151 handoff_queue_elt_by_worker_index[
i] = 0;
2156 congested_handoff_queue_by_worker_index[
i] =
2160 current_worker_index = ~0;
2166 .name =
"snat-in2out-worker-handoff",
2167 .vector_size =
sizeof (
u32),
2185 u32 n_left_from, * from, * to_next;
2187 u32 pkts_processed = 0;
2189 u32 stats_node_index;
2197 while (n_left_from > 0)
2202 to_next, n_left_to_next);
2204 while (n_left_from > 0 && n_left_to_next > 0)
2212 u32 new_addr0, old_addr0;
2213 u16 old_port0, new_port0;
2216 icmp46_header_t * icmp0;
2227 n_left_to_next -= 1;
2235 icmp0 = (icmp46_header_t *) udp0;
2247 next0 =
icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
2248 rx_fib_index0, node, next0, ~0, 0);
2258 b0->
error = node->
errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
2264 new_port0 = sm0.
port;
2279 old_port0 = tcp0->src_port;
2280 tcp0->src_port = new_port0;
2282 sum0 = tcp0->checksum;
2302 sum0 = tcp0->checksum;
2327 to_next, n_left_to_next,
2335 SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
2343 .name =
"snat-in2out-fast",
2344 .vector_size =
sizeof (
u32),
#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
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
u32 sessions_per_user_list_head_index
static u8 * format_snat_in2out_trace(u8 *s, va_list *args)
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)
static void clib_dlist_init(dlist_elt_t *pool, u32 index)
u8 runtime_data[0]
Function dependent node-runtime data.
static snat_det_session_t * snat_det_find_ses_by_in(snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port)
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 cpu_index)
static u8 * format_snat_in2out_fast_trace(u8 *s, va_list *args)
int snat_alloc_outside_address_and_port(snat_main_t *sm, u32 fib_index, snat_session_key_t *k, u32 *address_indexp)
static int ip4_header_bytes(ip4_header_t *i)
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
static f64 vlib_time_now(vlib_main_t *vm)
static char * snat_in2out_error_strings[]
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_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
static uword snat_in2out_worker_handoff_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
struct _vlib_node_registration vlib_node_registration_t
static uword snat_in2out_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_slow_path)
static void snat_det_forward(snat_det_map_t *dm, ip4_address_t *in_addr, ip4_address_t *out_addr, u16 *lo_port)
void snat_ipfix_logging_nat44_ses_delete(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 delete event.
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.
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
struct _tcp_header tcp_header_t
VLIB_NODE_FUNCTION_MULTIARCH(snat_in2out_node, snat_in2out_fast_path_fn)
static void 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.
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.
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)
ip4_address_t ext_host_addr
#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.
static u8 * format_snat_in2out_worker_handoff_trace(u8 *s, va_list *args)
static void * ip4_next_header(ip4_header_t *i)
vlib_node_registration_t snat_in2out_slowpath_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_slowpath_node)
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 cpu_index, snat_session_t **p_s0)
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.
#define foreach_snat_in2out_error
#define SNAT_TCP_TRANSITORY_TIMEOUT
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
deterministic NAT definitions
snat_det_session_t * sessions
u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, u32 cpu_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d)
Get address and port values to be used for packet SNAT translation and create session if needed...
static void clib_dlist_addtail(dlist_elt_t *pool, u32 head_index, u32 new_index)
uword os_get_cpu_number(void)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
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 cpu_index, void *d)
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)
#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 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 int snat_not_translate(snat_main_t *sm, snat_runtime_t *rt, u32 sw_if_index0, ip4_header_t *ip0, u32 proto0, u32 rx_fib_index0)
Check if packet should be translated.
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)
Match SNAT static mapping.
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)
#define CLIB_PREFETCH(addr, size, type)
vlib_node_registration_t snat_in2out_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_node)
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
#define clib_warning(format, args...)
#define VLIB_BUFFER_IS_TRACED
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)
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
static snat_protocol_t ip_proto_to_snat_proto(u8 ip_proto)
#define VLIB_NODE_FLAG_TRACE
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
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 snat_det_session_t * snat_det_get_ses_by_out(snat_det_map_t *dm, ip4_address_t *in_addr, u64 out_key)
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.
#define FIB_NODE_INDEX_INVALID
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static snat_det_map_t * snat_det_map_by_user(snat_main_t *sm, ip4_address_t *user_addr)
vlib_node_registration_t snat_in2out_worker_handoff_node
(constructor) VLIB_REGISTER_NODE (snat_in2out_worker_handoff_node)
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)
void snat_free_outside_address_and_port(snat_main_t *sm, snat_session_key_t *k, u32 address_index)
static void vlib_put_frame_queue_elt(vlib_frame_queue_elt_t *hf)
static uword snat_in2out_fast_path_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static void snat_det_ses_close(snat_det_map_t *dm, snat_det_session_t *ses)
#define VLIB_REGISTER_NODE(x,...)
static vlib_thread_main_t * vlib_get_thread_main()
u16 flags
Copy of main node flags.
u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 cpu_index, vlib_buffer_t *b0, snat_session_key_t *p_key, snat_session_key_t *p_value, u8 *p_dont_translate, void *d)
Get address and port values to be used for packet SNAT translation.
#define SNAT_SESSION_FLAG_STATIC_MAPPING
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
#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_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 vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
#define SNAT_TCP_ESTABLISHED_TIMEOUT
static u16 ip_csum_fold(ip_csum_t c)
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)