f->rewrite.dport = f->match.dport;
}
if (f->ops & NAT_FLOW_OP_ICMP_ID_REWRITE &&
- f->rewrite.icmp_id != f->match.icmp_id)
+ f->rewrite.icmp_id != f->match.sport)
{
f->l4_csum_delta =
ip_csum_add_even (f->l4_csum_delta, f->rewrite.icmp_id);
- f->l4_csum_delta = ip_csum_sub_even (f->l4_csum_delta, f->match.icmp_id);
+ f->l4_csum_delta = ip_csum_sub_even (f->l4_csum_delta, f->match.sport);
}
else
{
- f->rewrite.icmp_id = f->match.icmp_id;
+ f->rewrite.icmp_id = f->match.sport;
}
if (f->ops & NAT_FLOW_OP_TXFIB_REWRITE)
{
}) per_vrf_sessions_t;
/* *INDENT-ON* */
-typedef struct
+typedef union
{
- ip4_address_t saddr, daddr;
- u32 fib_index;
- u16 sport, dport;
- u16 icmp_id;
- u8 proto;
+ struct
+ {
+ ip4_address_t saddr, daddr;
+ u16 sport; // ICMP id for ICMP case
+ u16 dport;
+ u32 fib_index : 24;
+ u8 proto;
+ };
+ u64 as_u64[2];
+ u64x2u as_u128;
} nat_6t_t;
+STATIC_ASSERT_SIZEOF (nat_6t_t, 2 * sizeof (u64));
+
typedef struct
{
#define NAT_FLOW_OP_SADDR_REWRITE (1 << 1)
#define NAT_FLOW_OP_TXFIB_REWRITE (1 << 6)
int ops;
nat_6t_t match;
- nat_6t_t rewrite;
+ struct
+ {
+ ip4_address_t saddr, daddr;
+ u16 sport;
+ u16 dport;
+ u32 fib_index;
+ u8 proto;
+ u16 icmp_id;
+ } rewrite;
uword l3_csum_delta;
uword l4_csum_delta;
} nat_6t_flow_t;
}
static inline uword
-nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame,
- int is_output_feature)
+nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm,
+ vlib_node_runtime_t *node,
+ vlib_frame_t *frame,
+ int is_output_feature,
+ int is_multi_worker)
{
u32 n_left_from, *from;
snat_main_t *sm = &snat_main;
clib_bihash_kv_16_8_t kv0, value0;
nat_translation_error_e translation_error = NAT_ED_TRNSL_ERR_SUCCESS;
nat_6t_flow_t *f = 0;
- ip4_address_t lookup_saddr, lookup_daddr;
- u16 lookup_sport, lookup_dport;
- u8 lookup_protocol;
+ nat_6t_t lookup;
int lookup_skipped = 0;
b0 = *b;
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
rx_fib_index0 =
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index0);
+ lookup.fib_index = rx_fib_index0;
if (PREDICT_FALSE (ip0->ttl == 1))
{
goto trace0;
}
int err = nat_get_icmp_session_lookup_values (
- b0, ip0, &lookup_saddr, &lookup_sport, &lookup_daddr,
- &lookup_dport, &lookup_protocol);
+ b0, ip0, &lookup.saddr, &lookup.sport, &lookup.daddr,
+ &lookup.dport, &lookup.proto);
if (err != 0)
{
b0->error = node->errors[err];
}
else
{
- lookup_protocol = ip0->protocol;
- lookup_saddr = ip0->src_address;
- lookup_daddr = ip0->dst_address;
- lookup_sport = vnet_buffer (b0)->ip.reass.l4_src_port;
- lookup_dport = vnet_buffer (b0)->ip.reass.l4_dst_port;
+ lookup.proto = ip0->protocol;
+ lookup.saddr.as_u32 = ip0->src_address.as_u32;
+ lookup.daddr.as_u32 = ip0->dst_address.as_u32;
+ lookup.sport = vnet_buffer (b0)->ip.reass.l4_src_port;
+ lookup.dport = vnet_buffer (b0)->ip.reass.l4_dst_port;
}
/* there might be a stashed index in vnet_buffer2 from handoff or
* classify node, see if it can be used */
- if (!pool_is_free_index (tsm->sessions,
+ if (is_multi_worker &&
+ !pool_is_free_index (tsm->sessions,
vnet_buffer2 (b0)->nat.cached_session_index))
{
s0 = pool_elt_at_index (tsm->sessions,
vnet_buffer2 (b0)->nat.cached_session_index);
if (PREDICT_TRUE (
- nat_6t_flow_match (&s0->i2o, b0, lookup_saddr, lookup_sport,
- lookup_daddr, lookup_dport, lookup_protocol,
- rx_fib_index0)
+ nat_6t_t_eq (&s0->i2o.match, &lookup)
// for some hairpinning cases there are two "i2i" flows instead
// of i2o and o2i as both hosts are on inside
|| (s0->flags & SNAT_SESSION_FLAG_HAIRPINNING &&
- nat_6t_flow_match (
- &s0->o2i, b0, lookup_saddr, lookup_sport, lookup_daddr,
- lookup_dport, lookup_protocol, rx_fib_index0))))
+ nat_6t_t_eq (&s0->o2i.match, &lookup))))
{
/* yes, this is the droid we're looking for */
lookup_skipped = 1;
s0 = NULL;
}
- init_ed_k (&kv0, ip0->src_address, lookup_sport, ip0->dst_address,
- lookup_dport, rx_fib_index0, lookup_protocol);
+ init_ed_k (&kv0, lookup.saddr, lookup.sport, lookup.daddr, lookup.dport,
+ lookup.fib_index, lookup.proto);
// lookup flow
if (clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0))
b0->flags |= VNET_BUFFER_F_IS_NATED;
- if (nat_6t_flow_match (&s0->i2o, b0, lookup_saddr, lookup_sport,
- lookup_daddr, lookup_dport, lookup_protocol,
- rx_fib_index0))
+ if (nat_6t_t_eq (&s0->i2o.match, &lookup))
{
f = &s0->i2o;
}
else if (s0->flags & SNAT_SESSION_FLAG_HAIRPINNING &&
- nat_6t_flow_match (&s0->o2i, b0, lookup_saddr, lookup_sport,
- lookup_daddr, lookup_dport, lookup_protocol,
- rx_fib_index0))
+ nat_6t_t_eq (&s0->o2i.match, &lookup))
{
f = &s0->o2i;
}
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 0);
+ if (snat_main.num_workers > 1)
+ {
+ return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 0, 1);
+ }
+ else
+ {
+ return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 0, 0);
+ }
}
VLIB_REGISTER_NODE (nat44_ed_in2out_node) = {
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 1);
+ if (snat_main.num_workers > 1)
+ {
+ return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 1, 1);
+ }
+ else
+ {
+ return nat44_ed_in2out_fast_path_node_fn_inline (vm, node, frame, 1, 0);
+ }
}
VLIB_REGISTER_NODE (nat44_ed_in2out_output_node) = {
}
static_always_inline int
-nat_6t_flow_match (nat_6t_flow_t *f, vlib_buffer_t *b, ip4_address_t saddr,
- u16 sport, ip4_address_t daddr, u16 dport, u8 protocol,
- u32 fib_index)
-{
- return f->match.daddr.as_u32 == daddr.as_u32 &&
- f->match.dport == vnet_buffer (b)->ip.reass.l4_dst_port &&
- f->match.proto == protocol && f->match.fib_index == fib_index &&
- f->match.saddr.as_u32 == saddr.as_u32 &&
- f->match.sport == vnet_buffer (b)->ip.reass.l4_src_port;
+nat_6t_t_eq (nat_6t_t *t1, nat_6t_t *t2)
+{
+ return t1->as_u64[0] == t2->as_u64[0] && t1->as_u64[1] == t2->as_u64[1];
}
static inline uword
clib_bihash_kv_16_8_t kv0, value0;
nat_translation_error_e translation_error = NAT_ED_TRNSL_ERR_SUCCESS;
nat_6t_flow_t *f = 0;
- ip4_address_t lookup_saddr, lookup_daddr;
- u16 lookup_sport, lookup_dport;
- u8 lookup_protocol;
+ nat_6t_t lookup;
int lookup_skipped = 0;
b0 = *b;
b++;
- lookup_sport = vnet_buffer (b0)->ip.reass.l4_src_port;
- lookup_dport = vnet_buffer (b0)->ip.reass.l4_dst_port;
-
/* Prefetch next iteration. */
if (PREDICT_TRUE (n_left_from >= 2))
{
next[0] = vnet_buffer2 (b0)->nat.arc_next;
+ lookup.sport = vnet_buffer (b0)->ip.reass.l4_src_port;
+ lookup.dport = vnet_buffer (b0)->ip.reass.l4_dst_port;
+
vnet_buffer (b0)->snat.flags = 0;
ip0 = vlib_buffer_get_current (b0);
rx_fib_index0 =
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index0);
+ lookup.fib_index = rx_fib_index0;
+
if (PREDICT_FALSE (ip0->ttl == 1))
{
vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
goto trace0;
}
int err = nat_get_icmp_session_lookup_values (
- b0, ip0, &lookup_saddr, &lookup_sport, &lookup_daddr,
- &lookup_dport, &lookup_protocol);
+ b0, ip0, &lookup.saddr, &lookup.sport, &lookup.daddr,
+ &lookup.dport, &lookup.proto);
if (err != 0)
{
b0->error = node->errors[err];
}
else
{
- lookup_saddr.as_u32 = ip0->src_address.as_u32;
- lookup_daddr.as_u32 = ip0->dst_address.as_u32;
- lookup_protocol = ip0->protocol;
+ lookup.saddr.as_u32 = ip0->src_address.as_u32;
+ lookup.daddr.as_u32 = ip0->dst_address.as_u32;
+ lookup.proto = ip0->protocol;
}
/* there might be a stashed index in vnet_buffer2 from handoff or
* classify node, see if it can be used */
- if (!pool_is_free_index (tsm->sessions,
+ if (is_multi_worker &&
+ !pool_is_free_index (tsm->sessions,
vnet_buffer2 (b0)->nat.cached_session_index))
{
s0 = pool_elt_at_index (tsm->sessions,
vnet_buffer2 (b0)->nat.cached_session_index);
- if (PREDICT_TRUE (
- nat_6t_flow_match (&s0->o2i, b0, lookup_saddr, lookup_sport,
- lookup_daddr, lookup_dport, lookup_protocol,
- rx_fib_index0) ||
- (s0->flags & SNAT_SESSION_FLAG_TWICE_NAT &&
- nat_6t_flow_match (&s0->i2o, b0, lookup_saddr, lookup_sport,
- lookup_daddr, lookup_dport,
- lookup_protocol, rx_fib_index0))))
+ if (PREDICT_TRUE (nat_6t_t_eq (&s0->o2i.match, &lookup)) ||
+ (s0->flags & SNAT_SESSION_FLAG_TWICE_NAT &&
+ nat_6t_t_eq (&s0->i2o.match, &lookup)))
{
/* yes, this is the droid we're looking for */
lookup_skipped = 1;
s0 = NULL;
}
- init_ed_k (&kv0, lookup_saddr, lookup_sport, lookup_daddr, lookup_dport,
- rx_fib_index0, lookup_protocol);
+ init_ed_k (&kv0, lookup.saddr, lookup.sport, lookup.daddr, lookup.dport,
+ lookup.fib_index, lookup.proto);
// lookup flow
if (clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0))
goto trace0;
}
- if (nat_6t_flow_match (&s0->o2i, b0, lookup_saddr, lookup_sport,
- lookup_daddr, lookup_dport, lookup_protocol,
- rx_fib_index0))
+ if (nat_6t_t_eq (&s0->o2i.match, &lookup))
{
f = &s0->o2i;
}
else if (s0->flags & SNAT_SESSION_FLAG_TWICE_NAT &&
- nat_6t_flow_match (&s0->i2o, b0, lookup_saddr, lookup_sport,
- lookup_daddr, lookup_dport, lookup_protocol,
- rx_fib_index0))
+ nat_6t_t_eq (&s0->i2o.match, &lookup))
{
f = &s0->i2o;
}
}
else
{
- if (nat_6t_flow_match (&s0->i2o, b0, lookup_saddr, lookup_sport,
- lookup_daddr, lookup_dport,
- lookup_protocol, rx_fib_index0))
+ if (nat_6t_t_eq (&s0->i2o.match, &lookup))
{
f = &s0->i2o;
}