aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/nat/in2out_ed.c204
-rwxr-xr-xsrc/plugins/nat/nat.c245
-rw-r--r--src/plugins/nat/nat.h17
-rw-r--r--src/plugins/nat/nat44_classify.c8
-rw-r--r--src/plugins/nat/nat44_hairpinning.c17
-rw-r--r--src/plugins/nat/nat_inlines.h155
-rw-r--r--src/plugins/nat/out2in_ed.c141
7 files changed, 424 insertions, 363 deletions
diff --git a/src/plugins/nat/in2out_ed.c b/src/plugins/nat/in2out_ed.c
index 95f80a4ff2b..d78e552d3ba 100644
--- a/src/plugins/nat/in2out_ed.c
+++ b/src/plugins/nat/in2out_ed.c
@@ -72,7 +72,10 @@ nat44_i2o_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg)
nat44_is_idle_session_ctx_t *ctx = arg;
snat_session_t *s;
u64 sess_timeout_time;
- nat_ed_ses_key_t ed_key;
+ u8 proto;
+ u16 r_port, l_port;
+ ip4_address_t *l_addr, *r_addr;
+ u32 fib_index;
clib_bihash_kv_16_8_t ed_kv;
int i;
snat_address_t *a;
@@ -87,23 +90,23 @@ nat44_i2o_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg)
if (is_fwd_bypass_session (s))
goto delete;
- ed_key.l_addr = s->out2in.addr;
- ed_key.r_addr = s->ext_host_addr;
- ed_key.fib_index = s->out2in.fib_index;
+ l_addr = &s->out2in.addr;
+ r_addr = &s->ext_host_addr;
+ fib_index = s->out2in.fib_index;
if (snat_is_unk_proto_session (s))
{
- ed_key.proto = s->in2out.port;
- ed_key.r_port = 0;
- ed_key.l_port = 0;
+ proto = s->in2out.port;
+ r_port = 0;
+ l_port = 0;
}
else
{
- ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
- ed_key.l_port = s->out2in.port;
- ed_key.r_port = s->ext_host_port;
+ proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ l_port = s->out2in.port;
+ r_port = s->ext_host_port;
}
- ed_kv.key[0] = ed_key.as_u64[0];
- ed_kv.key[1] = ed_key.as_u64[1];
+ make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+ &ed_kv);
if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
nat_elog_warn ("out2in_ed key del failed");
@@ -191,11 +194,13 @@ snat_random_port (u16 min, u16 max)
}
static int
-nat_ed_alloc_addr_and_port (snat_main_t * sm, u32 fib_index,
- u32 thread_index, nat_ed_ses_key_t * key,
- snat_session_key_t * key1, u16 port_per_thread,
- u32 snat_thread_index,
+nat_ed_alloc_addr_and_port (snat_main_t * sm, u32 rx_fib_index,
+ u32 snat_proto, u32 thread_index,
+ ip4_address_t r_addr, u16 r_port, u8 proto,
+ u16 port_per_thread, u32 snat_thread_index,
snat_session_t * s,
+ ip4_address_t * allocated_addr,
+ u16 * allocated_port,
clib_bihash_kv_16_8_t * out2in_ed_kv)
{
int i;
@@ -208,11 +213,11 @@ nat_ed_alloc_addr_and_port (snat_main_t * sm, u32 fib_index,
for (i = 0; i < vec_len (sm->addresses); i++)
{
a = sm->addresses + i;
- switch (key1->protocol)
+ switch (snat_proto)
{
#define _(N, j, n, unused) \
case SNAT_PROTOCOL_##N: \
- if (a->fib_index == fib_index) \
+ if (a->fib_index == rx_fib_index) \
{ \
u16 port = snat_random_port (1, port_per_thread); \
u16 attempts = port_per_thread; \
@@ -220,10 +225,9 @@ nat_ed_alloc_addr_and_port (snat_main_t * sm, u32 fib_index,
{ \
--attempts; \
portnum = port_thread_offset + port; \
- make_ed_kv (out2in_ed_kv, &a->addr, &key->r_addr, key->proto, \
- s->out2in.fib_index, clib_host_to_net_u16 (portnum), \
- key->r_port); \
- out2in_ed_kv->value = s - tsm->sessions; \
+ make_ed_kv (&a->addr, &r_addr, proto, s->out2in.fib_index, \
+ clib_host_to_net_u16 (portnum), r_port, \
+ s - tsm->sessions, out2in_ed_kv); \
int rv = clib_bihash_add_del_16_8 (&tsm->out2in_ed, out2in_ed_kv, \
2 /* is_add */); \
if (0 == rv) \
@@ -231,8 +235,8 @@ nat_ed_alloc_addr_and_port (snat_main_t * sm, u32 fib_index,
++a->busy_##n##_port_refcounts[portnum]; \
a->busy_##n##_ports_per_thread[thread_index]++; \
a->busy_##n##_ports++; \
- key1->addr = a->addr; \
- key1->port = clib_host_to_net_u16 (portnum); \
+ *allocated_addr = a->addr; \
+ *allocated_port = clib_host_to_net_u16 (portnum); \
return 0; \
} \
port = (port + 1) % port_per_thread; \
@@ -254,9 +258,9 @@ nat_ed_alloc_addr_and_port (snat_main_t * sm, u32 fib_index,
if (ga)
{
/* fake fib_index to reuse macro */
- fib_index = ~0;
+ rx_fib_index = ~0;
a = ga;
- switch (key1->protocol)
+ switch (snat_proto)
{
foreach_snat_protocol;
default:
@@ -275,8 +279,12 @@ nat_ed_alloc_addr_and_port (snat_main_t * sm, u32 fib_index,
static u32
slow_path_ed (snat_main_t * sm,
vlib_buffer_t * b,
+ ip4_address_t l_addr,
+ ip4_address_t r_addr,
+ u16 l_port,
+ u16 r_port,
+ u8 proto,
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, f64 now)
{
@@ -284,23 +292,22 @@ slow_path_ed (snat_main_t * sm,
snat_session_key_t key0, key1;
lb_nat_type_t lb = 0;
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
- nat_ed_ses_key_t *key = (nat_ed_ses_key_t *) kv->key;
- u32 proto = ip_proto_to_snat_proto (key->proto);
+ u32 snat_proto = ip_proto_to_snat_proto (proto);
nat_outside_fib_t *outside_fib;
fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
clib_bihash_kv_16_8_t out2in_ed_kv;
bool out2in_ed_inserted = false;
+ ip4_address_t allocated_addr;
+ u16 allocated_port;
u8 identity_nat;
fib_prefix_t pfx = {
.fp_proto = FIB_PROTOCOL_IP4,
.fp_len = 32,
- .fp_addr = {
- .ip4.as_u32 = key->r_addr.as_u32,
- },
+ .fp_addr = {.ip4.as_u32 = r_addr.as_u32,},
};
nat44_is_idle_session_ctx_t ctx;
- if (PREDICT_TRUE (proto == SNAT_PROTOCOL_TCP))
+ if (PREDICT_TRUE (snat_proto == SNAT_PROTOCOL_TCP))
{
if (PREDICT_FALSE
(!tcp_flags_is_init
@@ -322,9 +329,9 @@ slow_path_ed (snat_main_t * sm,
}
}
- key0.addr = key->l_addr;
- key0.port = key->l_port;
- key1.protocol = key0.protocol = proto;
+ key0.addr = l_addr;
+ key0.port = l_port;
+ key1.protocol = key0.protocol = snat_proto;
key0.fib_index = rx_fib_index;
key1.fib_index = sm->outside_fib_index;
@@ -366,11 +373,12 @@ slow_path_ed (snat_main_t * sm,
}
/* Try to create dynamic translation */
- if (nat_ed_alloc_addr_and_port (sm, rx_fib_index,
- thread_index, key, &key1,
+ if (nat_ed_alloc_addr_and_port (sm, rx_fib_index, snat_proto,
+ thread_index, r_addr, r_port, proto,
sm->port_per_thread,
tsm->snat_thread_index, s,
- &out2in_ed_kv))
+ &allocated_addr,
+ &allocated_port, &out2in_ed_kv))
{
nat_elog_notice ("addresses exhausted");
b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS];
@@ -378,6 +386,8 @@ slow_path_ed (snat_main_t * sm,
}
out2in_ed_inserted = true;
+ key1.addr = allocated_addr;
+ key1.port = allocated_port;
}
else
{
@@ -422,9 +432,9 @@ slow_path_ed (snat_main_t * sm,
s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
- make_ed_kv (&out2in_ed_kv, &key1.addr, &key->r_addr, key->proto,
- s->out2in.fib_index, key1.port, key->r_port);
- out2in_ed_kv.value = s - tsm->sessions;
+ make_ed_kv (&key1.addr, &r_addr, proto,
+ s->out2in.fib_index, key1.port, r_port, s - tsm->sessions,
+ &out2in_ed_kv);
if (clib_bihash_add_or_overwrite_stale_16_8
(&tsm->out2in_ed, &out2in_ed_kv, nat44_o2i_ed_is_idle_session_cb,
&ctx))
@@ -435,16 +445,18 @@ slow_path_ed (snat_main_t * sm,
if (lb)
s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING;
s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
- s->ext_host_addr = key->r_addr;
- s->ext_host_port = key->r_port;
+ s->ext_host_addr = r_addr;
+ s->ext_host_port = r_port;
s->in2out = key0;
s->out2in = key1;
s->out2in.protocol = key0.protocol;
- kv->value = s - tsm->sessions;
+ clib_bihash_kv_16_8_t in2out_ed_kv;
+ make_ed_kv (&l_addr, &r_addr, proto, rx_fib_index, l_port, r_port,
+ s - tsm->sessions, &in2out_ed_kv);
ctx.now = now;
ctx.thread_index = thread_index;
- if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, kv,
+ if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, &in2out_ed_kv,
nat44_i2o_ed_is_idle_session_cb,
&ctx))
nat_elog_notice ("in2out-ed key add failed");
@@ -497,11 +509,11 @@ nat44_ed_not_translate (snat_main_t * sm, vlib_node_runtime_t * node,
clib_bihash_kv_16_8_t kv, value;
snat_session_key_t key0, key1;
- make_ed_kv (&kv, &ip->dst_address, &ip->src_address, ip->protocol,
- sm->outside_fib_index, udp->dst_port, udp->src_port);
+ make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol,
+ sm->outside_fib_index, udp->dst_port, udp->src_port, ~0ULL,
+ &kv);
- /* NAT packet aimed at external address if */
- /* has active sessions */
+ /* NAT packet aimed at external address if has active sessions */
if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
{
key0.addr = ip->dst_address;
@@ -527,7 +539,6 @@ 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)
{
- nat_ed_ses_key_t key;
clib_bihash_kv_16_8_t kv, value;
snat_session_t *s = 0;
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
@@ -537,23 +548,19 @@ nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip,
if (ip->protocol == IP_PROTOCOL_ICMP)
{
- key.as_u64[0] = key.as_u64[1] = 0;
- if (get_icmp_i2o_ed_key (b, ip, &key))
+ if (get_icmp_i2o_ed_key (b, ip, 0, ~0ULL, 0, 0, 0, &kv))
return 0;
- key.fib_index = 0;
- kv.key[0] = key.as_u64[0];
- kv.key[1] = key.as_u64[1];
}
else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
{
- make_ed_kv (&kv, &ip->src_address, &ip->dst_address, ip->protocol, 0,
+ make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol, 0,
vnet_buffer (b)->ip.reass.l4_src_port,
- vnet_buffer (b)->ip.reass.l4_dst_port);
+ vnet_buffer (b)->ip.reass.l4_dst_port, ~0ULL, &kv);
}
else
{
- make_ed_kv (&kv, &ip->src_address, &ip->dst_address, ip->protocol, 0, 0,
- 0);
+ make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol, 0, 0,
+ 0, ~0ULL, &kv);
}
if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
@@ -584,7 +591,7 @@ nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip,
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,
+ u16 src_port, u16 dst_port,
u32 thread_index, u32 rx_sw_if_index,
u32 tx_sw_if_index)
{
@@ -596,8 +603,8 @@ nat44_ed_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip,
u32 tx_fib_index = ip4_fib_table_get_index_for_sw_if_index (tx_sw_if_index);
/* src NAT check */
- make_ed_kv (&kv, &ip->src_address, &ip->dst_address, proto, tx_fib_index,
- src_port, dst_port);
+ make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol,
+ tx_fib_index, src_port, dst_port, ~0ULL, &kv);
if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
{
s = pool_elt_at_index (tsm->sessions, value.value);
@@ -612,8 +619,8 @@ nat44_ed_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip,
}
/* dst NAT check */
- make_ed_kv (&kv, &ip->dst_address, &ip->src_address, proto, rx_fib_index,
- dst_port, src_port);
+ make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol,
+ rx_fib_index, dst_port, src_port, ~0ULL, &kv);
if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
{
s = pool_elt_at_index (tsm->sessions, value.value);
@@ -643,29 +650,26 @@ icmp_match_in2out_ed (snat_main_t * sm, vlib_node_runtime_t * node,
{
u32 sw_if_index;
u32 rx_fib_index;
- nat_ed_ses_key_t key;
snat_session_t *s = 0;
u8 dont_translate = 0;
clib_bihash_kv_16_8_t kv, value;
u32 next = ~0;
int err;
+ u16 l_port = 0, r_port = 0; // initialize to workaround gcc warning
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
- key.as_u64[0] = key.as_u64[1] = 0;
- err = get_icmp_i2o_ed_key (b, ip, &key);
+ err =
+ get_icmp_i2o_ed_key (b, ip, rx_fib_index, ~0ULL, p_proto, &l_port,
+ &r_port, &kv);
if (err != 0)
{
b->error = node->errors[err];
next = NAT_NEXT_DROP;
goto out;
}
- key.fib_index = rx_fib_index;
-
- kv.key[0] = key.as_u64[0];
- kv.key[1] = key.as_u64[1];
if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
{
@@ -673,7 +677,7 @@ icmp_match_in2out_ed (snat_main_t * sm, vlib_node_runtime_t * node,
{
if (PREDICT_FALSE
(nat44_ed_not_translate_output_feature
- (sm, ip, key.proto, key.l_port, key.r_port, thread_index,
+ (sm, ip, l_port, r_port, thread_index,
sw_if_index, vnet_buffer (b)->sw_if_index[VLIB_TX])))
{
dont_translate = 1;
@@ -701,8 +705,10 @@ icmp_match_in2out_ed (snat_main_t * sm, vlib_node_runtime_t * node,
goto out;
}
- next = slow_path_ed (sm, b, rx_fib_index, &kv, &s, node, next,
- thread_index, vlib_time_now (sm->vlib_main));
+ next =
+ slow_path_ed (sm, b, ip->src_address, ip->dst_address, l_port, r_port,
+ ip->protocol, rx_fib_index, &s, node, next,
+ thread_index, vlib_time_now (sm->vlib_main));
if (PREDICT_FALSE (next == NAT_NEXT_DROP))
goto out;
@@ -730,8 +736,6 @@ icmp_match_in2out_ed (snat_main_t * sm, vlib_node_runtime_t * node,
s = pool_elt_at_index (tsm->sessions, value.value);
}
-
- *p_proto = ip_proto_to_snat_proto (key.proto);
out:
if (s)
*p_value = s->out2in;
@@ -798,8 +802,8 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm,
}
old_addr = ip->src_address.as_u32;
- make_ed_kv (&s_kv, &ip->src_address, &ip->dst_address, ip->protocol,
- rx_fib_index, 0, 0);
+ make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol,
+ rx_fib_index, 0, 0, ~0ULL, &s_kv);
if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &s_kv, &s_value))
{
@@ -834,8 +838,8 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm,
{
new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
- make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address, ip->protocol,
- outside_fib_index, 0, 0);
+ make_ed_kv (&s->out2in.addr, &ip->dst_address, ip->protocol,
+ outside_fib_index, 0, 0, ~0ULL, &s_kv);
if (clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
goto create_ses;
@@ -846,8 +850,9 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm,
for (i = 0; i < vec_len (sm->addresses); i++)
{
- make_ed_kv (&s_kv, &sm->addresses[i].addr, &ip->dst_address,
- ip->protocol, outside_fib_index, 0, 0);
+ make_ed_kv (&sm->addresses[i].addr, &ip->dst_address,
+ ip->protocol, outside_fib_index, 0, 0, ~0ULL,
+ &s_kv);
if (clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
{
new_addr = ip->src_address.as_u32 =
@@ -879,15 +884,13 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm,
s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
/* Add to lookup tables */
- make_ed_kv (&s_kv, &s->in2out.addr, &ip->dst_address, ip->protocol,
- rx_fib_index, 0, 0);
- s_kv.value = s - tsm->sessions;
+ make_ed_kv (&s->in2out.addr, &ip->dst_address, ip->protocol,
+ rx_fib_index, 0, 0, s - tsm->sessions, &s_kv);
if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
nat_elog_notice ("in2out key add failed");
- make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address, ip->protocol,
- outside_fib_index, 0, 0);
- s_kv.value = s - tsm->sessions;
+ make_ed_kv (&s->out2in.addr, &ip->dst_address, ip->protocol,
+ outside_fib_index, 0, 0, s - tsm->sessions, &s_kv);
if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1))
nat_elog_notice ("out2in key add failed");
}
@@ -1016,10 +1019,10 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t * vm,
goto trace0;
}
- make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
+ make_ed_kv (&ip0->src_address, &ip0->dst_address,
ip0->protocol, rx_fib_index0,
vnet_buffer (b0)->ip.reass.l4_src_port,
- vnet_buffer (b0)->ip.reass.l4_dst_port);
+ vnet_buffer (b0)->ip.reass.l4_dst_port, ~0ULL, &kv0);
// lookup for session
if (clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
@@ -1302,10 +1305,10 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
}
// move down
- make_ed_kv (&kv0, &ip0->src_address, &ip0->dst_address,
+ make_ed_kv (&ip0->src_address, &ip0->dst_address,
ip0->protocol, rx_fib_index0,
vnet_buffer (b0)->ip.reass.l4_src_port,
- vnet_buffer (b0)->ip.reass.l4_dst_port);
+ vnet_buffer (b0)->ip.reass.l4_dst_port, ~0ULL, &kv0);
if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv0, &value0))
{
@@ -1325,10 +1328,9 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
{
if (PREDICT_FALSE
(nat44_ed_not_translate_output_feature
- (sm, ip0, ip0->protocol,
- vnet_buffer (b0)->ip.reass.l4_src_port,
- vnet_buffer (b0)->ip.reass.l4_dst_port,
- thread_index, sw_if_index0,
+ (sm, ip0, vnet_buffer (b0)->ip.reass.l4_src_port,
+ vnet_buffer (b0)->ip.reass.l4_dst_port, thread_index,
+ sw_if_index0,
vnet_buffer (b0)->sw_if_index[VLIB_TX])))
goto trace0;
@@ -1352,8 +1354,12 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
goto trace0;
}
- next0 = slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node,
- next0, thread_index, now);
+ next0 =
+ slow_path_ed (sm, b0, ip0->src_address, ip0->dst_address,
+ vnet_buffer (b0)->ip.reass.l4_src_port,
+ vnet_buffer (b0)->ip.reass.l4_dst_port,
+ ip0->protocol, rx_fib_index0, &s0, node, next0,
+ thread_index, now);
if (PREDICT_FALSE (next0 == NAT_NEXT_DROP))
goto trace0;
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index b0c30d636af..ba682f9325b 100755
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -199,7 +199,10 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
{
snat_session_key_t key;
clib_bihash_kv_8_8_t kv;
- nat_ed_ses_key_t ed_key;
+ u8 proto;
+ u16 r_port, l_port;
+ ip4_address_t *l_addr, *r_addr;
+ u32 fib_index = 0;
clib_bihash_kv_16_8_t ed_kv;
snat_main_per_thread_data_t *tsm =
vec_elt_at_index (sm->per_thread_data, thread_index);
@@ -208,21 +211,20 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
{
if (snat_is_unk_proto_session (s))
{
- ed_key.proto = s->in2out.port;
- ed_key.r_port = 0;
- ed_key.l_port = 0;
+ make_ed_kv (&s->in2out.addr, &s->ext_host_addr, s->in2out.port, 0,
+ 0, 0, ~0ULL, &ed_kv);
}
else
{
- ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
- ed_key.l_port = s->in2out.port;
- ed_key.r_port = s->ext_host_port;
+ proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ l_port = s->in2out.port;
+ r_port = s->ext_host_port;
+ l_addr = &s->in2out.addr;
+ r_addr = &s->ext_host_addr;
+ proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+ &ed_kv);
}
- ed_key.l_addr = s->in2out.addr;
- ed_key.r_addr = s->ext_host_addr;
- ed_key.fib_index = 0;
- ed_kv.key[0] = ed_key.as_u64[0];
- ed_kv.key[1] = ed_key.as_u64[1];
if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
nat_elog_warn ("in2out_ed key del failed");
return;
@@ -234,36 +236,36 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index,
if (is_affinity_sessions (s))
nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
s->in2out.protocol, s->out2in.port);
- ed_key.l_addr = s->out2in.addr;
- ed_key.r_addr = s->ext_host_addr;
- ed_key.fib_index = s->out2in.fib_index;
+ l_addr = &s->out2in.addr;
+ r_addr = &s->ext_host_addr;
+ fib_index = s->out2in.fib_index;
if (snat_is_unk_proto_session (s))
{
- ed_key.proto = s->in2out.port;
- ed_key.r_port = 0;
- ed_key.l_port = 0;
+ proto = s->in2out.port;
+ r_port = 0;
+ l_port = 0;
}
else
{
- ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
- ed_key.l_port = s->out2in.port;
- ed_key.r_port = s->ext_host_port;
+ proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ l_port = s->out2in.port;
+ r_port = s->ext_host_port;
}
- ed_kv.key[0] = ed_key.as_u64[0];
- ed_kv.key[1] = ed_key.as_u64[1];
+ make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+ &ed_kv);
if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))
nat_elog_warn ("out2in_ed key del failed");
- ed_key.l_addr = s->in2out.addr;
- ed_key.fib_index = s->in2out.fib_index;
+ l_addr = &s->in2out.addr;
+ fib_index = s->in2out.fib_index;
if (!snat_is_unk_proto_session (s))
- ed_key.l_port = s->in2out.port;
+ l_port = s->in2out.port;
if (is_twice_nat_session (s))
{
- ed_key.r_addr = s->ext_host_nat_addr;
- ed_key.r_port = s->ext_host_nat_port;
+ r_addr = &s->ext_host_nat_addr;
+ r_port = s->ext_host_nat_port;
}
- ed_kv.key[0] = ed_key.as_u64[0];
- ed_kv.key[1] = ed_key.as_u64[1];
+ make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+ &ed_kv);
if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
nat_elog_warn ("in2out_ed key del failed");
@@ -332,7 +334,10 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
u32 thread_index, u8 is_ha)
{
snat_session_key_t key;
- nat_ed_ses_key_t ed_key;
+ u8 proto;
+ u16 r_port, l_port;
+ ip4_address_t *l_addr, *r_addr;
+ u32 fib_index;
clib_bihash_kv_16_8_t ed_kv;
snat_main_per_thread_data_t *tsm =
vec_elt_at_index (sm->per_thread_data, thread_index);
@@ -341,22 +346,22 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
{
if (snat_is_unk_proto_session (s))
{
- ed_key.proto = s->in2out.port;
- ed_key.r_port = 0;
- ed_key.l_port = 0;
+ proto = s->in2out.port;
+ r_port = 0;
+ l_port = 0;
}
else
{
- ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
- ed_key.l_port = s->in2out.port;
- ed_key.r_port = s->ext_host_port;
+ proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ l_port = s->in2out.port;
+ r_port = s->ext_host_port;
}
- ed_key.l_addr = s->in2out.addr;
- ed_key.r_addr = s->ext_host_addr;
- ed_key.fib_index = 0;
- ed_kv.key[0] = ed_key.as_u64[0];
- ed_kv.key[1] = ed_key.as_u64[1];
+ l_addr = &s->in2out.addr;
+ r_addr = &s->ext_host_addr;
+ fib_index = 0;
+ make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+ &ed_kv);
if (PREDICT_FALSE
(clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)))
@@ -368,41 +373,40 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s,
if (is_affinity_sessions (s))
nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
s->in2out.protocol, s->out2in.port);
- ed_key.l_addr = s->out2in.addr;
- ed_key.r_addr = s->ext_host_addr;
- ed_key.fib_index = s->out2in.fib_index;
+ l_addr = &s->out2in.addr;
+ r_addr = &s->ext_host_addr;
+ fib_index = s->out2in.fib_index;
if (snat_is_unk_proto_session (s))
{
- ed_key.proto = s->in2out.port;
- ed_key.r_port = 0;
- ed_key.l_port = 0;
+ proto = s->in2out.port;
+ r_port = 0;
+ l_port = 0;
}
else
{
- ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
- ed_key.l_port = s->out2in.port;
- ed_key.r_port = s->ext_host_port;
+ proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ l_port = s->out2in.port;
+ r_port = s->ext_host_port;
}
- ed_kv.key[0] = ed_key.as_u64[0];
- ed_kv.key[1] = ed_key.as_u64[1];
+ make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+ &ed_kv);
if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0)))
nat_elog_warn ("out2in_ed key del failed");
- ed_key.l_addr = s->in2out.addr;
- ed_key.fib_index = s->in2out.fib_index;
+ l_addr = &s->in2out.addr;
+ fib_index = s->in2out.fib_index;
if (!snat_is_unk_proto_session (s))
- ed_key.l_port = s->in2out.port;
+ l_port = s->in2out.port;
if (is_twice_nat_session (s))
{
- ed_key.r_addr = s->ext_host_nat_addr;
- ed_key.r_port = s->ext_host_nat_port;
+ r_addr = &s->ext_host_nat_addr;
+ r_port = s->ext_host_nat_port;
}
-
- ed_kv.key[0] = ed_key.as_u64[0];
- ed_kv.key[1] = ed_key.as_u64[1];
+ make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+ &ed_kv);
if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)))
nat_elog_warn ("in2out_ed key del failed");
@@ -2487,6 +2491,46 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
snat_session_key_t * k,
u16 port_per_thread, u32 snat_thread_index);
+void
+test_ed_make_split ()
+{
+ ip4_address_t l_addr;
+ l_addr.as_u8[0] = 1;
+ l_addr.as_u8[1] = 1;
+ l_addr.as_u8[2] = 1;
+ l_addr.as_u8[3] = 1;
+ ip4_address_t r_addr;
+ r_addr.as_u8[0] = 2;
+ r_addr.as_u8[1] = 2;
+ r_addr.as_u8[2] = 2;
+ r_addr.as_u8[3] = 2;
+ u16 l_port = 40001;
+ u16 r_port = 40301;
+ u8 proto = 9;
+ u32 fib_index = 9000001;
+ u64 value = ~0ULL;
+ clib_bihash_kv_16_8_t kv;
+ make_ed_kv (&l_addr, &r_addr, proto, fib_index, l_port, r_port, value, &kv);
+ ip4_address_t l_addr2;
+ ip4_address_t r_addr2;
+ clib_memset (&l_addr2, 0, sizeof (l_addr2));
+ clib_memset (&r_addr2, 0, sizeof (r_addr2));
+ u16 l_port2 = 0;
+ u16 r_port2 = 0;
+ u8 proto2 = 0;
+ u32 fib_index2 = 0;
+ split_ed_kv (&kv, &l_addr2, &r_addr2, &proto2, &fib_index2, &l_port2,
+ &r_port2);
+ u64 value2 = kv.value;
+ ASSERT (l_addr.as_u32 == l_addr2.as_u32);
+ ASSERT (r_addr.as_u32 == r_addr2.as_u32);
+ ASSERT (l_port == l_port2);
+ ASSERT (r_port == r_port2);
+ ASSERT (proto == proto2);
+ ASSERT (fib_index == fib_index2);
+ ASSERT (value == value2);
+}
+
static clib_error_t *
snat_init (vlib_main_t * vm)
{
@@ -2656,6 +2700,7 @@ snat_init (vlib_main_t * vm)
FIB_SOURCE_PRIORITY_LOW,
FIB_SOURCE_BH_SIMPLE);
+ test_ed_make_split ();
return error;
}
@@ -3159,16 +3204,18 @@ u8 *
format_ed_session_kvp (u8 * s, va_list * args)
{
clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
- nat_ed_ses_key_t k;
- k.as_u64[0] = v->key[0];
- k.as_u64[1] = v->key[1];
+ u8 proto;
+ u16 r_port, l_port;
+ ip4_address_t l_addr, r_addr;
+ u32 fib_index;
+ split_ed_kv (v, &l_addr, &r_addr, &proto, &fib_index, &l_port, &r_port);
s =
format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu",
- format_ip4_address, &k.l_addr, clib_net_to_host_u16 (k.l_port),
- format_ip4_address, &k.r_addr, clib_net_to_host_u16 (k.r_port),
- format_ip_protocol, k.proto, k.fib_index, v->value);
+ format_ip4_address, &l_addr, clib_net_to_host_u16 (l_port),
+ format_ip4_address, &r_addr, clib_net_to_host_u16 (r_port),
+ format_ip_protocol, proto, fib_index, v->value);
return s;
}
@@ -3340,8 +3387,9 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t * ip, u32 rx_fib_index,
break;
}
- make_ed_kv (&kv16, &ip->src_address, &ip->dst_address,
- ip->protocol, fib_index, udp->src_port, udp->dst_port);
+ make_ed_kv (&ip->src_address, &ip->dst_address,
+ ip->protocol, fib_index, udp->src_port, udp->dst_port,
+ ~0ULL, &kv16);
/* *INDENT-OFF* */
vec_foreach (tsm, sm->per_thread_data)
@@ -3410,8 +3458,9 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
{
udp = ip4_next_header (ip);
- make_ed_kv (&kv16, &ip->dst_address, &ip->src_address,
- ip->protocol, rx_fib_index, udp->dst_port, udp->src_port);
+ make_ed_kv (&ip->dst_address, &ip->src_address,
+ ip->protocol, rx_fib_index, udp->dst_port, udp->src_port,
+ ~0ULL, &kv16);
/* *INDENT-OFF* */
vec_foreach (tsm, sm->per_thread_data)
@@ -3431,15 +3480,8 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
}
else if (proto == SNAT_PROTOCOL_ICMP)
{
- nat_ed_ses_key_t key;
-
- if (!get_icmp_o2i_ed_key (b, ip, &key))
+ if (!get_icmp_o2i_ed_key (b, ip, rx_fib_index, ~0ULL, 0, 0, 0, &kv16))
{
-
- key.fib_index = rx_fib_index;
- kv16.key[0] = key.as_u64[0];
- kv16.key[1] = key.as_u64[1];
-
/* *INDENT-OFF* */
vec_foreach (tsm, sm->per_thread_data)
{
@@ -3796,14 +3838,14 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port,
key.fib_index = fib_index;
s->in2out = key;
- make_ed_kv (&kv, in_addr, &s->ext_host_nat_addr,
+ make_ed_kv (in_addr, &s->ext_host_nat_addr,
snat_proto_to_ip_proto (proto), fib_index, in_port,
- s->ext_host_nat_port);
+ s->ext_host_nat_port, s - tsm->sessions, &kv);
if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1))
nat_elog_warn ("in2out key add failed");
- make_ed_kv (&kv, out_addr, eh_addr, snat_proto_to_ip_proto (proto),
- s->out2in.fib_index, out_port, eh_port);
+ make_ed_kv (out_addr, eh_addr, snat_proto_to_ip_proto (proto),
+ s->out2in.fib_index, out_port, eh_port, s - tsm->sessions, &kv);
if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 1))
nat_elog_warn ("out2in key add failed");
}
@@ -3814,7 +3856,6 @@ nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port,
u32 fib_index, u32 ti)
{
snat_main_t *sm = &snat_main;
- nat_ed_ses_key_t key;
clib_bihash_kv_16_8_t kv, value;
u32 thread_index;
snat_session_t *s;
@@ -3829,14 +3870,8 @@ nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port,
thread_index = sm->num_workers;
tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
- key.l_addr.as_u32 = out_addr->as_u32;
- key.l_port = out_port;
- key.r_addr.as_u32 = eh_addr->as_u32;
- key.r_port = eh_port;
- key.proto = proto;
- key.fib_index = fib_index;
- kv.key[0] = key.as_u64[0];
- kv.key[1] = key.as_u64[1];
+ make_ed_kv (out_addr, eh_addr, proto, fib_index, out_port, eh_port, ~0ULL,
+ &kv);
if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
return;
@@ -3852,21 +3887,14 @@ nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port,
u32 thread_index)
{
snat_main_t *sm = &snat_main;
- nat_ed_ses_key_t key;
clib_bihash_kv_16_8_t kv, value;
snat_session_t *s;
snat_main_per_thread_data_t *tsm;
tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
- key.l_addr.as_u32 = out_addr->as_u32;
- key.l_port = out_port;
- key.r_addr.as_u32 = eh_addr->as_u32;
- key.r_port = eh_port;
- key.proto = proto;
- key.fib_index = fib_index;
- kv.key[0] = key.as_u64[0];
- kv.key[1] = key.as_u64[1];
+ make_ed_kv (out_addr, eh_addr, proto, fib_index, out_port, eh_port, ~0ULL,
+ &kv);
if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
return;
@@ -4411,7 +4439,6 @@ nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
{
ip4_header_t ip;
clib_bihash_16_8_t *t;
- nat_ed_ses_key_t key;
clib_bihash_kv_16_8_t kv, value;
u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
snat_session_t *s;
@@ -4429,16 +4456,12 @@ nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
t = is_in ? &tsm->in2out_ed : &tsm->out2in_ed;
- key.l_addr.as_u32 = addr->as_u32;
- key.r_addr.as_u32 = eh_addr->as_u32;
- key.l_port = clib_host_to_net_u16 (port);
- key.r_port = clib_host_to_net_u16 (eh_port);
- key.proto = proto;
- key.fib_index = fib_index;
- kv.key[0] = key.as_u64[0];
- kv.key[1] = key.as_u64[1];
+ make_ed_kv (addr, eh_addr, proto, fib_index, clib_host_to_net_u16 (port),
+ clib_host_to_net_u16 (eh_port), ~0ULL, &kv);
if (clib_bihash_search_16_8 (t, &kv, &value))
- return VNET_API_ERROR_NO_SUCH_ENTRY;
+ {
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+ }
if (pool_is_free_index (tsm->sessions, value.value))
return VNET_API_ERROR_UNSPECIFIED;
diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h
index 98c18c06635..c4f1be23b56 100644
--- a/src/plugins/nat/nat.h
+++ b/src/plugins/nat/nat.h
@@ -88,23 +88,6 @@ typedef struct
};
} snat_session_key_t;
-/* endpoint-dependent session key (6-tuple) */
-typedef struct
-{
- union
- {
- struct
- {
- ip4_address_t l_addr;
- ip4_address_t r_addr;
- u32 proto:8, fib_index:24;
- u16 l_port;
- u16 r_port;
- };
- u64 as_u64[2];
- };
-} nat_ed_ses_key_t;
-
/* deterministic session outside key */
typedef struct
{
diff --git a/src/plugins/nat/nat44_classify.c b/src/plugins/nat/nat44_classify.c
index 2afc479aa5b..a57f24177ab 100644
--- a/src/plugins/nat/nat44_classify.c
+++ b/src/plugins/nat/nat44_classify.c
@@ -258,11 +258,11 @@ nat44_ed_classify_node_fn_inline (vlib_main_t * vm,
rx_fib_index0 =
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
sw_if_index0);
- make_ed_kv (&ed_kv0, &ip0->src_address,
- &ip0->dst_address, ip0->protocol,
- rx_fib_index0,
+ make_ed_kv (&ip0->src_address, &ip0->dst_address,
+ ip0->protocol, rx_fib_index0,
vnet_buffer (b0)->ip.reass.l4_src_port,
- vnet_buffer (b0)->ip.reass.l4_dst_port);
+ vnet_buffer (b0)->ip.reass.l4_dst_port, ~0ULL,
+ &ed_kv0);
/* process whole packet */
if (!clib_bihash_search_16_8
(&tsm->in2out_ed, &ed_kv0, &ed_value0))
diff --git a/src/plugins/nat/nat44_hairpinning.c b/src/plugins/nat/nat44_hairpinning.c
index c0b84127741..bdf9e3ce813 100644
--- a/src/plugins/nat/nat44_hairpinning.c
+++ b/src/plugins/nat/nat44_hairpinning.c
@@ -126,9 +126,9 @@ snat_hairpinning (snat_main_t * sm,
if (is_ed)
{
clib_bihash_kv_16_8_t ed_kv, ed_value;
- make_ed_kv (&ed_kv, &ip0->dst_address, &ip0->src_address,
+ make_ed_kv (&ip0->dst_address, &ip0->src_address,
ip0->protocol, sm->outside_fib_index, udp0->dst_port,
- udp0->src_port);
+ udp0->src_port, ~0ULL, &ed_kv);
rv = clib_bihash_search_16_8 (&sm->per_thread_data[ti].out2in_ed,
&ed_kv, &ed_value);
si = ed_value.value;
@@ -226,11 +226,12 @@ snat_icmp_hairpinning (snat_main_t * sm,
if (is_ed)
{
clib_bihash_kv_16_8_t ed_kv, ed_value;
- make_ed_kv (&ed_kv, &ip0->dst_address, &ip0->src_address,
+ make_ed_kv (&ip0->dst_address, &ip0->src_address,
inner_ip0->protocol, sm->outside_fib_index,
- l4_header->src_port, l4_header->dst_port);
- if (clib_bihash_search_16_8 (&sm->per_thread_data[ti].out2in_ed,
- &ed_kv, &ed_value))
+ l4_header->src_port, l4_header->dst_port, ~0ULL,
+ &ed_kv);
+ if (clib_bihash_search_16_8
+ (&sm->per_thread_data[ti].out2in_ed, &ed_kv, &ed_value))
return 1;
si = ed_value.value;
}
@@ -397,8 +398,8 @@ nat44_ed_hairpinning_unknown_proto (snat_main_t * sm,
tsm = &sm->per_thread_data[ti];
old_addr = ip->dst_address.as_u32;
- make_ed_kv (&s_kv, &ip->dst_address, &ip->src_address, ip->protocol,
- sm->outside_fib_index, 0, 0);
+ make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol,
+ sm->outside_fib_index, 0, 0, ~0ULL, &s_kv);
if (clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
{
make_sm_kv (&kv, &ip->dst_address, 0, 0, 0);
diff --git a/src/plugins/nat/nat_inlines.h b/src/plugins/nat/nat_inlines.h
index daf501dcef3..a0803566ccc 100644
--- a/src/plugins/nat/nat_inlines.h
+++ b/src/plugins/nat/nat_inlines.h
@@ -473,43 +473,67 @@ nat44_session_update_lru (snat_main_t * sm, snat_session_t * s,
}
always_inline 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)
+make_ed_kv (ip4_address_t * l_addr, ip4_address_t * r_addr, u8 proto,
+ u32 fib_index, u16 l_port, u16 r_port, u64 value,
+ clib_bihash_kv_16_8_t * kv)
{
- nat_ed_ses_key_t *key = (nat_ed_ses_key_t *) kv->key;
-
- key->l_addr.as_u32 = l_addr->as_u32;
- key->r_addr.as_u32 = r_addr->as_u32;
- key->fib_index = fib_index;
- key->proto = proto;
- key->l_port = l_port;
- key->r_port = r_port;
+ kv->key[0] = (u64) r_addr->as_u32 << 32 | l_addr->as_u32;
+ kv->key[1] =
+ (u64) r_port << 48 | (u64) l_port << 32 | fib_index << 8 | proto;
+ kv->value = value;
+}
- kv->value = ~0ULL;
+always_inline void
+split_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)
+{
+ if (l_addr)
+ {
+ l_addr->as_u32 = kv->key[0] & (u32) ~ 0;
+ }
+ if (r_addr)
+ {
+ r_addr->as_u32 = kv->key[0] >> 32;
+ }
+ if (r_port)
+ {
+ *r_port = kv->key[1] >> 48;
+ }
+ if (l_port)
+ {
+ *l_port = (kv->key[1] >> 32) & (u16) ~ 0;
+ }
+ if (fib_index)
+ {
+ *fib_index = (kv->key[1] >> 8) & ((1 << 24) - 1);
+ }
+ if (proto)
+ {
+ *proto = kv->key[1] & (u8) ~ 0;
+ }
}
always_inline void
make_sm_kv (clib_bihash_kv_8_8_t * kv, ip4_address_t * addr, u8 proto,
u32 fib_index, u16 port)
{
- snat_session_key_t key;
-
- key.addr.as_u32 = addr->as_u32;
- key.port = port;
- key.protocol = proto;
- key.fib_index = fib_index;
+ kv->key = (u64) fib_index << 51 | (u64) proto << 48 | (u64) port << 32 |
+ addr->as_u32;
- kv->key = key.as_u64;
kv->value = ~0ULL;
}
static_always_inline int
-get_icmp_i2o_ed_key (vlib_buffer_t * b, ip4_header_t * ip0,
- nat_ed_ses_key_t * p_key0)
+get_icmp_i2o_ed_key (vlib_buffer_t * b, ip4_header_t * ip0, u32 rx_fib_index,
+ u64 value, u8 * snat_proto, u16 * l_port, u16 * r_port,
+ clib_bihash_kv_16_8_t * kv)
{
+ u8 proto;
+ u16 _l_port, _r_port;
+ ip4_address_t *l_addr, *r_addr;
+
icmp46_header_t *icmp0;
- nat_ed_ses_key_t key0;
icmp_echo_header_t *echo0, *inner_echo0 = 0;
ip4_header_t *inner_ip0 = 0;
void *l4_header = 0;
@@ -521,47 +545,63 @@ get_icmp_i2o_ed_key (vlib_buffer_t * b, ip4_header_t * ip0,
if (!icmp_type_is_error_message
(vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
{
- key0.proto = IP_PROTOCOL_ICMP;
- key0.l_addr = ip0->src_address;
- key0.r_addr = ip0->dst_address;
- key0.l_port = vnet_buffer (b)->ip.reass.l4_src_port; // TODO should this be src or dst?
- key0.r_port = 0;
+ proto = IP_PROTOCOL_ICMP;
+ l_addr = &ip0->src_address;
+ r_addr = &ip0->dst_address;
+ _l_port = vnet_buffer (b)->ip.reass.l4_src_port; // TODO should this be src or dst?
+ _r_port = 0;
}
else
{
inner_ip0 = (ip4_header_t *) (echo0 + 1);
l4_header = ip4_next_header (inner_ip0);
- key0.proto = inner_ip0->protocol;
- key0.r_addr = inner_ip0->src_address;
- key0.l_addr = inner_ip0->dst_address;
+ proto = inner_ip0->protocol;
+ r_addr = &inner_ip0->src_address;
+ l_addr = &inner_ip0->dst_address;
switch (ip_proto_to_snat_proto (inner_ip0->protocol))
{
case SNAT_PROTOCOL_ICMP:
inner_icmp0 = (icmp46_header_t *) l4_header;
inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
- key0.r_port = 0;
- key0.l_port = inner_echo0->identifier;
+ _r_port = 0;
+ _l_port = inner_echo0->identifier;
break;
case SNAT_PROTOCOL_UDP:
case SNAT_PROTOCOL_TCP:
- key0.l_port = ((tcp_udp_header_t *) l4_header)->dst_port;
- key0.r_port = ((tcp_udp_header_t *) l4_header)->src_port;
+ _l_port = ((tcp_udp_header_t *) l4_header)->dst_port;
+ _r_port = ((tcp_udp_header_t *) l4_header)->src_port;
break;
default:
return NAT_IN2OUT_ED_ERROR_UNSUPPORTED_PROTOCOL;
}
}
- *p_key0 = key0;
+ make_ed_kv (l_addr, r_addr, proto, rx_fib_index, _l_port, _r_port, value,
+ kv);
+ if (snat_proto)
+ {
+ *snat_proto = ip_proto_to_snat_proto (proto);
+ }
+ if (l_port)
+ {
+ *l_port = _l_port;
+ }
+ if (r_port)
+ {
+ *r_port = _r_port;
+ }
return 0;
}
static_always_inline int
-get_icmp_o2i_ed_key (vlib_buffer_t * b, ip4_header_t * ip0,
- nat_ed_ses_key_t * p_key0)
+get_icmp_o2i_ed_key (vlib_buffer_t * b, ip4_header_t * ip0, u32 rx_fib_index,
+ u64 value, u8 * snat_proto, u16 * l_port, u16 * r_port,
+ clib_bihash_kv_16_8_t * kv)
{
icmp46_header_t *icmp0;
- nat_ed_ses_key_t key0;
+ u8 proto;
+ ip4_address_t *l_addr, *r_addr;
+ u16 _l_port, _r_port;
icmp_echo_header_t *echo0, *inner_echo0 = 0;
ip4_header_t *inner_ip0;
void *l4_header = 0;
@@ -573,37 +613,50 @@ get_icmp_o2i_ed_key (vlib_buffer_t * b, ip4_header_t * ip0,
if (!icmp_type_is_error_message
(vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
{
- key0.proto = IP_PROTOCOL_ICMP;
- key0.l_addr = ip0->dst_address;
- key0.r_addr = ip0->src_address;
- key0.l_port = vnet_buffer (b)->ip.reass.l4_src_port; // TODO should this be src or dst?
- key0.r_port = 0;
+ proto = IP_PROTOCOL_ICMP;
+ l_addr = &ip0->dst_address;
+ r_addr = &ip0->src_address;
+ _l_port = vnet_buffer (b)->ip.reass.l4_src_port; // TODO should this be src or dst?
+ _r_port = 0;
}
else
{
inner_ip0 = (ip4_header_t *) (echo0 + 1);
l4_header = ip4_next_header (inner_ip0);
- key0.proto = inner_ip0->protocol;
- key0.l_addr = inner_ip0->src_address;
- key0.r_addr = inner_ip0->dst_address;
+ proto = inner_ip0->protocol;
+ l_addr = &inner_ip0->src_address;
+ r_addr = &inner_ip0->dst_address;
switch (ip_proto_to_snat_proto (inner_ip0->protocol))
{
case SNAT_PROTOCOL_ICMP:
inner_icmp0 = (icmp46_header_t *) l4_header;
inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
- key0.l_port = inner_echo0->identifier;
- key0.r_port = 0;
+ _l_port = inner_echo0->identifier;
+ _r_port = 0;
break;
case SNAT_PROTOCOL_UDP:
case SNAT_PROTOCOL_TCP:
- key0.l_port = ((tcp_udp_header_t *) l4_header)->src_port;
- key0.r_port = ((tcp_udp_header_t *) l4_header)->dst_port;
+ _l_port = ((tcp_udp_header_t *) l4_header)->src_port;
+ _r_port = ((tcp_udp_header_t *) l4_header)->dst_port;
break;
default:
return -1;
}
}
- *p_key0 = key0;
+ make_ed_kv (l_addr, r_addr, proto, rx_fib_index, _l_port, _r_port, value,
+ kv);
+ if (snat_proto)
+ {
+ *snat_proto = ip_proto_to_snat_proto (proto);
+ }
+ if (l_port)
+ {
+ *l_port = _l_port;
+ }
+ if (r_port)
+ {
+ *r_port = _r_port;
+ }
return 0;
}
diff --git a/src/plugins/nat/out2in_ed.c b/src/plugins/nat/out2in_ed.c
index 560dc0d89d4..1382125dcf7 100644
--- a/src/plugins/nat/out2in_ed.c
+++ b/src/plugins/nat/out2in_ed.c
@@ -94,7 +94,10 @@ nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg)
nat44_is_idle_session_ctx_t *ctx = arg;
snat_session_t *s;
u64 sess_timeout_time;
- nat_ed_ses_key_t ed_key;
+ u8 proto;
+ u16 r_port, l_port;
+ ip4_address_t *l_addr, *r_addr;
+ u32 fib_index;
clib_bihash_kv_16_8_t ed_kv;
int i;
snat_address_t *a;
@@ -106,28 +109,28 @@ nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg)
sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s);
if (ctx->now >= sess_timeout_time)
{
- ed_key.l_addr = s->in2out.addr;
- ed_key.r_addr = s->ext_host_addr;
- ed_key.fib_index = s->in2out.fib_index;
+ l_addr = &s->in2out.addr;
+ r_addr = &s->ext_host_addr;
+ fib_index = s->in2out.fib_index;
if (snat_is_unk_proto_session (s))
{
- ed_key.proto = s->in2out.port;
- ed_key.r_port = 0;
- ed_key.l_port = 0;
+ proto = s->in2out.port;
+ r_port = 0;
+ l_port = 0;
}
else
{
- ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol);
- ed_key.l_port = s->in2out.port;
- ed_key.r_port = s->ext_host_port;
+ proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ l_port = s->in2out.port;
+ r_port = s->ext_host_port;
}
if (is_twice_nat_session (s))
{
- ed_key.r_addr = s->ext_host_nat_addr;
- ed_key.r_port = s->ext_host_nat_port;
+ r_addr = &s->ext_host_nat_addr;
+ r_port = s->ext_host_nat_port;
}
- ed_kv.key[0] = ed_key.as_u64[0];
- ed_kv.key[1] = ed_key.as_u64[1];
+ make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL,
+ &ed_kv);
if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
nat_elog_warn ("in2out_ed key del failed");
@@ -233,9 +236,9 @@ create_session_for_static_mapping_ed (snat_main_t * sm,
s->in2out.protocol = s->out2in.protocol;
/* Add to lookup tables */
- make_ed_kv (&kv, &e_key.addr, &s->ext_host_addr, ip->protocol,
- e_key.fib_index, e_key.port, s->ext_host_port);
- kv.value = s - tsm->sessions;
+ make_ed_kv (&e_key.addr, &s->ext_host_addr, ip->protocol,
+ e_key.fib_index, e_key.port, s->ext_host_port,
+ s - tsm->sessions, &kv);
ctx.now = now;
ctx.thread_index = thread_index;
if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->out2in_ed, &kv,
@@ -261,15 +264,16 @@ create_session_for_static_mapping_ed (snat_main_t * sm,
s->ext_host_nat_addr.as_u32 = eh_key.addr.as_u32;
s->ext_host_nat_port = eh_key.port;
s->flags |= SNAT_SESSION_FLAG_TWICE_NAT;
- make_ed_kv (&kv, &l_key.addr, &s->ext_host_nat_addr, ip->protocol,
- l_key.fib_index, l_key.port, s->ext_host_nat_port);
+ make_ed_kv (&l_key.addr, &s->ext_host_nat_addr, ip->protocol,
+ l_key.fib_index, l_key.port, s->ext_host_nat_port,
+ s - tsm->sessions, &kv);
}
else
{
- make_ed_kv (&kv, &l_key.addr, &s->ext_host_addr, ip->protocol,
- l_key.fib_index, l_key.port, s->ext_host_port);
+ make_ed_kv (&l_key.addr, &s->ext_host_addr, ip->protocol,
+ l_key.fib_index, l_key.port, s->ext_host_port,
+ s - tsm->sessions, &kv);
}
- kv.value = s - tsm->sessions;
if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, &kv,
nat44_i2o_ed_is_idle_session_cb,
&ctx))
@@ -299,14 +303,14 @@ create_session_for_static_mapping_ed (snat_main_t * sm,
}
static int
-next_src_nat (snat_main_t * sm, ip4_header_t * ip, u8 proto, u16 src_port,
+next_src_nat (snat_main_t * sm, ip4_header_t * ip, u16 src_port,
u16 dst_port, u32 thread_index, u32 rx_fib_index)
{
clib_bihash_kv_16_8_t kv, value;
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
- make_ed_kv (&kv, &ip->src_address, &ip->dst_address, proto,
- rx_fib_index, src_port, dst_port);
+ make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol,
+ rx_fib_index, src_port, dst_port, ~0ULL, &kv);
if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
return 1;
@@ -317,37 +321,35 @@ static void
create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip,
u32 rx_fib_index, u32 thread_index)
{
- nat_ed_ses_key_t key;
clib_bihash_kv_16_8_t kv, value;
udp_header_t *udp;
snat_session_t *s = 0;
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
f64 now = vlib_time_now (sm->vlib_main);
+ u16 l_port, r_port;
if (ip->protocol == IP_PROTOCOL_ICMP)
{
- if (get_icmp_o2i_ed_key (b, ip, &key))
+ if (get_icmp_o2i_ed_key
+ (b, ip, rx_fib_index, ~0ULL, 0, &l_port, &r_port, &kv))
return;
}
- else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
- {
- udp = ip4_next_header (ip);
- key.r_addr = ip->src_address;
- key.l_addr = ip->dst_address;
- key.proto = ip->protocol;
- key.l_port = udp->dst_port;
- key.r_port = udp->src_port;
- }
else
{
- key.r_addr = ip->src_address;
- key.l_addr = ip->dst_address;
- key.proto = ip->protocol;
- key.l_port = key.r_port = 0;
+ if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
+ {
+ udp = ip4_next_header (ip);
+ l_port = udp->dst_port;
+ r_port = udp->src_port;
+ }
+ else
+ {
+ l_port = 0;
+ r_port = 0;
+ }
+ make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol,
+ rx_fib_index, l_port, r_port, ~0ULL, &kv);
}
- key.fib_index = 0;
- kv.key[0] = key.as_u64[0];
- kv.key[1] = key.as_u64[1];
if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value))
{
@@ -367,13 +369,13 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip,
return;
}
- proto = ip_proto_to_snat_proto (key.proto);
+ proto = ip_proto_to_snat_proto (ip->protocol);
- s->ext_host_addr = key.r_addr;
- s->ext_host_port = key.r_port;
+ s->ext_host_addr = ip->src_address;
+ s->ext_host_port = r_port;
s->flags |= SNAT_SESSION_FLAG_FWD_BYPASS;
- s->out2in.addr = key.l_addr;
- s->out2in.port = key.l_port;
+ s->out2in.addr = ip->dst_address;
+ s->out2in.port = l_port;
s->out2in.protocol = proto;
if (proto == ~0)
{
@@ -423,32 +425,30 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
u8 * p_dont_translate, void *d, void *e)
{
u32 next = ~0, sw_if_index, rx_fib_index;
- nat_ed_ses_key_t key;
clib_bihash_kv_16_8_t kv, value;
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
snat_session_t *s = 0;
u8 dont_translate = 0, is_addr_only, identity_nat;
snat_session_key_t e_key, l_key;
+ u16 l_port, r_port;
sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
- if (get_icmp_o2i_ed_key (b, ip, &key))
+ if (get_icmp_o2i_ed_key
+ (b, ip, rx_fib_index, ~0ULL, p_proto, &l_port, &r_port, &kv))
{
b->error = node->errors[NAT_OUT2IN_ED_ERROR_UNSUPPORTED_PROTOCOL];
next = NAT_NEXT_DROP;
goto out;
}
- key.fib_index = rx_fib_index;
- kv.key[0] = key.as_u64[0];
- kv.key[1] = key.as_u64[1];
if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value))
{
/* Try to match static mapping */
e_key.addr = ip->dst_address;
- e_key.port = key.l_port;
- e_key.protocol = ip_proto_to_snat_proto (key.proto);
+ e_key.port = l_port;
+ e_key.protocol = ip_proto_to_snat_proto (ip->protocol);
e_key.fib_index = rx_fib_index;
if (snat_static_mapping_match
(sm, e_key, &l_key, 1, &is_addr_only, 0, 0, 0, &identity_nat))
@@ -469,7 +469,7 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
else
{
dont_translate = 1;
- if (next_src_nat (sm, ip, key.proto, key.l_port, key.r_port,
+ if (next_src_nat (sm, ip, l_port, r_port,
thread_index, rx_fib_index))
{
next = NAT_NEXT_IN2OUT_ED_FAST_PATH;
@@ -529,8 +529,6 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
s = pool_elt_at_index (tsm->sessions, value.value);
}
-
- *p_proto = ip_proto_to_snat_proto (key.proto);
out:
if (s)
*p_value = s->in2out;
@@ -560,8 +558,8 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm,
old_addr = ip->dst_address.as_u32;
- make_ed_kv (&s_kv, &ip->dst_address, &ip->src_address, ip->protocol,
- rx_fib_index, 0, 0);
+ make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol, rx_fib_index,
+ 0, 0, ~0ULL, &s_kv);
if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value))
{
@@ -613,9 +611,8 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm,
if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1))
nat_elog_notice ("out2in key add failed");
- make_ed_kv (&s_kv, &ip->dst_address, &ip->src_address, ip->protocol,
- m->fib_index, 0, 0);
- s_kv.value = s - tsm->sessions;
+ make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol,
+ m->fib_index, 0, 0, s - tsm->sessions, &s_kv);
if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1))
nat_elog_notice ("in2out key add failed");
}
@@ -721,10 +718,10 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
goto trace0;
}
- make_ed_kv (&kv0, &ip0->dst_address, &ip0->src_address,
+ make_ed_kv (&ip0->dst_address, &ip0->src_address,
ip0->protocol, rx_fib_index0,
vnet_buffer (b0)->ip.reass.l4_dst_port,
- vnet_buffer (b0)->ip.reass.l4_src_port);
+ vnet_buffer (b0)->ip.reass.l4_src_port, ~0ULL, &kv0);
if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
{
@@ -1006,10 +1003,10 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
goto trace0;
}
- make_ed_kv (&kv0, &ip0->dst_address, &ip0->src_address,
+ make_ed_kv (&ip0->dst_address, &ip0->src_address,
ip0->protocol, rx_fib_index0,
vnet_buffer (b0)->ip.reass.l4_dst_port,
- vnet_buffer (b0)->ip.reass.l4_src_port);
+ vnet_buffer (b0)->ip.reass.l4_src_port, ~0ULL, &kv0);
s0 = NULL;
if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
@@ -1059,12 +1056,10 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
}
else
{
- if (next_src_nat (sm, ip0, ip0->protocol,
- vnet_buffer (b0)->ip.
- reass.l4_src_port,
- vnet_buffer (b0)->ip.
- reass.l4_dst_port, thread_index,
- rx_fib_index0))
+ if (next_src_nat
+ (sm, ip0, vnet_buffer (b0)->ip.reass.l4_src_port,
+ vnet_buffer (b0)->ip.reass.l4_dst_port,
+ thread_index, rx_fib_index0))
{
next0 = NAT_NEXT_IN2OUT_ED_FAST_PATH;
goto trace0;