cnat: fixes & prepare maglev

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>
This commit is contained in:
Nathan Skrzypczak
2021-02-25 11:01:41 +01:00
committed by Florin Coras
parent b80d67ca43
commit 27647a27c7
16 changed files with 391 additions and 367 deletions

View 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;
};

View 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
----------------

View 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

View File

@ -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

View 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",

File diff suppressed because it is too large Load Diff

View 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
*

View File

@ -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

View 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)

View 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

View 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

View 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++)
{

View 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

View File

@ -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_
@ -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
*/

View 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_

View 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):