cnat: fixes & prepare maglev 46/31446/3
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>
Thu, 25 Feb 2021 10:01:41 +0000 (11:01 +0100)
committerFlorin Coras <florin.coras@gmail.com>
Fri, 26 Feb 2021 01:55:07 +0000 (01:55 +0000)
Notable changes:
- ip[46]-cnat-snat is renamed to cnat-snat-ip[46]
- indent fixes
- common trace primitives
- bihash is now 40_56 with alias

Type: refactor

Change-Id: I0a82cfe3b40efd96473e51061d7135ffe412ddfc
Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
16 files changed:
src/plugins/cnat/cnat.api
src/plugins/cnat/cnat.rst
src/plugins/cnat/cnat_api.c
src/plugins/cnat/cnat_bihash.h [moved from src/plugins/cnat/bihash_40_48.h with 66% similarity]
src/plugins/cnat/cnat_client.c
src/plugins/cnat/cnat_node.h
src/plugins/cnat/cnat_node_snat.c
src/plugins/cnat/cnat_node_vip.c
src/plugins/cnat/cnat_scanner.c
src/plugins/cnat/cnat_session.c
src/plugins/cnat/cnat_session.h
src/plugins/cnat/cnat_snat.c
src/plugins/cnat/cnat_translation.c
src/plugins/cnat/cnat_translation.h
src/plugins/cnat/cnat_types.h
src/plugins/cnat/test/test_cnat.py

index 7bf6be8..685f9e1 100644 (file)
@@ -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;
 };
 
index 3cb08bc..8781f40 100644 (file)
@@ -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
 ----------------
index c215caa..1c6ef7b 100644 (file)
@@ -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
similarity index 66%
rename from src/plugins/cnat/bihash_40_48.h
rename to src/plugins/cnat/cnat_bihash.h
index df345ce..a148ad5 100644 (file)
 #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>
 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
index 8beaead..b8fcb9a 100644 (file)
@@ -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",
index e2a9965..56a6c61 100644 (file)
 #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]);
index 8166df6..ef784a6 100644 (file)
@@ -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
  *
index 02e6da4..f653aa1 100644 (file)
 
 #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
index d0ed5e3..b3591f7 100644 (file)
@@ -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)
index c3d8aa7..bb04de0 100644 (file)
@@ -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
@@ -67,6 +66,28 @@ cnat_session_purge_walk (BVT (clib_bihash_kv) * key, void *arg)
   return (BIHASH_WALK_CONTINUE);
 }
 
+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)
 {
@@ -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
index fba28e5..540a2f2 100644 (file)
@@ -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
@@ -87,23 +88,22 @@ 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
index 7c79906..68b2f2b 100644 (file)
@@ -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++)
     {
index 9a1cc8b..65c44d8 100644 (file)
@@ -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
index 7a03581..8bec739 100644 (file)
  */
 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_
@@ -129,6 +134,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
    */
index d3b7295..2c1b7f9 100644 (file)
@@ -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_
index 271f507..4398a63 100644 (file)
@@ -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):