summaryrefslogtreecommitdiffstats
path: root/src/plugins/cnat
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/cnat')
-rw-r--r--src/plugins/cnat/cnat.api1
-rw-r--r--src/plugins/cnat/cnat.rst2
-rw-r--r--src/plugins/cnat/cnat_api.c7
-rw-r--r--src/plugins/cnat/cnat_bihash.h (renamed from src/plugins/cnat/bihash_40_48.h)44
-rw-r--r--src/plugins/cnat/cnat_client.c2
-rw-r--r--src/plugins/cnat/cnat_node.h283
-rw-r--r--src/plugins/cnat/cnat_node_snat.c100
-rw-r--r--src/plugins/cnat/cnat_node_vip.c94
-rw-r--r--src/plugins/cnat/cnat_scanner.c4
-rw-r--r--src/plugins/cnat/cnat_session.c74
-rw-r--r--src/plugins/cnat/cnat_session.h47
-rw-r--r--src/plugins/cnat/cnat_snat.c10
-rw-r--r--src/plugins/cnat/cnat_translation.c70
-rw-r--r--src/plugins/cnat/cnat_translation.h12
-rw-r--r--src/plugins/cnat/cnat_types.h2
-rw-r--r--src/plugins/cnat/test/test_cnat.py4
16 files changed, 390 insertions, 366 deletions
diff --git a/src/plugins/cnat/cnat.api b/src/plugins/cnat/cnat.api
index 7bf6be8b349..685f9e17146 100644
--- a/src/plugins/cnat/cnat.api
+++ b/src/plugins/cnat/cnat.api
@@ -102,6 +102,7 @@ typedef cnat_session
vl_api_cnat_endpoint_t dst;
vl_api_cnat_endpoint_t new;
vl_api_ip_proto_t ip_proto;
+ u8 location;
f64 timestamp;
};
diff --git a/src/plugins/cnat/cnat.rst b/src/plugins/cnat/cnat.rst
index 3cb08bc8c6c..8781f405a23 100644
--- a/src/plugins/cnat/cnat.rst
+++ b/src/plugins/cnat/cnat.rst
@@ -96,7 +96,7 @@ address assigned to an interface)
cnat snat with 30.0.0.1
cnat snat exclude 20.0.0.0/24
- set interface feature tap0 ip4-cnat-snat arc ip4-unicast
+ set interface feature tap0 cnat-snat-ip4 arc ip4-unicast
Other parameters
----------------
diff --git a/src/plugins/cnat/cnat_api.c b/src/plugins/cnat/cnat_api.c
index c215caae86f..1c6ef7b6cf4 100644
--- a/src/plugins/cnat/cnat_api.c
+++ b/src/plugins/cnat/cnat_api.c
@@ -124,12 +124,10 @@ vl_api_cnat_translation_update_t_handler (vl_api_cnat_translation_update_t
vec_free (paths);
done:
- /* *INDENT-OFF* */
REPLY_MACRO2 (VL_API_CNAT_TRANSLATION_UPDATE_REPLY,
({
rmp->id = htonl (id);
}));
- /* *INDENT-ON* */
}
static void
@@ -246,6 +244,7 @@ cnat_session_send_details (const cnat_session_t * session, void *args)
cnat_endpoint_encode (&ep, &mp->session.dst);
mp->session.ip_proto = ip_proto_encode (session->key.cs_proto);
+ mp->session.location = session->key.cs_loc;
vl_api_send_msg (ctx->rp, (u8 *) mp);
@@ -289,14 +288,12 @@ vl_api_cnat_get_snat_addresses_t_handler (vl_api_cnat_get_snat_addresses_t
vl_api_cnat_get_snat_addresses_reply_t *rmp;
int rv = 0;
- /* *INDENT-OFF* */
REPLY_MACRO2 (VL_API_CNAT_GET_SNAT_ADDRESSES_REPLY,
({
ip6_address_encode (&ip_addr_v6(&cnat_main.snat_ip6.ce_ip), rmp->snat_ip6);
ip4_address_encode (&ip_addr_v4(&cnat_main.snat_ip4.ce_ip), rmp->snat_ip4);
rmp->sw_if_index = clib_host_to_net_u32 (cnat_main.snat_ip6.ce_sw_if_index);
}));
- /* *INDENT-ON* */
}
static void
@@ -347,12 +344,10 @@ cnat_api_init (vlib_main_t * vm)
VLIB_INIT_FUNCTION (cnat_api_init);
-/* *INDENT-OFF* */
VLIB_PLUGIN_REGISTER () = {
.version = VPP_BUILD_VER,
.description = "CNat Translate",
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/plugins/cnat/bihash_40_48.h b/src/plugins/cnat/cnat_bihash.h
index df345cec357..a148ad57682 100644
--- a/src/plugins/cnat/bihash_40_48.h
+++ b/src/plugins/cnat/cnat_bihash.h
@@ -21,14 +21,14 @@
#undef BIHASH_LAZY_INSTANTIATE
#undef BIHASH_BUCKET_PREFETCH_CACHE_LINES
-#define BIHASH_TYPE _40_48
+#define BIHASH_TYPE _40_56
#define BIHASH_KVP_PER_PAGE 2
#define BIHASH_KVP_AT_BUCKET_LEVEL 1
#define BIHASH_LAZY_INSTANTIATE 1
#define BIHASH_BUCKET_PREFETCH_CACHE_LINES 2
-#ifndef __included_bihash_40_48_h__
-#define __included_bihash_40_48_h__
+#ifndef __included_bihash_40_56_h__
+#define __included_bihash_40_56_h__
#include <vppinfra/crc32.h>
#include <vppinfra/heap.h>
@@ -39,11 +39,11 @@
typedef struct
{
u64 key[5];
- u64 value[6];
-} clib_bihash_kv_40_48_t;
+ u64 value[7];
+} clib_bihash_kv_40_56_t;
static inline int
-clib_bihash_is_free_40_48 (const clib_bihash_kv_40_48_t * v)
+clib_bihash_is_free_40_56 (const clib_bihash_kv_40_56_t *v)
{
/* Free values are clib_memset to 0xff, check a bit... */
if (v->key[0] == ~0ULL && v->value[0] == ~0ULL)
@@ -52,7 +52,7 @@ clib_bihash_is_free_40_48 (const clib_bihash_kv_40_48_t * v)
}
static inline u64
-clib_bihash_hash_40_48 (const clib_bihash_kv_40_48_t * v)
+clib_bihash_hash_40_56 (const clib_bihash_kv_40_56_t *v)
{
#ifdef clib_crc32c_uses_intrinsics
return clib_crc32c ((u8 *) v->key, 40);
@@ -63,21 +63,21 @@ clib_bihash_hash_40_48 (const clib_bihash_kv_40_48_t * v)
}
static inline u8 *
-format_bihash_kvp_40_48 (u8 * s, va_list * args)
+format_bihash_kvp_40_56 (u8 *s, va_list *args)
{
- clib_bihash_kv_40_48_t *v = va_arg (*args, clib_bihash_kv_40_48_t *);
+ clib_bihash_kv_40_56_t *v = va_arg (*args, clib_bihash_kv_40_56_t *);
- s =
- format (s,
- "key %llu %llu %llu %llu %llu value %llu %llu %llu %llu %llu %u",
- v->key[0], v->key[1], v->key[2], v->key[3], v->key[4],
- v->value[0], v->value[1], v->value[2], v->value[3], v->value[4],
- v->value[5]);
+ s = format (s,
+ "key %llu %llu %llu %llu %llu"
+ "value %llu %llu %llu %llu %llu %llu %llu",
+ v->key[0], v->key[1], v->key[2], v->key[3], v->key[4],
+ v->value[0], v->value[1], v->value[2], v->value[3], v->value[4],
+ v->value[5], v->value[6]);
return s;
}
static inline int
-clib_bihash_key_compare_40_48 (u64 * a, u64 * b)
+clib_bihash_key_compare_40_56 (u64 *a, u64 *b)
{
#if defined (CLIB_HAVE_VEC512)
u64x8 v;
@@ -101,7 +101,17 @@ clib_bihash_key_compare_40_48 (u64 * a, u64 * b)
#undef __included_bihash_template_h__
#include <vppinfra/bihash_template.h>
-#endif /* __included_bihash_40_48_h__ */
+typedef clib_bihash_kv_40_56_t cnat_bihash_kv_t;
+typedef clib_bihash_40_56_t cnat_bihash_t;
+
+#define cnat_bihash_search_i2_hash clib_bihash_search_inline_2_with_hash_40_56
+#define cnat_bihash_search_i2 clib_bihash_search_inline_2_40_56
+#define cnat_bihash_add_del clib_bihash_add_del_40_56
+#define cnat_bihash_hash clib_bihash_hash_40_56
+#define cnat_bihash_prefetch_bucket clib_bihash_prefetch_bucket_40_56
+#define cnat_bihash_prefetch_data clib_bihash_prefetch_data_40_56
+
+#endif /* __included_bihash_40_56_h__ */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/plugins/cnat/cnat_client.c b/src/plugins/cnat/cnat_client.c
index 8beaeadb4b1..b8fcb9add64 100644
--- a/src/plugins/cnat/cnat_client.c
+++ b/src/plugins/cnat/cnat_client.c
@@ -301,14 +301,12 @@ cnat_client_show (vlib_main_t * vm,
return (NULL);
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cnat_client_show_cmd_node, static) = {
.path = "show cnat client",
.function = cnat_client_show,
.short_help = "show cnat client",
.is_mp_safe = 1,
};
-/* *INDENT-ON* */
const static char *const cnat_client_dpo_ip4_nodes[] = {
"ip4-cnat-tx",
diff --git a/src/plugins/cnat/cnat_node.h b/src/plugins/cnat/cnat_node.h
index e2a9965b2a6..56a6c612e1b 100644
--- a/src/plugins/cnat/cnat_node.h
+++ b/src/plugins/cnat/cnat_node.h
@@ -17,9 +17,16 @@
#define __CNAT_NODE_H__
#include <vlibmemory/api.h>
+#include <vnet/dpo/load_balance.h>
+#include <vnet/dpo/load_balance_map.h>
+
#include <cnat/cnat_session.h>
#include <cnat/cnat_client.h>
#include <cnat/cnat_inline.h>
+#include <cnat/cnat_translation.h>
+
+#include <vnet/ip/ip4_inlines.h>
+#include <vnet/ip/ip6_inlines.h>
typedef uword (*cnat_node_sub_t) (vlib_main_t * vm,
vlib_node_runtime_t * node,
@@ -27,6 +34,77 @@ typedef uword (*cnat_node_sub_t) (vlib_main_t * vm,
cnat_node_ctx_t * ctx, int rv,
cnat_session_t * session);
+typedef struct cnat_trace_element_t_
+{
+ cnat_session_t session;
+ cnat_translation_t tr;
+ u32 sw_if_index[VLIB_N_RX_TX];
+ u32 snat_policy_result;
+ u8 flags;
+} cnat_trace_element_t;
+
+typedef enum cnat_trace_element_flag_t_
+{
+ CNAT_TRACE_SESSION_FOUND = (1 << 0),
+ CNAT_TRACE_SESSION_CREATED = (1 << 1),
+ CNAT_TRACE_TRANSLATION_FOUND = (1 << 2),
+ CNAT_TRACE_NO_NAT = (1 << 3),
+} cnat_trace_element_flag_t;
+
+static_always_inline void
+cnat_add_trace (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b,
+ cnat_session_t *session, const cnat_translation_t *ct,
+ u8 flags)
+{
+ cnat_trace_element_t *t;
+ if (NULL != ct)
+ flags |= CNAT_TRACE_TRANSLATION_FOUND;
+
+ t = vlib_add_trace (vm, node, b, sizeof (*t));
+ t->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_RX];
+ t->sw_if_index[VLIB_TX] = vnet_buffer (b)->sw_if_index[VLIB_TX];
+
+ if (flags & (CNAT_TRACE_SESSION_FOUND | CNAT_TRACE_SESSION_CREATED))
+ clib_memcpy (&t->session, session, sizeof (t->session));
+ if (flags & CNAT_TRACE_TRANSLATION_FOUND)
+ clib_memcpy (&t->tr, ct, sizeof (cnat_translation_t));
+ t->flags = flags;
+}
+
+static u8 *
+format_cnat_trace (u8 *s, va_list *args)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+ cnat_trace_element_t *t = va_arg (*args, cnat_trace_element_t *);
+ u32 indent = format_get_indent (s);
+ vnet_main_t *vnm = vnet_get_main ();
+
+ if (t->flags & CNAT_TRACE_SESSION_CREATED)
+ s = format (s, "created session");
+ else if (t->flags & CNAT_TRACE_SESSION_FOUND)
+ s = format (s, "found session");
+ else
+ s = format (s, "session not found");
+
+ if (t->flags & (CNAT_TRACE_NO_NAT))
+ s = format (s, " [policy:skip]");
+
+ s = format (s, "\n%Uin:%U out:%U ", format_white_space, indent,
+ format_vnet_sw_if_index_name, vnm, t->sw_if_index[VLIB_RX],
+ format_vnet_sw_if_index_name, vnm, t->sw_if_index[VLIB_TX]);
+
+ if (t->flags & (CNAT_TRACE_SESSION_CREATED | CNAT_TRACE_SESSION_FOUND))
+ s = format (s, "\n%U%U", format_white_space, indent, format_cnat_session,
+ &t->session, 1);
+
+ if (t->flags & CNAT_TRACE_TRANSLATION_FOUND)
+ s = format (s, "\n%Utranslation: %U", format_white_space, indent,
+ format_cnat_translation, &t->tr, 0);
+
+ return s;
+}
+
static_always_inline u8
icmp_type_is_error_message (u8 icmp_type)
{
@@ -604,18 +682,25 @@ cnat_translation_ip6 (const cnat_session_t * session,
}
static_always_inline void
-cnat_session_make_key (vlib_buffer_t * b, ip_address_family_t af,
- clib_bihash_kv_40_48_t * bkey)
+cnat_session_make_key (vlib_buffer_t *b, ip_address_family_t af,
+ cnat_session_location_t cs_loc, cnat_bihash_kv_t *bkey)
{
udp_header_t *udp;
cnat_session_t *session = (cnat_session_t *) bkey;
+ u32 iph_offset = 0;
session->key.cs_af = af;
- session->key.__cs_pad[0] = 0;
- session->key.__cs_pad[1] = 0;
+
+ session->key.cs_loc = cs_loc;
+ session->key.__cs_pad = 0;
+ if (cs_loc == CNAT_LOCATION_OUTPUT)
+ /* rewind buffer */
+ iph_offset = vnet_buffer (b)->ip.save_rewrite_length;
+
if (AF_IP4 == af)
{
ip4_header_t *ip4;
- ip4 = vlib_buffer_get_current (b);
+ ip4 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b) + iph_offset);
+
if (PREDICT_FALSE (ip4->protocol == IP_PROTOCOL_ICMP))
{
icmp46_header_t *icmp = (icmp46_header_t *) (ip4 + 1);
@@ -646,7 +731,8 @@ cnat_session_make_key (vlib_buffer_t * b, ip_address_family_t af,
else
goto error;
}
- else
+ else if (ip4->protocol == IP_PROTOCOL_UDP ||
+ ip4->protocol == IP_PROTOCOL_TCP)
{
udp = (udp_header_t *) (ip4 + 1);
ip46_address_set_ip4 (&session->key.cs_ip[VLIB_TX],
@@ -657,12 +743,13 @@ cnat_session_make_key (vlib_buffer_t * b, ip_address_family_t af,
session->key.cs_port[VLIB_RX] = udp->src_port;
session->key.cs_port[VLIB_TX] = udp->dst_port;
}
-
+ else
+ goto error;
}
else
{
ip6_header_t *ip6;
- ip6 = vlib_buffer_get_current (b);
+ ip6 = (ip6_header_t *) ((u8 *) vlib_buffer_get_current (b) + iph_offset);
if (PREDICT_FALSE (ip6->protocol == IP_PROTOCOL_ICMP6))
{
icmp46_header_t *icmp = (icmp46_header_t *) (ip6 + 1);
@@ -693,7 +780,8 @@ cnat_session_make_key (vlib_buffer_t * b, ip_address_family_t af,
else
goto error;
}
- else
+ else if (ip6->protocol == IP_PROTOCOL_UDP ||
+ ip6->protocol == IP_PROTOCOL_TCP)
{
udp = (udp_header_t *) (ip6 + 1);
ip46_address_set_ip6 (&session->key.cs_ip[VLIB_TX],
@@ -704,6 +792,8 @@ cnat_session_make_key (vlib_buffer_t * b, ip_address_family_t af,
session->key.cs_port[VLIB_TX] = udp->dst_port;
session->key.cs_proto = ip6->protocol;
}
+ else
+ goto error;
}
return;
@@ -715,59 +805,64 @@ error:
/**
* Create NAT sessions
+ * rsession_location is the location the (return) session will be
+ * matched at
*/
-
static_always_inline void
-cnat_session_create (cnat_session_t * session, cnat_node_ctx_t * ctx,
+cnat_session_create (cnat_session_t *session, cnat_node_ctx_t *ctx,
+ cnat_session_location_t rsession_location,
u8 rsession_flags)
{
cnat_client_t *cc;
- clib_bihash_kv_40_48_t rkey;
+ cnat_bihash_kv_t rkey;
cnat_session_t *rsession = (cnat_session_t *) & rkey;
- clib_bihash_kv_40_48_t *bkey = (clib_bihash_kv_40_48_t *) session;
- clib_bihash_kv_40_48_t rvalue;
+ cnat_bihash_kv_t *bkey = (cnat_bihash_kv_t *) session;
+ cnat_bihash_kv_t rvalue;
int rv;
session->value.cs_ts_index = cnat_timestamp_new (ctx->now);
- clib_bihash_add_del_40_48 (&cnat_session_db, bkey, 1);
-
- /* is this the first time we've seen this source address */
- cc = (AF_IP4 == ctx->af ?
- cnat_client_ip4_find (&session->value.cs_ip[VLIB_RX].ip4) :
- cnat_client_ip6_find (&session->value.cs_ip[VLIB_RX].ip6));
+ cnat_bihash_add_del (&cnat_session_db, bkey, 1);
- if (NULL == cc)
+ if (!(rsession_flags & CNAT_SESSION_FLAG_NO_CLIENT))
{
- ip_address_t addr;
- uword *p;
- u32 refcnt;
+ /* is this the first time we've seen this source address */
+ cc = (AF_IP4 == ctx->af ?
+ cnat_client_ip4_find (&session->value.cs_ip[VLIB_RX].ip4) :
+ cnat_client_ip6_find (&session->value.cs_ip[VLIB_RX].ip6));
- addr.version = ctx->af;
- ip46_address_copy (&addr.ip, &session->value.cs_ip[VLIB_RX]);
+ if (NULL == cc)
+ {
+ ip_address_t addr;
+ uword *p;
+ u32 refcnt;
- /* Throttle */
- clib_spinlock_lock (&cnat_client_db.throttle_lock);
+ addr.version = ctx->af;
+ ip46_address_copy (&addr.ip, &session->value.cs_ip[VLIB_RX]);
- p = hash_get_mem (cnat_client_db.throttle_mem, &addr);
- if (p)
- {
- refcnt = p[0] + 1;
- hash_set_mem (cnat_client_db.throttle_mem, &addr, refcnt);
- }
- else
- hash_set_mem_alloc (&cnat_client_db.throttle_mem, &addr, 0);
+ /* Throttle */
+ clib_spinlock_lock (&cnat_client_db.throttle_lock);
- clib_spinlock_unlock (&cnat_client_db.throttle_lock);
+ p = hash_get_mem (cnat_client_db.throttle_mem, &addr);
+ if (p)
+ {
+ refcnt = p[0] + 1;
+ hash_set_mem (cnat_client_db.throttle_mem, &addr, refcnt);
+ }
+ else
+ hash_set_mem_alloc (&cnat_client_db.throttle_mem, &addr, 0);
- /* fire client create to the main thread */
- if (!p)
- vl_api_rpc_call_main_thread (cnat_client_learn, (u8 *) &addr,
- sizeof (addr));
- }
- else
- {
- /* Refcount reverse session */
- cnat_client_cnt_session (cc);
+ clib_spinlock_unlock (&cnat_client_db.throttle_lock);
+
+ /* fire client create to the main thread */
+ if (!p)
+ vl_api_rpc_call_main_thread (cnat_client_learn, (u8 *) &addr,
+ sizeof (addr));
+ }
+ else
+ {
+ /* Refcount reverse session */
+ cnat_client_cnt_session (cc);
+ }
}
/* create the reverse flow key */
@@ -776,14 +871,14 @@ cnat_session_create (cnat_session_t * session, cnat_node_ctx_t * ctx,
ip46_address_copy (&rsession->key.cs_ip[VLIB_TX],
&session->value.cs_ip[VLIB_RX]);
rsession->key.cs_proto = session->key.cs_proto;
- rsession->key.__cs_pad[0] = 0;
- rsession->key.__cs_pad[1] = 0;
+ rsession->key.cs_loc = rsession_location;
+ rsession->key.__cs_pad = 0;
rsession->key.cs_af = ctx->af;
rsession->key.cs_port[VLIB_RX] = session->value.cs_port[VLIB_TX];
rsession->key.cs_port[VLIB_TX] = session->value.cs_port[VLIB_RX];
/* First search for existing reverse session */
- rv = clib_bihash_search_inline_2_40_48 (&cnat_session_db, &rkey, &rvalue);
+ rv = cnat_bihash_search_i2 (&cnat_session_db, &rkey, &rvalue);
if (!rv)
{
/* Reverse session already exists
@@ -802,15 +897,14 @@ cnat_session_create (cnat_session_t * session, cnat_node_ctx_t * ctx,
rsession->value.cs_port[VLIB_TX] = session->key.cs_port[VLIB_RX];
rsession->value.cs_port[VLIB_RX] = session->key.cs_port[VLIB_TX];
- clib_bihash_add_del_40_48 (&cnat_session_db, &rkey, 1);
+ cnat_bihash_add_del (&cnat_session_db, &rkey, 1);
}
always_inline uword
-cnat_node_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame,
- cnat_node_sub_t cnat_sub,
- ip_address_family_t af, u8 do_trace)
+cnat_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame, cnat_node_sub_t cnat_sub,
+ ip_address_family_t af, cnat_session_location_t cs_loc,
+ u8 do_trace)
{
u32 n_left, *from, thread_index;
vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
@@ -825,7 +919,7 @@ cnat_node_inline (vlib_main_t * vm,
vlib_get_buffers (vm, from, bufs, n_left);
now = vlib_time_now (vm);
cnat_session_t *session[4];
- clib_bihash_kv_40_48_t bkey[4], bvalue[4];
+ cnat_bihash_kv_t bkey[4], bvalue[4];
u64 hash[4];
int rv[4];
@@ -834,15 +928,15 @@ cnat_node_inline (vlib_main_t * vm,
if (n_left >= 8)
{
/* Kickstart our state */
- cnat_session_make_key (b[3], af, &bkey[3]);
- cnat_session_make_key (b[2], af, &bkey[2]);
- cnat_session_make_key (b[1], af, &bkey[1]);
- cnat_session_make_key (b[0], af, &bkey[0]);
+ cnat_session_make_key (b[3], af, cs_loc, &bkey[3]);
+ cnat_session_make_key (b[2], af, cs_loc, &bkey[2]);
+ cnat_session_make_key (b[1], af, cs_loc, &bkey[1]);
+ cnat_session_make_key (b[0], af, cs_loc, &bkey[0]);
- hash[3] = clib_bihash_hash_40_48 (&bkey[3]);
- hash[2] = clib_bihash_hash_40_48 (&bkey[2]);
- hash[1] = clib_bihash_hash_40_48 (&bkey[1]);
- hash[0] = clib_bihash_hash_40_48 (&bkey[0]);
+ hash[3] = cnat_bihash_hash (&bkey[3]);
+ hash[2] = cnat_bihash_hash (&bkey[2]);
+ hash[1] = cnat_bihash_hash (&bkey[1]);
+ hash[0] = cnat_bihash_hash (&bkey[0]);
}
while (n_left >= 8)
@@ -855,53 +949,45 @@ cnat_node_inline (vlib_main_t * vm,
vlib_prefetch_buffer_header (b[8], LOAD);
}
- rv[3] =
- clib_bihash_search_inline_2_with_hash_40_48 (&cnat_session_db,
- hash[3], &bkey[3],
- &bvalue[3]);
+ rv[3] = cnat_bihash_search_i2_hash (&cnat_session_db, hash[3], &bkey[3],
+ &bvalue[3]);
session[3] = (cnat_session_t *) (rv[3] ? &bkey[3] : &bvalue[3]);
next[3] = cnat_sub (vm, node, b[3], &ctx, rv[3], session[3]);
- rv[2] =
- clib_bihash_search_inline_2_with_hash_40_48 (&cnat_session_db,
- hash[2], &bkey[2],
- &bvalue[2]);
+ rv[2] = cnat_bihash_search_i2_hash (&cnat_session_db, hash[2], &bkey[2],
+ &bvalue[2]);
session[2] = (cnat_session_t *) (rv[2] ? &bkey[2] : &bvalue[2]);
next[2] = cnat_sub (vm, node, b[2], &ctx, rv[2], session[2]);
- rv[1] =
- clib_bihash_search_inline_2_with_hash_40_48 (&cnat_session_db,
- hash[1], &bkey[1],
- &bvalue[1]);
+ rv[1] = cnat_bihash_search_i2_hash (&cnat_session_db, hash[1], &bkey[1],
+ &bvalue[1]);
session[1] = (cnat_session_t *) (rv[1] ? &bkey[1] : &bvalue[1]);
next[1] = cnat_sub (vm, node, b[1], &ctx, rv[1], session[1]);
- rv[0] =
- clib_bihash_search_inline_2_with_hash_40_48 (&cnat_session_db,
- hash[0], &bkey[0],
- &bvalue[0]);
+ rv[0] = cnat_bihash_search_i2_hash (&cnat_session_db, hash[0], &bkey[0],
+ &bvalue[0]);
session[0] = (cnat_session_t *) (rv[0] ? &bkey[0] : &bvalue[0]);
next[0] = cnat_sub (vm, node, b[0], &ctx, rv[0], session[0]);
- cnat_session_make_key (b[7], af, &bkey[3]);
- cnat_session_make_key (b[6], af, &bkey[2]);
- cnat_session_make_key (b[5], af, &bkey[1]);
- cnat_session_make_key (b[4], af, &bkey[0]);
+ cnat_session_make_key (b[7], af, cs_loc, &bkey[3]);
+ cnat_session_make_key (b[6], af, cs_loc, &bkey[2]);
+ cnat_session_make_key (b[5], af, cs_loc, &bkey[1]);
+ cnat_session_make_key (b[4], af, cs_loc, &bkey[0]);
- hash[3] = clib_bihash_hash_40_48 (&bkey[3]);
- hash[2] = clib_bihash_hash_40_48 (&bkey[2]);
- hash[1] = clib_bihash_hash_40_48 (&bkey[1]);
- hash[0] = clib_bihash_hash_40_48 (&bkey[0]);
+ hash[3] = cnat_bihash_hash (&bkey[3]);
+ hash[2] = cnat_bihash_hash (&bkey[2]);
+ hash[1] = cnat_bihash_hash (&bkey[1]);
+ hash[0] = cnat_bihash_hash (&bkey[0]);
- clib_bihash_prefetch_bucket_40_48 (&cnat_session_db, hash[3]);
- clib_bihash_prefetch_bucket_40_48 (&cnat_session_db, hash[2]);
- clib_bihash_prefetch_bucket_40_48 (&cnat_session_db, hash[1]);
- clib_bihash_prefetch_bucket_40_48 (&cnat_session_db, hash[0]);
+ cnat_bihash_prefetch_bucket (&cnat_session_db, hash[3]);
+ cnat_bihash_prefetch_bucket (&cnat_session_db, hash[2]);
+ cnat_bihash_prefetch_bucket (&cnat_session_db, hash[1]);
+ cnat_bihash_prefetch_bucket (&cnat_session_db, hash[0]);
- clib_bihash_prefetch_data_40_48 (&cnat_session_db, hash[3]);
- clib_bihash_prefetch_data_40_48 (&cnat_session_db, hash[2]);
- clib_bihash_prefetch_data_40_48 (&cnat_session_db, hash[1]);
- clib_bihash_prefetch_data_40_48 (&cnat_session_db, hash[0]);
+ cnat_bihash_prefetch_data (&cnat_session_db, hash[3]);
+ cnat_bihash_prefetch_data (&cnat_session_db, hash[2]);
+ cnat_bihash_prefetch_data (&cnat_session_db, hash[1]);
+ cnat_bihash_prefetch_data (&cnat_session_db, hash[0]);
b += 4;
next += 4;
@@ -910,9 +996,8 @@ cnat_node_inline (vlib_main_t * vm,
while (n_left > 0)
{
- cnat_session_make_key (b[0], af, &bkey[0]);
- rv[0] = clib_bihash_search_inline_2_40_48 (&cnat_session_db,
- &bkey[0], &bvalue[0]);
+ cnat_session_make_key (b[0], af, cs_loc, &bkey[0]);
+ rv[0] = cnat_bihash_search_i2 (&cnat_session_db, &bkey[0], &bvalue[0]);
session[0] = (cnat_session_t *) (rv[0] ? &bkey[0] : &bvalue[0]);
next[0] = cnat_sub (vm, node, b[0], &ctx, rv[0], session[0]);
diff --git a/src/plugins/cnat/cnat_node_snat.c b/src/plugins/cnat/cnat_node_snat.c
index 8166df6a757..ef784a6c103 100644
--- a/src/plugins/cnat/cnat_node_snat.c
+++ b/src/plugins/cnat/cnat_node_snat.c
@@ -25,44 +25,18 @@ typedef enum cnat_snat_next_
CNAT_SNAT_N_NEXT,
} cnat_snat_next_t;
-typedef struct cnat_snat_trace_
-{
- cnat_session_t session;
- u32 found_session;
- u32 created_session;
-} cnat_snat_trace_t;
-
vlib_node_registration_t cnat_snat_ip4_node;
vlib_node_registration_t cnat_snat_ip6_node;
-static u8 *
-format_cnat_snat_trace (u8 * s, va_list * args)
-{
- CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
- CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
- cnat_snat_trace_t *t = va_arg (*args, cnat_snat_trace_t *);
-
- if (t->found_session)
- s = format (s, "found: %U", format_cnat_session, &t->session, 1);
- else if (t->created_session)
- s = format (s, "created: %U\n tr: %U",
- format_cnat_session, &t->session, 1);
- else
- s = format (s, "not found");
- return s;
-}
-
/* CNat sub for source NAT as a feature arc on ip[46]-unicast
This node's sub shouldn't apply to the same flows as
cnat_vip_inline */
static uword
-cnat_snat_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_buffer_t * b,
- cnat_node_ctx_t * ctx, int rv, cnat_session_t * session)
+cnat_snat_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_buffer_t *b, cnat_node_ctx_t *ctx,
+ int session_not_found, cnat_session_t *session)
{
cnat_main_t *cm = &cnat_main;
- int created_session = 0;
ip4_header_t *ip4 = NULL;
ip_protocol_t iproto;
ip6_header_t *ip6 = NULL;
@@ -70,6 +44,8 @@ cnat_snat_node_fn (vlib_main_t * vm,
u32 arc_next0;
u16 next0;
u16 sport;
+ u8 trace_flags = 0;
+ int rv;
if (AF_IP4 == ctx->af)
{
@@ -95,7 +71,7 @@ cnat_snat_node_fn (vlib_main_t * vm,
goto trace;
}
- if (!rv)
+ if (!session_not_found)
{
/* session table hit */
cnat_timestamp_update (session->value.cs_ts_index, ctx->now);
@@ -151,9 +127,10 @@ cnat_snat_node_fn (vlib_main_t * vm,
session->value.cs_lbi = INDEX_INVALID;
session->value.flags =
CNAT_SESSION_FLAG_NO_CLIENT | CNAT_SESSION_FLAG_ALLOC_PORT;
+ trace_flags |= CNAT_TRACE_SESSION_CREATED;
- created_session = 1;
- cnat_session_create (session, ctx, CNAT_SESSION_FLAG_HAS_SNAT);
+ cnat_session_create (session, ctx, CNAT_LOCATION_FIB,
+ CNAT_SESSION_FLAG_HAS_SNAT);
}
@@ -165,14 +142,8 @@ cnat_snat_node_fn (vlib_main_t * vm,
trace:
if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
{
- cnat_snat_trace_t *t;
-
- t = vlib_add_trace (vm, node, b, sizeof (*t));
-
- t->found_session = !rv;
- t->created_session = created_session;
- if (t->found_session || t->created_session)
- clib_memcpy (&t->session, session, sizeof (t->session));
+ trace_flags |= session_not_found ? 0 : CNAT_TRACE_SESSION_FOUND;
+ cnat_add_trace (vm, node, b, session, NULL, trace_flags);
}
return next0;
}
@@ -183,9 +154,9 @@ VLIB_NODE_FN (cnat_snat_ip4_node) (vlib_main_t * vm,
{
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
return cnat_node_inline (vm, node, frame, cnat_snat_node_fn, AF_IP4,
- 1 /* do_trace */ );
+ CNAT_LOCATION_FIB, 1 /* do_trace */);
return cnat_node_inline (vm, node, frame, cnat_snat_node_fn, AF_IP4,
- 0 /* do_trace */ );
+ CNAT_LOCATION_FIB, 0 /* do_trace */);
}
VLIB_NODE_FN (cnat_snat_ip6_node) (vlib_main_t * vm,
@@ -194,56 +165,47 @@ VLIB_NODE_FN (cnat_snat_ip6_node) (vlib_main_t * vm,
{
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
return cnat_node_inline (vm, node, frame, cnat_snat_node_fn, AF_IP6,
- 1 /* do_trace */ );
+ CNAT_LOCATION_FIB, 1 /* do_trace */);
return cnat_node_inline (vm, node, frame, cnat_snat_node_fn, AF_IP6,
- 0 /* do_trace */ );
+ CNAT_LOCATION_FIB, 0 /* do_trace */);
}
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (cnat_snat_ip4_node) =
-{
- .name = "ip4-cnat-snat",
+VLIB_REGISTER_NODE (cnat_snat_ip4_node) = {
+ .name = "cnat-snat-ip4",
.vector_size = sizeof (u32),
- .format_trace = format_cnat_snat_trace,
+ .format_trace = format_cnat_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = CNAT_N_ERROR,
.error_strings = cnat_error_strings,
.n_next_nodes = CNAT_SNAT_N_NEXT,
- .next_nodes =
- {
- [CNAT_SNAT_NEXT_DROP] = "ip4-drop",
- }
+ .next_nodes = {
+ [CNAT_SNAT_NEXT_DROP] = "ip4-drop",
+ },
};
-VLIB_REGISTER_NODE (cnat_snat_ip6_node) =
-{
- .name = "ip6-cnat-snat",
+VLIB_REGISTER_NODE (cnat_snat_ip6_node) = {
+ .name = "cnat-snat-ip6",
.vector_size = sizeof (u32),
- .format_trace = format_cnat_snat_trace,
+ .format_trace = format_cnat_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = CNAT_N_ERROR,
.error_strings = cnat_error_strings,
.n_next_nodes = CNAT_SNAT_N_NEXT,
- .next_nodes =
- {
- [CNAT_SNAT_NEXT_DROP] = "ip6-drop",
- }
+ .next_nodes = {
+ [CNAT_SNAT_NEXT_DROP] = "ip6-drop",
+ },
};
-VNET_FEATURE_INIT (cnat_snat_ip4_node, static) =
-{
+VNET_FEATURE_INIT (cnat_snat_ip4_node, static) = {
.arc_name = "ip4-unicast",
- .node_name = "ip4-cnat-snat",
+ .node_name = "cnat-snat-ip4",
};
-VNET_FEATURE_INIT (cnat_snat_ip6_node, static) =
-{
+VNET_FEATURE_INIT (cnat_snat_ip6_node, static) = {
.arc_name = "ip6-unicast",
- .node_name = "ip6-cnat-snat",
+ .node_name = "cnat-snat-ip6",
};
-/* *INDENT-ON* */
-
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/src/plugins/cnat/cnat_node_vip.c b/src/plugins/cnat/cnat_node_vip.c
index 02e6da4c2e9..f653aa1e430 100644
--- a/src/plugins/cnat/cnat_node_vip.c
+++ b/src/plugins/cnat/cnat_node_vip.c
@@ -15,25 +15,9 @@
#include <vlibmemory/api.h>
#include <cnat/cnat_node.h>
-#include <cnat/cnat_translation.h>
#include <cnat/cnat_inline.h>
#include <cnat/cnat_src_policy.h>
-#include <vnet/dpo/load_balance.h>
-#include <vnet/dpo/load_balance_map.h>
-
-#include <vnet/ip/ip4_inlines.h>
-#include <vnet/ip/ip6_inlines.h>
-
-typedef struct cnat_translation_trace_t_
-{
- cnat_session_t session;
- cnat_translation_t tr;
- u32 found_session;
- u32 created_session;
- u32 has_tr;
-} cnat_translation_trace_t;
-
typedef enum cnat_translation_next_t_
{
CNAT_TRANSLATION_NEXT_DROP,
@@ -44,34 +28,14 @@ typedef enum cnat_translation_next_t_
vlib_node_registration_t cnat_vip_ip4_node;
vlib_node_registration_t cnat_vip_ip6_node;
-static u8 *
-format_cnat_translation_trace (u8 * s, va_list * args)
-{
- CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
- CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
- cnat_translation_trace_t *t = va_arg (*args, cnat_translation_trace_t *);
-
- if (t->found_session)
- s = format (s, "found: %U", format_cnat_session, &t->session, 1);
- else if (t->created_session)
- s = format (s, "created: %U\n tr: %U",
- format_cnat_session, &t->session, 1,
- format_cnat_translation, &t->tr, 0);
- else if (t->has_tr)
- s = format (s, "tr pass: %U", format_cnat_translation, &t->tr, 0);
- else
- s = format (s, "not found");
- return s;
-}
-
/* CNat sub for NAT behind a fib entry (VIP or interposed real IP) */
static uword
-cnat_vip_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_buffer_t * b,
- cnat_node_ctx_t * ctx, int rv, cnat_session_t * session)
+cnat_vip_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b,
+ cnat_node_ctx_t *ctx, int session_not_found,
+ cnat_session_t *session)
{
vlib_combined_counter_main_t *cntm = &cnat_translation_counters;
+ cnat_src_policy_main_t *cspm = &cnat_src_policy_main;
const cnat_translation_t *ct = NULL;
ip4_header_t *ip4 = NULL;
ip_protocol_t iproto;
@@ -80,8 +44,9 @@ cnat_vip_node_fn (vlib_main_t * vm,
cnat_client_t *cc;
u16 next0;
index_t cti;
- int created_session = 0;
- cnat_src_policy_main_t *cspm = &cnat_src_policy_main;
+ u8 trace_flags = 0;
+ int rv;
+
if (AF_IP4 == ctx->af)
{
ip4 = vlib_buffer_get_current (b);
@@ -106,7 +71,7 @@ cnat_vip_node_fn (vlib_main_t * vm,
goto trace;
}
- if (!rv)
+ if (!session_not_found)
{
/* session table hit */
cnat_timestamp_update (session->value.cs_ts_index, ctx->now);
@@ -201,16 +166,20 @@ cnat_vip_node_fn (vlib_main_t * vm,
if (rv)
{
if (CNAT_SOURCE_ERROR_EXHAUSTED_PORTS == rv)
- vlib_node_increment_counter (vm, cnat_vip_ip4_node.index,
- CNAT_ERROR_EXHAUSTED_PORTS, 1);
+ {
+ vlib_node_registration_t *node =
+ (AF_IP4 == ctx->af) ? &cnat_vip_ip4_node : &cnat_vip_ip6_node;
+ vlib_node_increment_counter (vm, node->index,
+ CNAT_ERROR_EXHAUSTED_PORTS, 1);
+ }
next0 = CNAT_TRANSLATION_NEXT_DROP;
goto trace;
}
/* refcnt session in current client */
cnat_client_cnt_session (cc);
- cnat_session_create (session, ctx, rsession_flags);
- created_session = 1;
+ cnat_session_create (session, ctx, CNAT_LOCATION_FIB, rsession_flags);
+ trace_flags |= CNAT_TRACE_SESSION_CREATED;
next0 = ct->ct_lb.dpoi_next_node;
vnet_buffer (b)->ip.adj_index[VLIB_TX] = session->value.cs_lbi;
@@ -231,17 +200,8 @@ cnat_vip_node_fn (vlib_main_t * vm,
trace:
if (PREDICT_FALSE (ctx->do_trace))
{
- cnat_translation_trace_t *t;
-
- t = vlib_add_trace (vm, node, b, sizeof (*t));
-
- t->found_session = !rv;
- t->created_session = created_session;
- if (t->found_session || t->created_session)
- clib_memcpy (&t->session, session, sizeof (t->session));
- t->has_tr = (NULL != ct);
- if (t->has_tr)
- clib_memcpy (&t->tr, ct, sizeof (cnat_translation_t));
+ trace_flags |= session_not_found ? 0 : CNAT_TRACE_SESSION_FOUND;
+ cnat_add_trace (vm, node, b, session, ct, trace_flags);
}
return next0;
}
@@ -252,9 +212,9 @@ VLIB_NODE_FN (cnat_vip_ip4_node) (vlib_main_t * vm,
{
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
return cnat_node_inline (vm, node, frame, cnat_vip_node_fn, AF_IP4,
- 1 /* do_trace */ );
+ CNAT_LOCATION_FIB, 1 /* do_trace */);
return cnat_node_inline (vm, node, frame, cnat_vip_node_fn, AF_IP4,
- 0 /* do_trace */ );
+ CNAT_LOCATION_FIB, 0 /* do_trace */);
}
VLIB_NODE_FN (cnat_vip_ip6_node) (vlib_main_t * vm,
@@ -263,17 +223,16 @@ VLIB_NODE_FN (cnat_vip_ip6_node) (vlib_main_t * vm,
{
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
return cnat_node_inline (vm, node, frame, cnat_vip_node_fn, AF_IP6,
- 1 /* do_trace */ );
+ CNAT_LOCATION_FIB, 1 /* do_trace */);
return cnat_node_inline (vm, node, frame, cnat_vip_node_fn, AF_IP6,
- 0 /* do_trace */ );
+ CNAT_LOCATION_FIB, 0 /* do_trace */);
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (cnat_vip_ip4_node) =
{
.name = "ip4-cnat-tx",
.vector_size = sizeof (u32),
- .format_trace = format_cnat_translation_trace,
+ .format_trace = format_cnat_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = 0,
.n_next_nodes = CNAT_TRANSLATION_N_NEXT,
@@ -281,13 +240,13 @@ VLIB_REGISTER_NODE (cnat_vip_ip4_node) =
{
[CNAT_TRANSLATION_NEXT_DROP] = "ip4-drop",
[CNAT_TRANSLATION_NEXT_LOOKUP] = "ip4-lookup",
- }
+ },
};
VLIB_REGISTER_NODE (cnat_vip_ip6_node) =
{
.name = "ip6-cnat-tx",
.vector_size = sizeof (u32),
- .format_trace = format_cnat_translation_trace,
+ .format_trace = format_cnat_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = 0,
.n_next_nodes = CNAT_TRANSLATION_N_NEXT,
@@ -295,9 +254,8 @@ VLIB_REGISTER_NODE (cnat_vip_ip6_node) =
{
[CNAT_TRANSLATION_NEXT_DROP] = "ip6-drop",
[CNAT_TRANSLATION_NEXT_LOOKUP] = "ip6-lookup",
- }
+ },
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/plugins/cnat/cnat_scanner.c b/src/plugins/cnat/cnat_scanner.c
index d0ed5e318a3..b3591f7e8b0 100644
--- a/src/plugins/cnat/cnat_scanner.c
+++ b/src/plugins/cnat/cnat_scanner.c
@@ -58,13 +58,11 @@ cnat_scanner_process (vlib_main_t * vm,
return 0;
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (cnat_scanner_process_node) = {
.function = cnat_scanner_process,
.type = VLIB_NODE_TYPE_PROCESS,
.name = "cnat-scanner-process",
};
-/* *INDENT-ON* */
static clib_error_t *
cnat_scanner_cmd (vlib_main_t * vm,
@@ -89,13 +87,11 @@ cnat_scanner_cmd (vlib_main_t * vm,
return (NULL);
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cnat_scanner_cmd_node, static) = {
.path = "test cnat scanner",
.function = cnat_scanner_cmd,
.short_help = "test cnat scanner",
};
-/* *INDENT-ON* */
static clib_error_t *
cnat_scanner_init (vlib_main_t * vm)
diff --git a/src/plugins/cnat/cnat_session.c b/src/plugins/cnat/cnat_session.c
index c3d8aa7eb3d..bb04de07c82 100644
--- a/src/plugins/cnat/cnat_session.c
+++ b/src/plugins/cnat/cnat_session.c
@@ -20,8 +20,7 @@
#include <vppinfra/bihash_template.h>
#include <vppinfra/bihash_template.c>
-
-clib_bihash_40_48_t cnat_session_db;
+cnat_bihash_t cnat_session_db;
void (*cnat_free_port_cb) (u16 port, ip_protocol_t iproto);
typedef struct cnat_session_walk_ctx_t_
@@ -54,7 +53,7 @@ cnat_session_walk (cnat_session_walk_cb_t cb, void *ctx)
typedef struct cnat_session_purge_walk_t_
{
- clib_bihash_kv_40_48_t *keys;
+ cnat_bihash_kv_t *keys;
} cnat_session_purge_walk_ctx_t;
static int
@@ -68,6 +67,28 @@ cnat_session_purge_walk (BVT (clib_bihash_kv) * key, void *arg)
}
u8 *
+format_cnat_session_location (u8 *s, va_list *args)
+{
+ u8 location = va_arg (*args, int);
+ switch (location)
+ {
+ case CNAT_LOCATION_INPUT:
+ s = format (s, "input");
+ break;
+ case CNAT_LOCATION_OUTPUT:
+ s = format (s, "output");
+ break;
+ case CNAT_LOCATION_FIB:
+ s = format (s, "fib");
+ break;
+ default:
+ s = format (s, "unknown");
+ break;
+ }
+ return (s);
+}
+
+u8 *
format_cnat_session (u8 * s, va_list * args)
{
cnat_session_t *sess = va_arg (*args, cnat_session_t *);
@@ -76,19 +97,17 @@ format_cnat_session (u8 * s, va_list * args)
if (!pool_is_free_index (cnat_timestamps, sess->value.cs_ts_index))
ts = cnat_timestamp_exp (sess->value.cs_ts_index);
- s =
- format (s,
- "session:[%U;%d -> %U;%d, %U] => %U;%d -> %U;%d lb:%d age:%f",
- format_ip46_address, &sess->key.cs_ip[VLIB_RX], IP46_TYPE_ANY,
- clib_host_to_net_u16 (sess->key.cs_port[VLIB_RX]),
- format_ip46_address, &sess->key.cs_ip[VLIB_TX], IP46_TYPE_ANY,
- clib_host_to_net_u16 (sess->key.cs_port[VLIB_TX]),
- format_ip_protocol, sess->key.cs_proto, format_ip46_address,
- &sess->value.cs_ip[VLIB_RX], IP46_TYPE_ANY,
- clib_host_to_net_u16 (sess->value.cs_port[VLIB_RX]),
- format_ip46_address, &sess->value.cs_ip[VLIB_TX], IP46_TYPE_ANY,
- clib_host_to_net_u16 (sess->value.cs_port[VLIB_TX]),
- sess->value.cs_lbi, ts);
+ s = format (
+ s, "session:[%U;%d -> %U;%d, %U] => %U;%d -> %U;%d %U lb:%d age:%f",
+ format_ip46_address, &sess->key.cs_ip[VLIB_RX], IP46_TYPE_ANY,
+ clib_host_to_net_u16 (sess->key.cs_port[VLIB_RX]), format_ip46_address,
+ &sess->key.cs_ip[VLIB_TX], IP46_TYPE_ANY,
+ clib_host_to_net_u16 (sess->key.cs_port[VLIB_TX]), format_ip_protocol,
+ sess->key.cs_proto, format_ip46_address, &sess->value.cs_ip[VLIB_RX],
+ IP46_TYPE_ANY, clib_host_to_net_u16 (sess->value.cs_port[VLIB_RX]),
+ format_ip46_address, &sess->value.cs_ip[VLIB_TX], IP46_TYPE_ANY,
+ clib_host_to_net_u16 (sess->value.cs_port[VLIB_TX]),
+ format_cnat_session_location, sess->key.cs_loc, sess->value.cs_lbi, ts);
return (s);
}
@@ -114,19 +133,17 @@ cnat_session_show (vlib_main_t * vm,
return (NULL);
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cnat_session_show_cmd_node, static) = {
.path = "show cnat session",
.function = cnat_session_show,
.short_help = "show cnat session",
.is_mp_safe = 1,
};
-/* *INDENT-ON* */
void
cnat_session_free (cnat_session_t * session)
{
- clib_bihash_kv_40_48_t *bkey = (clib_bihash_kv_40_48_t *) session;
+ cnat_bihash_kv_t *bkey = (cnat_bihash_kv_t *) session;
/* age it */
if (session->value.flags & CNAT_SESSION_FLAG_ALLOC_PORT)
cnat_free_port_cb (session->value.cs_port[VLIB_RX],
@@ -135,7 +152,7 @@ cnat_session_free (cnat_session_t * session)
cnat_client_free_by_ip (&session->key.cs_ip[VLIB_TX], session->key.cs_af);
cnat_timestamp_free (session->value.cs_ts_index);
- clib_bihash_add_del_40_48 (&cnat_session_db, bkey, 0 /* is_add */ );
+ cnat_bihash_add_del (&cnat_session_db, bkey, 0 /* is_add */);
}
int
@@ -143,7 +160,7 @@ cnat_session_purge (void)
{
/* flush all the session from the DB */
cnat_session_purge_walk_ctx_t ctx = { };
- clib_bihash_kv_40_48_t *key;
+ cnat_bihash_kv_t *key;
BV (clib_bihash_foreach_key_value_pair) (&cnat_session_db,
cnat_session_purge_walk, &ctx);
@@ -242,25 +259,22 @@ cnat_timestamp_show (vlib_main_t * vm,
{
cnat_timestamp_t *ts;
clib_rwlock_reader_lock (&cnat_main.ts_lock);
- /* *INDENT-OFF* */
- pool_foreach (ts, cnat_timestamps) {
- vlib_cli_output (vm, "[%d] last_seen:%f lifetime:%u ref:%u",
- ts - cnat_timestamps,
- ts->last_seen, ts->lifetime, ts->refcnt);
- }
- /* *INDENT-ON* */
+ pool_foreach (ts, cnat_timestamps)
+ {
+ vlib_cli_output (vm, "[%d] last_seen:%f lifetime:%u ref:%u",
+ ts - cnat_timestamps, ts->last_seen, ts->lifetime,
+ ts->refcnt);
+ }
clib_rwlock_reader_unlock (&cnat_main.ts_lock);
return (NULL);
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cnat_timestamp_show_cmd, static) = {
.path = "show cnat timestamp",
.function = cnat_timestamp_show,
.short_help = "show cnat timestamp",
.is_mp_safe = 1,
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/plugins/cnat/cnat_session.h b/src/plugins/cnat/cnat_session.h
index fba28e5a241..540a2f29409 100644
--- a/src/plugins/cnat/cnat_session.h
+++ b/src/plugins/cnat/cnat_session.h
@@ -20,8 +20,7 @@
#include <cnat/cnat_types.h>
#include <cnat/cnat_client.h>
-#include <cnat/bihash_40_48.h>
-
+#include <cnat/cnat_bihash.h>
/**
* A session represents the memory of a translation.
@@ -63,9 +62,11 @@ typedef struct cnat_session_t_
u8 cs_af;
/**
- * spare space
+ * input / output / fib session
*/
- u8 __cs_pad[2];
+ u8 cs_loc;
+
+ u8 __cs_pad;
} key;
/**
* this value sits in the same memory location a 'value' in the bihash kvp
@@ -88,22 +89,21 @@ typedef struct cnat_session_t_
index_t cs_lbi;
/**
+ * Persist translation->ct_lb.dpoi_next_node
+ */
+ u32 dpoi_next_node;
+
+ /**
* Timestamp index this session was last used
*/
u32 cs_ts_index;
- union
- {
- /**
- * session flags if cs_lbi == INDEX_INVALID
- */
- u32 flags;
- /**
- * Persist translation->ct_lb.dpoi_next_node
- * when cs_lbi != INDEX_INVALID
- */
- u32 dpoi_next_node;
- };
+ /**
+ * session flags
+ */
+ u32 flags;
+
+ u32 __pad;
} value;
} cnat_session_t;
@@ -124,24 +124,31 @@ typedef enum cnat_session_flag_t_
CNAT_SESSION_FLAG_NO_CLIENT = (1 << 2),
} cnat_session_flag_t;
+typedef enum cnat_session_location_t_
+{
+ CNAT_LOCATION_INPUT = 0,
+ CNAT_LOCATION_OUTPUT = 1,
+ CNAT_LOCATION_FIB = 0xff,
+} cnat_session_location_t;
+
extern u8 *format_cnat_session (u8 * s, va_list * args);
/**
* Ensure the session object correctly overlays the bihash key/value pair
*/
STATIC_ASSERT (STRUCT_OFFSET_OF (cnat_session_t, key) ==
- STRUCT_OFFSET_OF (clib_bihash_kv_40_48_t, key),
+ STRUCT_OFFSET_OF (cnat_bihash_kv_t, key),
"key overlaps");
STATIC_ASSERT (STRUCT_OFFSET_OF (cnat_session_t, value) ==
- STRUCT_OFFSET_OF (clib_bihash_kv_40_48_t, value),
+ STRUCT_OFFSET_OF (cnat_bihash_kv_t, value),
"value overlaps");
-STATIC_ASSERT (sizeof (cnat_session_t) == sizeof (clib_bihash_kv_40_48_t),
+STATIC_ASSERT (sizeof (cnat_session_t) == sizeof (cnat_bihash_kv_t),
"session kvp");
/**
* The DB of sessions
*/
-extern clib_bihash_40_48_t cnat_session_db;
+extern cnat_bihash_t cnat_session_db;
/**
* Callback function invoked during a walk of all translations
diff --git a/src/plugins/cnat/cnat_snat.c b/src/plugins/cnat/cnat_snat.c
index 7c799065b57..68b2f2b11bf 100644
--- a/src/plugins/cnat/cnat_snat.c
+++ b/src/plugins/cnat/cnat_snat.c
@@ -24,13 +24,11 @@ cnat_compute_prefix_lengths_in_search_order (cnat_snat_pfx_table_t *
int i;
vec_reset_length (table->meta[af].prefix_lengths_in_search_order);
/* Note: bitmap reversed so this is in fact a longest prefix match */
- /* *INDENT-OFF* */
clib_bitmap_foreach (i, table->meta[af].non_empty_dst_address_length_bitmap)
{
int dst_address_length = 128 - i;
vec_add1 (table->meta[af].prefix_lengths_in_search_order, dst_address_length);
}
- /* *INDENT-ON* */
}
int
@@ -220,14 +218,12 @@ done:
return (e);
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cnat_set_snat_command, static) =
{
.path = "cnat snat with",
.short_help = "cnat snat with [<ip4-address>][<ip6-address>][sw_if_index]",
.function = cnat_set_snat_cli,
};
-/* *INDENT-ON* */
static clib_error_t *
cnat_snat_exclude (vlib_main_t * vm,
@@ -261,14 +257,12 @@ cnat_snat_exclude (vlib_main_t * vm,
return (NULL);
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cnat_snat_exclude_command, static) =
{
.path = "cnat snat exclude",
.short_help = "cnat snat exclude [ip]",
.function = cnat_snat_exclude,
};
-/* *INDENT-ON* */
static clib_error_t *
cnat_show_snat (vlib_main_t * vm,
@@ -283,20 +277,18 @@ cnat_show_snat (vlib_main_t * vm,
return (NULL);
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cnat_show_snat_command, static) =
{
.path = "show cnat snat",
.short_help = "show cnat snat",
.function = cnat_show_snat,
};
-/* *INDENT-ON* */
static clib_error_t *
cnat_snat_init (vlib_main_t * vm)
{
- cnat_snat_pfx_table_t *table = &cnat_main.snat_pfx_table;
cnat_main_t *cm = &cnat_main;
+ cnat_snat_pfx_table_t *table = &cm->snat_pfx_table;
int i;
for (i = 0; i < ARRAY_LEN (table->ip_masks); i++)
{
diff --git a/src/plugins/cnat/cnat_translation.c b/src/plugins/cnat/cnat_translation.c
index 9a1cc8bbc0b..65c44d80b19 100644
--- a/src/plugins/cnat/cnat_translation.c
+++ b/src/plugins/cnat/cnat_translation.c
@@ -68,13 +68,12 @@ cnat_translation_unwatch_addr (u32 cti, cnat_addr_resol_type_t type)
/* Delete tr resolution entries matching translation index */
addr_resolution_t *ar;
index_t *indexes = 0, *ari;
- /* *INDENT-OFF* */
- pool_foreach (ar, tr_resolutions) {
- if ((cti == INDEX_INVALID || ar->cti == cti) &&
- (ar->type == type || CNAT_RESOLV_ADDR_ANY == type))
- vec_add1(indexes, ar - tr_resolutions);
- }
- /* *INDENT-ON* */
+ pool_foreach (ar, tr_resolutions)
+ {
+ if ((cti == INDEX_INVALID || ar->cti == cti) &&
+ (ar->type == type || CNAT_RESOLV_ADDR_ANY == type))
+ vec_add1 (indexes, ar - tr_resolutions);
+ }
vec_foreach (ari, indexes) pool_put_index (tr_resolutions, *ari);
vec_free (indexes);
@@ -84,7 +83,7 @@ static void
cnat_tracker_release (cnat_ep_trk_t * trk)
{
/* We only track fully resolved endpoints */
- if (!trk->is_active)
+ if (!(trk->ct_flags & CNAT_TRK_ACTIVE))
return;
fib_entry_untrack (trk->ct_fei, trk->ct_sibling);
}
@@ -94,10 +93,14 @@ cnat_tracker_track (index_t cti, cnat_ep_trk_t * trk)
{
fib_prefix_t pfx;
/* We only track fully resolved endpoints */
- trk->is_active = trk->ct_ep[VLIB_TX].ce_flags & CNAT_EP_FLAG_RESOLVED
- && trk->ct_ep[VLIB_RX].ce_flags & CNAT_EP_FLAG_RESOLVED;
- if (!trk->is_active)
- return;
+ if (trk->ct_ep[VLIB_TX].ce_flags & CNAT_EP_FLAG_RESOLVED &&
+ trk->ct_ep[VLIB_RX].ce_flags & CNAT_EP_FLAG_RESOLVED)
+ trk->ct_flags |= CNAT_TRK_ACTIVE;
+ else
+ {
+ trk->ct_flags &= ~CNAT_TRK_ACTIVE;
+ return;
+ }
ip_address_to_fib_prefix (&trk->ct_ep[VLIB_TX].ce_ip, &pfx);
trk->ct_fei = fib_entry_track (CNAT_FIB_TABLE,
@@ -186,14 +189,17 @@ cnat_translation_stack (cnat_translation_t * ct)
fproto = ip_address_family_to_fib_proto (ct->ct_vip.ce_ip.version);
dproto = fib_proto_to_dpo (fproto);
- vec_foreach (trk, ct->ct_paths) if (trk->is_active)
- ep_idx++;
+ vec_reset_length (ct->ct_active_paths);
- lbi = load_balance_create (ep_idx, fib_proto_to_dpo (fproto),
- IP_FLOW_HASH_DEFAULT);
+ vec_foreach (trk, ct->ct_paths)
+ if (trk->ct_flags & CNAT_TRK_ACTIVE)
+ vec_add1 (ct->ct_active_paths, *trk);
+
+ lbi = load_balance_create (vec_len (ct->ct_active_paths),
+ fib_proto_to_dpo (fproto), IP_FLOW_HASH_DEFAULT);
ep_idx = 0;
- vec_foreach (trk, ct->ct_paths) if (trk->is_active)
+ vec_foreach (trk, ct->ct_active_paths)
load_balance_set_bucket (lbi, ep_idx++, &trk->ct_dpo);
dpo_set (&ct->ct_lb, DPO_LOAD_BALANCE, dproto, lbi);
@@ -214,7 +220,8 @@ cnat_translation_delete (u32 id)
dpo_reset (&ct->ct_lb);
- vec_foreach (trk, ct->ct_paths) cnat_tracker_release (trk);
+ vec_foreach (trk, ct->ct_active_paths)
+ cnat_tracker_release (trk);
cnat_remove_translation_from_db (ct->ct_cci, &ct->ct_vip, ct->ct_proto);
cnat_client_translation_deleted (ct->ct_cci);
@@ -312,13 +319,11 @@ cnat_translation_walk (cnat_translation_walk_cb_t cb, void *ctx)
{
u32 api;
- /* *INDENT-OFF* */
pool_foreach_index (api, cnat_translation_pool)
{
if (!cb(api, ctx))
break;
}
- /* *INDENT-ON* */
}
static u8 *
@@ -380,13 +385,11 @@ cnat_translation_show (vlib_main_t * vm,
if (INDEX_INVALID == cti)
{
- /* *INDENT-OFF* */
pool_foreach_index (cti, cnat_translation_pool)
{
ct = pool_elt_at_index (cnat_translation_pool, cti);
vlib_cli_output(vm, "%U", format_cnat_translation, ct);
}
- /* *INDENT-ON* */
}
else
{
@@ -402,12 +405,10 @@ cnat_translation_purge (void)
/* purge all the translations */
index_t tri, *trp, *trs = NULL;
- /* *INDENT-OFF* */
pool_foreach_index (tri, cnat_translation_pool)
{
vec_add1(trs, tri);
}
- /* *INDENT-ON* */
vec_foreach (trp, trs) cnat_translation_delete (*trp);
@@ -418,14 +419,12 @@ cnat_translation_purge (void)
return (0);
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cnat_translation_show_cmd_node, static) = {
.path = "show cnat translation",
.function = cnat_translation_show,
.short_help = "show cnat translation <VIP>",
.is_mp_safe = 1,
};
-/* *INDENT-ON* */
static fib_node_t *
cnat_translation_get_node (fib_node_index_t index)
@@ -533,14 +532,12 @@ done:
return (e);
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cnat_translation_cli_add_del_command, static) =
{
.path = "cnat translation",
.short_help = "cnat translation [add|del] proto [TCP|UDP] [vip|real] [ip|sw_if_index [v6]] [port] [to [ip|sw_if_index [v6]] [port]->[ip|sw_if_index [v6]] [port]]",
.function = cnat_translation_cli_add_del,
};
-/* *INDENT-ON* */
static void
cnat_if_addr_add_del_translation_cb (addr_resolution_t * ar,
@@ -648,15 +645,14 @@ cnat_if_addr_add_del_callback (u32 sw_if_index, ip_address_t * address,
u8 is_del)
{
addr_resolution_t *ar;
- /* *INDENT-OFF* */
- pool_foreach (ar, tr_resolutions) {
- if (ar->sw_if_index != sw_if_index)
- continue;
- if (ar->af != ip_addr_version (address))
- continue;
- cnat_if_addr_add_cbs[ar->type] (ar, address, is_del);
- }
- /* *INDENT-ON* */
+ pool_foreach (ar, tr_resolutions)
+ {
+ if (ar->sw_if_index != sw_if_index)
+ continue;
+ if (ar->af != ip_addr_version (address))
+ continue;
+ cnat_if_addr_add_cbs[ar->type](ar, address, is_del);
+ }
}
static void
diff --git a/src/plugins/cnat/cnat_translation.h b/src/plugins/cnat/cnat_translation.h
index 7a035814544..8bec7396050 100644
--- a/src/plugins/cnat/cnat_translation.h
+++ b/src/plugins/cnat/cnat_translation.h
@@ -25,6 +25,11 @@
*/
extern vlib_combined_counter_main_t cnat_translation_counters;
+typedef enum cnat_trk_flag_t_
+{
+ CNAT_TRK_ACTIVE = (1 << 0),
+} cnat_trk_flag_t;
+
/**
* Data used to track an EP in the FIB
*/
@@ -53,7 +58,7 @@ typedef struct cnat_ep_trk_t_
/**
* Allows to disable if not resolved yet
*/
- u8 is_active;
+ u8 ct_flags; /* cnat_trk_flag_t */
} cnat_ep_trk_t;
typedef enum cnat_translation_flag_t_
@@ -130,6 +135,11 @@ typedef struct cnat_translation_t_
cnat_ep_trk_t *ct_paths;
/**
+ * The vector of active tracked back-ends
+ */
+ cnat_ep_trk_t *ct_active_paths;
+
+ /**
* The ip protocol for the translation
*/
ip_protocol_t ct_proto;
diff --git a/src/plugins/cnat/cnat_types.h b/src/plugins/cnat/cnat_types.h
index d3b7295f6b4..2c1b7f9be50 100644
--- a/src/plugins/cnat/cnat_types.h
+++ b/src/plugins/cnat/cnat_types.h
@@ -54,7 +54,7 @@
typedef enum
{
/* Endpoint addr has been resolved */
- CNAT_EP_FLAG_RESOLVED = 1,
+ CNAT_EP_FLAG_RESOLVED = (1 << 0),
} cnat_ep_flag_t;
typedef struct cnat_endpoint_t_
diff --git a/src/plugins/cnat/test/test_cnat.py b/src/plugins/cnat/test/test_cnat.py
index 271f5076942..4398a63d5aa 100644
--- a/src/plugins/cnat/test/test_cnat.py
+++ b/src/plugins/cnat/test/test_cnat.py
@@ -563,12 +563,12 @@ class TestCNatSourceNAT(VppTestCase):
self.vapi.feature_enable_disable(
enable=1,
arc_name="ip6-unicast",
- feature_name="ip6-cnat-snat",
+ feature_name="cnat-snat-ip6",
sw_if_index=self.pg0.sw_if_index)
self.vapi.feature_enable_disable(
enable=1,
arc_name="ip4-unicast",
- feature_name="ip4-cnat-snat",
+ feature_name="cnat-snat-ip4",
sw_if_index=self.pg0.sw_if_index)
def tearDown(self):