From 27647a27c7b1e800547e3a3ea97b099b25618177 Mon Sep 17 00:00:00 2001 From: Nathan Skrzypczak Date: Thu, 25 Feb 2021 11:01:41 +0100 Subject: 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 --- src/plugins/cnat/bihash_40_48.h | 112 -------------- src/plugins/cnat/cnat.api | 1 + src/plugins/cnat/cnat.rst | 2 +- src/plugins/cnat/cnat_api.c | 7 +- src/plugins/cnat/cnat_bihash.h | 122 ++++++++++++++++ src/plugins/cnat/cnat_client.c | 2 - src/plugins/cnat/cnat_node.h | 283 +++++++++++++++++++++++------------- src/plugins/cnat/cnat_node_snat.c | 100 ++++--------- src/plugins/cnat/cnat_node_vip.c | 94 ++++-------- src/plugins/cnat/cnat_scanner.c | 4 - src/plugins/cnat/cnat_session.c | 74 ++++++---- src/plugins/cnat/cnat_session.h | 47 +++--- src/plugins/cnat/cnat_snat.c | 10 +- src/plugins/cnat/cnat_translation.c | 70 +++++---- src/plugins/cnat/cnat_translation.h | 12 +- src/plugins/cnat/cnat_types.h | 2 +- src/plugins/cnat/test/test_cnat.py | 4 +- 17 files changed, 485 insertions(+), 461 deletions(-) delete mode 100644 src/plugins/cnat/bihash_40_48.h create mode 100644 src/plugins/cnat/cnat_bihash.h (limited to 'src/plugins/cnat') diff --git a/src/plugins/cnat/bihash_40_48.h b/src/plugins/cnat/bihash_40_48.h deleted file mode 100644 index df345cec357..00000000000 --- a/src/plugins/cnat/bihash_40_48.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#undef BIHASH_TYPE -#undef BIHASH_KVP_PER_PAGE -#undef BIHASH_32_64_SVM -#undef BIHASH_ENABLE_STATS -#undef BIHASH_KVP_AT_BUCKET_LEVEL -#undef BIHASH_LAZY_INSTANTIATE -#undef BIHASH_BUCKET_PREFETCH_CACHE_LINES - -#define BIHASH_TYPE _40_48 -#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__ - -#include -#include -#include -#include -#include - -typedef struct -{ - u64 key[5]; - u64 value[6]; -} clib_bihash_kv_40_48_t; - -static inline int -clib_bihash_is_free_40_48 (const clib_bihash_kv_40_48_t * v) -{ - /* Free values are clib_memset to 0xff, check a bit... */ - if (v->key[0] == ~0ULL && v->value[0] == ~0ULL) - return 1; - return 0; -} - -static inline u64 -clib_bihash_hash_40_48 (const clib_bihash_kv_40_48_t * v) -{ -#ifdef clib_crc32c_uses_intrinsics - return clib_crc32c ((u8 *) v->key, 40); -#else - u64 tmp = v->key[0] ^ v->key[1] ^ v->key[2] ^ v->key[3] ^ v->key[4]; - return clib_xxhash (tmp); -#endif -} - -static inline u8 * -format_bihash_kvp_40_48 (u8 * s, va_list * args) -{ - clib_bihash_kv_40_48_t *v = va_arg (*args, clib_bihash_kv_40_48_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]); - return s; -} - -static inline int -clib_bihash_key_compare_40_48 (u64 * a, u64 * b) -{ -#if defined (CLIB_HAVE_VEC512) - u64x8 v; - v = u64x8_load_unaligned (a) ^ u64x8_load_unaligned (b); - return (u64x8_is_zero_mask (v) & 0x1f) == 0; -#elif defined (CLIB_HAVE_VEC256) - u64x4 v = { a[4] ^ b[4], 0, 0, 0 }; - v |= u64x4_load_unaligned (a) ^ u64x4_load_unaligned (b); - return u64x4_is_all_zero (v); -#elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) - u64x2 v = { a[4] ^ b[4], 0 }; - v |= u64x2_load_unaligned (a) ^ u64x2_load_unaligned (b); - v |= u64x2_load_unaligned (a + 2) ^ u64x2_load_unaligned (b + 2); - return u64x2_is_all_zero (v); -#else - return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) - | (a[4] ^ b[4])) == 0; -#endif -} - -#undef __included_bihash_template_h__ -#include - -#endif /* __included_bihash_40_48_h__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ 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/cnat_bihash.h b/src/plugins/cnat/cnat_bihash.h new file mode 100644 index 00000000000..a148ad57682 --- /dev/null +++ b/src/plugins/cnat/cnat_bihash.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef BIHASH_TYPE +#undef BIHASH_KVP_PER_PAGE +#undef BIHASH_32_64_SVM +#undef BIHASH_ENABLE_STATS +#undef BIHASH_KVP_AT_BUCKET_LEVEL +#undef BIHASH_LAZY_INSTANTIATE +#undef BIHASH_BUCKET_PREFETCH_CACHE_LINES + +#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_56_h__ +#define __included_bihash_40_56_h__ + +#include +#include +#include +#include +#include + +typedef struct +{ + u64 key[5]; + u64 value[7]; +} clib_bihash_kv_40_56_t; + +static inline int +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) + return 1; + return 0; +} + +static inline u64 +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); +#else + u64 tmp = v->key[0] ^ v->key[1] ^ v->key[2] ^ v->key[3] ^ v->key[4]; + return clib_xxhash (tmp); +#endif +} + +static inline u8 * +format_bihash_kvp_40_56 (u8 *s, va_list *args) +{ + 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 %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_56 (u64 *a, u64 *b) +{ +#if defined (CLIB_HAVE_VEC512) + u64x8 v; + v = u64x8_load_unaligned (a) ^ u64x8_load_unaligned (b); + return (u64x8_is_zero_mask (v) & 0x1f) == 0; +#elif defined (CLIB_HAVE_VEC256) + u64x4 v = { a[4] ^ b[4], 0, 0, 0 }; + v |= u64x4_load_unaligned (a) ^ u64x4_load_unaligned (b); + return u64x4_is_all_zero (v); +#elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) + u64x2 v = { a[4] ^ b[4], 0 }; + v |= u64x2_load_unaligned (a) ^ u64x2_load_unaligned (b); + v |= u64x2_load_unaligned (a + 2) ^ u64x2_load_unaligned (b + 2); + return u64x2_is_all_zero (v); +#else + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) + | (a[4] ^ b[4])) == 0; +#endif +} + +#undef __included_bihash_template_h__ +#include + +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 + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ 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 +#include +#include + #include #include #include +#include + +#include +#include 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 #include -#include #include #include -#include -#include - -#include -#include - -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 #include - -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 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 #include -#include - +#include /** * 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 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 [][][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 ", .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_ @@ -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 */ 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): -- cgit 1.2.3-korg