summaryrefslogtreecommitdiffstats
path: root/src/plugins/snat
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/snat')
-rw-r--r--src/plugins/snat/in2out.c3454
-rw-r--r--src/plugins/snat/nat64.c858
-rw-r--r--src/plugins/snat/nat64.h322
-rw-r--r--src/plugins/snat/nat64_cli.c983
-rw-r--r--src/plugins/snat/nat64_db.c603
-rw-r--r--src/plugins/snat/nat64_db.h307
-rw-r--r--src/plugins/snat/nat64_doc.md73
-rw-r--r--src/plugins/snat/nat64_in2out.c1118
-rw-r--r--src/plugins/snat/nat64_out2in.c494
-rw-r--r--src/plugins/snat/out2in.c2294
-rw-r--r--src/plugins/snat/snat.api897
-rw-r--r--src/plugins/snat/snat.c2842
-rw-r--r--src/plugins/snat/snat.h541
-rw-r--r--src/plugins/snat/snat_all_api_h.h19
-rw-r--r--src/plugins/snat/snat_api.c1970
-rw-r--r--src/plugins/snat/snat_det.c158
-rw-r--r--src/plugins/snat/snat_det.h196
-rw-r--r--src/plugins/snat/snat_ipfix_logging.c835
-rw-r--r--src/plugins/snat/snat_ipfix_logging.h79
-rw-r--r--src/plugins/snat/snat_msg_enum.h31
-rw-r--r--src/plugins/snat/snat_test.c1167
21 files changed, 0 insertions, 19241 deletions
diff --git a/src/plugins/snat/in2out.c b/src/plugins/snat/in2out.c
deleted file mode 100644
index abe0d9dbe87..00000000000
--- a/src/plugins/snat/in2out.c
+++ /dev/null
@@ -1,3454 +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.
- */
-
-#include <vlib/vlib.h>
-#include <vnet/vnet.h>
-#include <vnet/pg/pg.h>
-#include <vnet/handoff.h>
-
-#include <vnet/ip/ip.h>
-#include <vnet/ethernet/ethernet.h>
-#include <vnet/fib/ip4_fib.h>
-#include <snat/snat.h>
-#include <snat/snat_ipfix_logging.h>
-#include <snat/snat_det.h>
-
-#include <vppinfra/hash.h>
-#include <vppinfra/error.h>
-#include <vppinfra/elog.h>
-
-typedef struct {
- u32 sw_if_index;
- u32 next_index;
- u32 session_index;
- u32 is_slow_path;
-} snat_in2out_trace_t;
-
-typedef struct {
- u32 next_worker_index;
- u8 do_handoff;
-} snat_in2out_worker_handoff_trace_t;
-
-/* packet trace format function */
-static u8 * format_snat_in2out_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 *);
- snat_in2out_trace_t * t = va_arg (*args, snat_in2out_trace_t *);
- char * tag;
-
- tag = t->is_slow_path ? "SNAT_IN2OUT_SLOW_PATH" : "SNAT_IN2OUT_FAST_PATH";
-
- s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag,
- t->sw_if_index, t->next_index, t->session_index);
-
- return s;
-}
-
-static u8 * format_snat_in2out_fast_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 *);
- snat_in2out_trace_t * t = va_arg (*args, snat_in2out_trace_t *);
-
- s = format (s, "SANT_IN2OUT_FAST: sw_if_index %d, next index %d",
- t->sw_if_index, t->next_index);
-
- return s;
-}
-
-static u8 * format_snat_in2out_worker_handoff_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 *);
- snat_in2out_worker_handoff_trace_t * t =
- va_arg (*args, snat_in2out_worker_handoff_trace_t *);
- char * m;
-
- m = t->do_handoff ? "next worker" : "same worker";
- s = format (s, "SNAT_IN2OUT_WORKER_HANDOFF: %s %d", m, t->next_worker_index);
-
- return s;
-}
-
-vlib_node_registration_t snat_in2out_node;
-vlib_node_registration_t snat_in2out_slowpath_node;
-vlib_node_registration_t snat_in2out_fast_node;
-vlib_node_registration_t snat_in2out_worker_handoff_node;
-vlib_node_registration_t snat_det_in2out_node;
-vlib_node_registration_t snat_in2out_output_node;
-vlib_node_registration_t snat_in2out_output_slowpath_node;
-vlib_node_registration_t snat_in2out_output_worker_handoff_node;
-vlib_node_registration_t snat_hairpin_dst_node;
-vlib_node_registration_t snat_hairpin_src_node;
-
-
-#define foreach_snat_in2out_error \
-_(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \
-_(IN2OUT_PACKETS, "Good in2out packets processed") \
-_(OUT_OF_PORTS, "Out of ports") \
-_(BAD_OUTSIDE_FIB, "Outside VRF ID not found") \
-_(BAD_ICMP_TYPE, "unsupported ICMP type") \
-_(NO_TRANSLATION, "No translation")
-
-typedef enum {
-#define _(sym,str) SNAT_IN2OUT_ERROR_##sym,
- foreach_snat_in2out_error
-#undef _
- SNAT_IN2OUT_N_ERROR,
-} snat_in2out_error_t;
-
-static char * snat_in2out_error_strings[] = {
-#define _(sym,string) string,
- foreach_snat_in2out_error
-#undef _
-};
-
-typedef enum {
- SNAT_IN2OUT_NEXT_LOOKUP,
- SNAT_IN2OUT_NEXT_DROP,
- SNAT_IN2OUT_NEXT_ICMP_ERROR,
- SNAT_IN2OUT_NEXT_SLOW_PATH,
- SNAT_IN2OUT_N_NEXT,
-} snat_in2out_next_t;
-
-typedef enum {
- SNAT_HAIRPIN_SRC_NEXT_DROP,
- SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT,
- SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH,
- SNAT_HAIRPIN_SRC_NEXT_INTERFACE_OUTPUT,
- SNAT_HAIRPIN_SRC_N_NEXT,
-} snat_hairpin_next_t;
-
-/**
- * @brief Check if packet should be translated
- *
- * Packets aimed at outside interface and external addresss with active session
- * should be translated.
- *
- * @param sm SNAT main
- * @param rt SNAT runtime data
- * @param sw_if_index0 index of the inside interface
- * @param ip0 IPv4 header
- * @param proto0 SNAT protocol
- * @param rx_fib_index0 RX FIB index
- *
- * @returns 0 if packet should be translated otherwise 1
- */
-static inline int
-snat_not_translate_fast (snat_main_t * sm, vlib_node_runtime_t *node,
- u32 sw_if_index0, ip4_header_t * ip0, u32 proto0,
- u32 rx_fib_index0)
-{
- fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
- fib_prefix_t pfx = {
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_len = 32,
- .fp_addr = {
- .ip4.as_u32 = ip0->dst_address.as_u32,
- },
- };
-
- /* Don't NAT packet aimed at the intfc address */
- if (PREDICT_FALSE(is_interface_addr(sm, node, sw_if_index0,
- ip0->dst_address.as_u32)))
- return 1;
-
- fei = fib_table_lookup (rx_fib_index0, &pfx);
- if (FIB_NODE_INDEX_INVALID != fei)
- {
- u32 sw_if_index = fib_entry_get_resolving_interface (fei);
- if (sw_if_index == ~0)
- {
- fei = fib_table_lookup (sm->outside_fib_index, &pfx);
- if (FIB_NODE_INDEX_INVALID != fei)
- sw_if_index = fib_entry_get_resolving_interface (fei);
- }
- snat_interface_t *i;
- pool_foreach (i, sm->interfaces,
- ({
- /* NAT packet aimed at outside interface */
- if ((i->is_inside == 0) && (sw_if_index == i->sw_if_index))
- return 0;
- }));
- }
-
- return 1;
-}
-
-static inline int
-snat_not_translate (snat_main_t * sm, vlib_node_runtime_t *node,
- u32 sw_if_index0, ip4_header_t * ip0, u32 proto0,
- u32 rx_fib_index0)
-{
- udp_header_t * udp0 = ip4_next_header (ip0);
- snat_session_key_t key0, sm0;
- clib_bihash_kv_8_8_t kv0, value0;
-
- key0.addr = ip0->dst_address;
- key0.port = udp0->dst_port;
- key0.protocol = proto0;
- key0.fib_index = sm->outside_fib_index;
- kv0.key = key0.as_u64;
-
- /* NAT packet aimed at external address if */
- /* has active sessions */
- if (clib_bihash_search_8_8 (&sm->out2in, &kv0, &value0))
- {
- /* or is static mappings */
- if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0))
- return 0;
- }
- else
- return 0;
-
- return snat_not_translate_fast(sm, node, sw_if_index0, ip0, proto0,
- rx_fib_index0);
-}
-
-static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0,
- ip4_header_t * ip0,
- u32 rx_fib_index0,
- snat_session_key_t * key0,
- snat_session_t ** sessionp,
- vlib_node_runtime_t * node,
- u32 next0,
- u32 thread_index)
-{
- snat_user_t *u;
- snat_user_key_t user_key;
- snat_session_t *s;
- clib_bihash_kv_8_8_t kv0, value0;
- u32 oldest_per_user_translation_list_index;
- dlist_elt_t * oldest_per_user_translation_list_elt;
- dlist_elt_t * per_user_translation_list_elt;
- dlist_elt_t * per_user_list_head_elt;
- u32 session_index;
- snat_session_key_t key1;
- u32 address_index = ~0;
- u32 outside_fib_index;
- uword * p;
- snat_worker_key_t worker_by_out_key;
-
- p = hash_get (sm->ip4_main->fib_index_by_table_id, sm->outside_vrf_id);
- if (! p)
- {
- b0->error = node->errors[SNAT_IN2OUT_ERROR_BAD_OUTSIDE_FIB];
- return SNAT_IN2OUT_NEXT_DROP;
- }
- outside_fib_index = p[0];
-
- key1.protocol = key0->protocol;
- user_key.addr = ip0->src_address;
- user_key.fib_index = rx_fib_index0;
- kv0.key = user_key.as_u64;
-
- /* Ever heard of the "user" = src ip4 address before? */
- if (clib_bihash_search_8_8 (&sm->user_hash, &kv0, &value0))
- {
- /* no, make a new one */
- pool_get (sm->per_thread_data[thread_index].users, u);
- memset (u, 0, sizeof (*u));
- u->addr = ip0->src_address;
- u->fib_index = rx_fib_index0;
-
- pool_get (sm->per_thread_data[thread_index].list_pool, per_user_list_head_elt);
-
- u->sessions_per_user_list_head_index = per_user_list_head_elt -
- sm->per_thread_data[thread_index].list_pool;
-
- clib_dlist_init (sm->per_thread_data[thread_index].list_pool,
- u->sessions_per_user_list_head_index);
-
- kv0.value = u - sm->per_thread_data[thread_index].users;
-
- /* add user */
- clib_bihash_add_del_8_8 (&sm->user_hash, &kv0, 1 /* is_add */);
- }
- else
- {
- u = pool_elt_at_index (sm->per_thread_data[thread_index].users,
- value0.value);
- }
-
- /* Over quota? Recycle the least recently used dynamic translation */
- if (u->nsessions >= sm->max_translations_per_user)
- {
- /* Remove the oldest dynamic translation */
- do {
- oldest_per_user_translation_list_index =
- clib_dlist_remove_head (sm->per_thread_data[thread_index].list_pool,
- u->sessions_per_user_list_head_index);
-
- ASSERT (oldest_per_user_translation_list_index != ~0);
-
- /* add it back to the end of the LRU list */
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- u->sessions_per_user_list_head_index,
- oldest_per_user_translation_list_index);
- /* Get the list element */
- oldest_per_user_translation_list_elt =
- pool_elt_at_index (sm->per_thread_data[thread_index].list_pool,
- oldest_per_user_translation_list_index);
-
- /* Get the session index from the list element */
- session_index = oldest_per_user_translation_list_elt->value;
-
- /* Get the session */
- s = pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
- session_index);
- } while (snat_is_session_static (s));
-
- if (snat_is_unk_proto_session (s))
- {
- clib_bihash_kv_16_8_t up_kv;
- snat_unk_proto_ses_key_t key;
-
- /* Remove from lookup tables */
- key.l_addr = s->in2out.addr;
- key.r_addr = s->ext_host_addr;
- key.fib_index = s->in2out.fib_index;
- key.proto = s->in2out.port;
- up_kv.key[0] = key.as_u64[0];
- up_kv.key[1] = key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->in2out_unk_proto, &up_kv, 0))
- clib_warning ("in2out key del failed");
-
- key.l_addr = s->out2in.addr;
- key.fib_index = s->out2in.fib_index;
- up_kv.key[0] = key.as_u64[0];
- up_kv.key[1] = key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->out2in_unk_proto, &up_kv, 0))
- clib_warning ("out2in key del failed");
- }
- else
- {
- /* Remove in2out, out2in keys */
- kv0.key = s->in2out.as_u64;
- if (clib_bihash_add_del_8_8 (&sm->in2out, &kv0, 0 /* is_add */))
- clib_warning ("in2out key delete failed");
- kv0.key = s->out2in.as_u64;
- if (clib_bihash_add_del_8_8 (&sm->out2in, &kv0, 0 /* is_add */))
- clib_warning ("out2in key delete failed");
-
- /* log NAT event */
- snat_ipfix_logging_nat44_ses_delete(s->in2out.addr.as_u32,
- s->out2in.addr.as_u32,
- s->in2out.protocol,
- s->in2out.port,
- s->out2in.port,
- s->in2out.fib_index);
-
- snat_free_outside_address_and_port
- (sm, &s->out2in, s->outside_address_index);
- }
- s->outside_address_index = ~0;
-
- if (snat_alloc_outside_address_and_port (sm, rx_fib_index0, thread_index,
- &key1, &address_index))
- {
- ASSERT(0);
-
- b0->error = node->errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
- return SNAT_IN2OUT_NEXT_DROP;
- }
- s->outside_address_index = address_index;
- }
- else
- {
- u8 static_mapping = 1;
-
- /* First try to match static mapping by local address and port */
- if (snat_static_mapping_match (sm, *key0, &key1, 0, 0))
- {
- static_mapping = 0;
- /* Try to create dynamic translation */
- if (snat_alloc_outside_address_and_port (sm, rx_fib_index0,
- thread_index, &key1,
- &address_index))
- {
- b0->error = node->errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
- return SNAT_IN2OUT_NEXT_DROP;
- }
- }
-
- /* Create a new session */
- pool_get (sm->per_thread_data[thread_index].sessions, s);
- memset (s, 0, sizeof (*s));
-
- s->outside_address_index = address_index;
-
- if (static_mapping)
- {
- u->nstaticsessions++;
- s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
- }
- else
- {
- u->nsessions++;
- }
-
- /* Create list elts */
- pool_get (sm->per_thread_data[thread_index].list_pool,
- per_user_translation_list_elt);
- clib_dlist_init (sm->per_thread_data[thread_index].list_pool,
- per_user_translation_list_elt -
- sm->per_thread_data[thread_index].list_pool);
-
- per_user_translation_list_elt->value =
- s - sm->per_thread_data[thread_index].sessions;
- s->per_user_index = per_user_translation_list_elt -
- sm->per_thread_data[thread_index].list_pool;
- s->per_user_list_head_index = u->sessions_per_user_list_head_index;
-
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s->per_user_list_head_index,
- per_user_translation_list_elt -
- sm->per_thread_data[thread_index].list_pool);
- }
-
- s->in2out = *key0;
- s->out2in = key1;
- s->out2in.protocol = key0->protocol;
- s->out2in.fib_index = outside_fib_index;
- s->ext_host_addr.as_u32 = ip0->dst_address.as_u32;
- *sessionp = s;
-
- /* Add to translation hashes */
- kv0.key = s->in2out.as_u64;
- kv0.value = s - sm->per_thread_data[thread_index].sessions;
- if (clib_bihash_add_del_8_8 (&sm->in2out, &kv0, 1 /* is_add */))
- clib_warning ("in2out key add failed");
-
- kv0.key = s->out2in.as_u64;
- kv0.value = s - sm->per_thread_data[thread_index].sessions;
-
- if (clib_bihash_add_del_8_8 (&sm->out2in, &kv0, 1 /* is_add */))
- clib_warning ("out2in key add failed");
-
- /* Add to translated packets worker lookup */
- worker_by_out_key.addr = s->out2in.addr;
- worker_by_out_key.port = s->out2in.port;
- worker_by_out_key.fib_index = s->out2in.fib_index;
- kv0.key = worker_by_out_key.as_u64;
- kv0.value = thread_index;
- clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv0, 1);
-
- /* log NAT event */
- snat_ipfix_logging_nat44_ses_create(s->in2out.addr.as_u32,
- s->out2in.addr.as_u32,
- s->in2out.protocol,
- s->in2out.port,
- s->out2in.port,
- s->in2out.fib_index);
- return next0;
-}
-
-static_always_inline
-snat_in2out_error_t icmp_get_key(ip4_header_t *ip0,
- snat_session_key_t *p_key0)
-{
- icmp46_header_t *icmp0;
- snat_session_key_t key0;
- icmp_echo_header_t *echo0, *inner_echo0 = 0;
- ip4_header_t *inner_ip0 = 0;
- void *l4_header = 0;
- icmp46_header_t *inner_icmp0;
-
- icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
- echo0 = (icmp_echo_header_t *)(icmp0+1);
-
- if (!icmp_is_error_message (icmp0))
- {
- key0.protocol = SNAT_PROTOCOL_ICMP;
- key0.addr = ip0->src_address;
- key0.port = echo0->identifier;
- }
- else
- {
- inner_ip0 = (ip4_header_t *)(echo0+1);
- l4_header = ip4_next_header (inner_ip0);
- key0.protocol = ip_proto_to_snat_proto (inner_ip0->protocol);
- key0.addr = inner_ip0->dst_address;
- switch (key0.protocol)
- {
- case SNAT_PROTOCOL_ICMP:
- inner_icmp0 = (icmp46_header_t*)l4_header;
- inner_echo0 = (icmp_echo_header_t *)(inner_icmp0+1);
- key0.port = inner_echo0->identifier;
- break;
- case SNAT_PROTOCOL_UDP:
- case SNAT_PROTOCOL_TCP:
- key0.port = ((tcp_udp_header_t*)l4_header)->dst_port;
- break;
- default:
- return SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL;
- }
- }
- *p_key0 = key0;
- return -1; /* success */
-}
-
-/**
- * Get address and port values to be used for packet SNAT translation
- * and create session if needed
- *
- * @param[in,out] sm SNAT main
- * @param[in,out] node SNAT node runtime
- * @param[in] thread_index thread index
- * @param[in,out] b0 buffer containing packet to be translated
- * @param[out] p_proto protocol used for matching
- * @param[out] p_value address and port after NAT translation
- * @param[out] p_dont_translate if packet should not be translated
- * @param d optional parameter
- * @param e optional parameter
- */
-u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e)
-{
- ip4_header_t *ip0;
- icmp46_header_t *icmp0;
- u32 sw_if_index0;
- u32 rx_fib_index0;
- snat_session_key_t key0;
- snat_session_t *s0 = 0;
- u8 dont_translate = 0;
- clib_bihash_kv_8_8_t kv0, value0;
- u32 next0 = ~0;
- int err;
- u32 iph_offset0 = 0;
-
- if (PREDICT_FALSE(vnet_buffer(b0)->sw_if_index[VLIB_TX] != ~0))
- {
- iph_offset0 = vnet_buffer (b0)->ip.save_rewrite_length;
- }
- ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) + iph_offset0);
- icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
-
- err = icmp_get_key (ip0, &key0);
- if (err != -1)
- {
- b0->error = node->errors[err];
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
- key0.fib_index = rx_fib_index0;
-
- kv0.key = key0.as_u64;
-
- if (clib_bihash_search_8_8 (&sm->in2out, &kv0, &value0))
- {
- if (PREDICT_FALSE(snat_not_translate(sm, node, sw_if_index0, ip0,
- IP_PROTOCOL_ICMP, rx_fib_index0) &&
- vnet_buffer(b0)->sw_if_index[VLIB_TX] == ~0))
- {
- dont_translate = 1;
- goto out;
- }
-
- if (PREDICT_FALSE(icmp_is_error_message (icmp0)))
- {
- b0->error = node->errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
-
- next0 = slow_path (sm, b0, ip0, rx_fib_index0, &key0,
- &s0, node, next0, thread_index);
-
- if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
- goto out;
- }
- else
- {
- if (PREDICT_FALSE(icmp0->type != ICMP4_echo_request &&
- icmp0->type != ICMP4_echo_reply &&
- !icmp_is_error_message (icmp0)))
- {
- b0->error = node->errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
-
- s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
- value0.value);
- }
-
-out:
- *p_proto = key0.protocol;
- if (s0)
- *p_value = s0->out2in;
- *p_dont_translate = dont_translate;
- if (d)
- *(snat_session_t**)d = s0;
- return next0;
-}
-
-/**
- * Get address and port values to be used for packet SNAT translation
- *
- * @param[in] sm SNAT main
- * @param[in,out] node SNAT node runtime
- * @param[in] thread_index thread index
- * @param[in,out] b0 buffer containing packet to be translated
- * @param[out] p_proto protocol used for matching
- * @param[out] p_value address and port after NAT translation
- * @param[out] p_dont_translate if packet should not be translated
- * @param d optional parameter
- * @param e optional parameter
- */
-u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e)
-{
- ip4_header_t *ip0;
- icmp46_header_t *icmp0;
- u32 sw_if_index0;
- u32 rx_fib_index0;
- snat_session_key_t key0;
- snat_session_key_t sm0;
- u8 dont_translate = 0;
- u8 is_addr_only;
- u32 next0 = ~0;
- int err;
-
- ip0 = vlib_buffer_get_current (b0);
- icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
-
- err = icmp_get_key (ip0, &key0);
- if (err != -1)
- {
- b0->error = node->errors[err];
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out2;
- }
- key0.fib_index = rx_fib_index0;
-
- if (snat_static_mapping_match(sm, key0, &sm0, 0, &is_addr_only))
- {
- if (PREDICT_FALSE(snat_not_translate_fast(sm, node, sw_if_index0, ip0,
- IP_PROTOCOL_ICMP, rx_fib_index0)))
- {
- dont_translate = 1;
- goto out;
- }
-
- if (icmp_is_error_message (icmp0))
- {
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
-
- b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
-
- if (PREDICT_FALSE(icmp0->type != ICMP4_echo_request &&
- (icmp0->type != ICMP4_echo_reply || !is_addr_only) &&
- !icmp_is_error_message (icmp0)))
- {
- b0->error = node->errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
-
-out:
- *p_value = sm0;
-out2:
- *p_proto = key0.protocol;
- *p_dont_translate = dont_translate;
- return next0;
-}
-
-static inline u32 icmp_in2out (snat_main_t *sm,
- vlib_buffer_t * b0,
- ip4_header_t * ip0,
- icmp46_header_t * icmp0,
- u32 sw_if_index0,
- u32 rx_fib_index0,
- vlib_node_runtime_t * node,
- u32 next0,
- u32 thread_index,
- void *d,
- void *e)
-{
- snat_session_key_t sm0;
- u8 protocol;
- icmp_echo_header_t *echo0, *inner_echo0 = 0;
- ip4_header_t *inner_ip0;
- void *l4_header = 0;
- icmp46_header_t *inner_icmp0;
- u8 dont_translate;
- u32 new_addr0, old_addr0;
- u16 old_id0, new_id0;
- ip_csum_t sum0;
- u16 checksum0;
- u32 next0_tmp;
-
- echo0 = (icmp_echo_header_t *)(icmp0+1);
-
- next0_tmp = sm->icmp_match_in2out_cb(sm, node, thread_index, b0,
- &protocol, &sm0, &dont_translate, d, e);
- if (next0_tmp != ~0)
- next0 = next0_tmp;
- if (next0 == SNAT_IN2OUT_NEXT_DROP || dont_translate)
- goto out;
-
- sum0 = ip_incremental_checksum (0, icmp0,
- ntohs(ip0->length) - ip4_header_bytes (ip0));
- checksum0 = ~ip_csum_fold (sum0);
- if (PREDICT_FALSE(checksum0 != 0 && checksum0 != 0xffff))
- {
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
-
- old_addr0 = ip0->src_address.as_u32;
- new_addr0 = ip0->src_address.as_u32 = sm0.addr.as_u32;
- if (vnet_buffer(b0)->sw_if_index[VLIB_TX] == ~0)
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm0.fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
- src_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (!icmp_is_error_message (icmp0))
- {
- new_id0 = sm0.port;
- if (PREDICT_FALSE(new_id0 != echo0->identifier))
- {
- old_id0 = echo0->identifier;
- new_id0 = sm0.port;
- echo0->identifier = new_id0;
-
- sum0 = icmp0->checksum;
- sum0 = ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
- identifier);
- icmp0->checksum = ip_csum_fold (sum0);
- }
- }
- else
- {
- inner_ip0 = (ip4_header_t *)(echo0+1);
- l4_header = ip4_next_header (inner_ip0);
-
- if (!ip4_header_checksum_is_valid (inner_ip0))
- {
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
-
- old_addr0 = inner_ip0->dst_address.as_u32;
- inner_ip0->dst_address = sm0.addr;
- new_addr0 = inner_ip0->dst_address.as_u32;
-
- sum0 = icmp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
- dst_address /* changed member */);
- icmp0->checksum = ip_csum_fold (sum0);
-
- switch (protocol)
- {
- case SNAT_PROTOCOL_ICMP:
- inner_icmp0 = (icmp46_header_t*)l4_header;
- inner_echo0 = (icmp_echo_header_t *)(inner_icmp0+1);
-
- old_id0 = inner_echo0->identifier;
- new_id0 = sm0.port;
- inner_echo0->identifier = new_id0;
-
- sum0 = icmp0->checksum;
- sum0 = ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
- identifier);
- icmp0->checksum = ip_csum_fold (sum0);
- break;
- case SNAT_PROTOCOL_UDP:
- case SNAT_PROTOCOL_TCP:
- old_id0 = ((tcp_udp_header_t*)l4_header)->dst_port;
- new_id0 = sm0.port;
- ((tcp_udp_header_t*)l4_header)->dst_port = new_id0;
-
- sum0 = icmp0->checksum;
- sum0 = ip_csum_update (sum0, old_id0, new_id0, tcp_udp_header_t,
- dst_port);
- icmp0->checksum = ip_csum_fold (sum0);
- break;
- default:
- ASSERT(0);
- }
- }
-
-out:
- return next0;
-}
-
-/**
- * @brief Hairpinning
- *
- * Hairpinning allows two endpoints on the internal side of the NAT to
- * communicate even if they only use each other's external IP addresses
- * and ports.
- *
- * @param sm SNAT main.
- * @param b0 Vlib buffer.
- * @param ip0 IP header.
- * @param udp0 UDP header.
- * @param tcp0 TCP header.
- * @param proto0 SNAT protocol.
- */
-static inline void
-snat_hairpinning (snat_main_t *sm,
- vlib_buffer_t * b0,
- ip4_header_t * ip0,
- udp_header_t * udp0,
- tcp_header_t * tcp0,
- u32 proto0)
-{
- snat_session_key_t key0, sm0;
- snat_worker_key_t k0;
- snat_session_t * s0;
- clib_bihash_kv_8_8_t kv0, value0;
- ip_csum_t sum0;
- u32 new_dst_addr0 = 0, old_dst_addr0, ti = 0, si;
- u16 new_dst_port0, old_dst_port0;
-
- key0.addr = ip0->dst_address;
- key0.port = udp0->dst_port;
- key0.protocol = proto0;
- key0.fib_index = sm->outside_fib_index;
- kv0.key = key0.as_u64;
-
- /* Check if destination is in active sessions */
- if (clib_bihash_search_8_8 (&sm->out2in, &kv0, &value0))
- {
- /* or static mappings */
- if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0))
- {
- new_dst_addr0 = sm0.addr.as_u32;
- new_dst_port0 = sm0.port;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm0.fib_index;
- }
- }
- else
- {
- si = value0.value;
- if (sm->num_workers > 1)
- {
- k0.addr = ip0->dst_address;
- k0.port = udp0->dst_port;
- k0.fib_index = sm->outside_fib_index;
- kv0.key = k0.as_u64;
- if (clib_bihash_search_8_8 (&sm->worker_by_out, &kv0, &value0))
- ASSERT(0);
- else
- ti = value0.value;
- }
- else
- ti = sm->num_workers;
-
- s0 = pool_elt_at_index (sm->per_thread_data[ti].sessions, si);
- new_dst_addr0 = s0->in2out.addr.as_u32;
- new_dst_port0 = s0->in2out.port;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
- }
-
- /* Destination is behind the same NAT, use internal address and port */
- if (new_dst_addr0)
- {
- old_dst_addr0 = ip0->dst_address.as_u32;
- ip0->dst_address.as_u32 = new_dst_addr0;
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_dst_addr0, new_dst_addr0,
- ip4_header_t, dst_address);
- ip0->checksum = ip_csum_fold (sum0);
-
- old_dst_port0 = tcp0->dst;
- if (PREDICT_TRUE(new_dst_port0 != old_dst_port0))
- {
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- tcp0->dst = new_dst_port0;
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_dst_addr0, new_dst_addr0,
- ip4_header_t, dst_address);
- sum0 = ip_csum_update (sum0, old_dst_port0, new_dst_port0,
- ip4_header_t /* cheat */, length);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- udp0->dst_port = new_dst_port0;
- udp0->checksum = 0;
- }
- }
- else
- {
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_dst_addr0, new_dst_addr0,
- ip4_header_t, dst_address);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- }
- }
-}
-
-static inline void
-snat_icmp_hairpinning (snat_main_t *sm,
- vlib_buffer_t * b0,
- ip4_header_t * ip0,
- icmp46_header_t * icmp0)
-{
- snat_session_key_t key0, sm0;
- clib_bihash_kv_8_8_t kv0, value0;
- snat_worker_key_t k0;
- u32 new_dst_addr0 = 0, old_dst_addr0, si, ti = 0;
- ip_csum_t sum0;
- snat_session_t *s0;
-
- if (!icmp_is_error_message (icmp0))
- {
- icmp_echo_header_t *echo0 = (icmp_echo_header_t *)(icmp0+1);
- u16 icmp_id0 = echo0->identifier;
- key0.addr = ip0->dst_address;
- key0.port = icmp_id0;
- key0.protocol = SNAT_PROTOCOL_ICMP;
- key0.fib_index = sm->outside_fib_index;
- kv0.key = key0.as_u64;
-
- /* Check if destination is in active sessions */
- if (clib_bihash_search_8_8 (&sm->out2in, &kv0, &value0))
- {
- /* or static mappings */
- if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0))
- {
- new_dst_addr0 = sm0.addr.as_u32;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm0.fib_index;
- }
- }
- else
- {
- si = value0.value;
- if (sm->num_workers > 1)
- {
- k0.addr = ip0->dst_address;
- k0.port = icmp_id0;
- k0.fib_index = sm->outside_fib_index;
- kv0.key = k0.as_u64;
- if (clib_bihash_search_8_8 (&sm->worker_by_out, &kv0, &value0))
- ASSERT(0);
- else
- ti = value0.value;
- }
- else
- ti = sm->num_workers;
-
- s0 = pool_elt_at_index (sm->per_thread_data[ti].sessions, si);
- new_dst_addr0 = s0->in2out.addr.as_u32;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
- echo0->identifier = s0->in2out.port;
- sum0 = icmp0->checksum;
- sum0 = ip_csum_update (sum0, icmp_id0, s0->in2out.port,
- icmp_echo_header_t, identifier);
- icmp0->checksum = ip_csum_fold (sum0);
- }
-
- /* Destination is behind the same NAT, use internal address and port */
- if (new_dst_addr0)
- {
- old_dst_addr0 = ip0->dst_address.as_u32;
- ip0->dst_address.as_u32 = new_dst_addr0;
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_dst_addr0, new_dst_addr0,
- ip4_header_t, dst_address);
- ip0->checksum = ip_csum_fold (sum0);
- }
- }
-
-}
-
-static inline u32 icmp_in2out_slow_path (snat_main_t *sm,
- vlib_buffer_t * b0,
- ip4_header_t * ip0,
- icmp46_header_t * icmp0,
- u32 sw_if_index0,
- u32 rx_fib_index0,
- vlib_node_runtime_t * node,
- u32 next0,
- f64 now,
- u32 thread_index,
- snat_session_t ** p_s0)
-{
- next0 = icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
- next0, thread_index, p_s0, 0);
- snat_session_t * s0 = *p_s0;
- if (PREDICT_TRUE(next0 != SNAT_IN2OUT_NEXT_DROP && s0))
- {
- /* Hairpinning */
- if (vnet_buffer(b0)->sw_if_index[VLIB_TX] == 0)
- snat_icmp_hairpinning(sm, b0, ip0, icmp0);
- /* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (sm->vlib_main, b0);
- /* Per-user LRU list maintenance for dynamic translations */
- if (!snat_is_session_static (s0))
- {
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
- }
- }
- return next0;
-}
-static inline void
-snat_hairpinning_unknown_proto (snat_main_t *sm,
- vlib_buffer_t * b,
- ip4_header_t * ip)
-{
- u32 old_addr, new_addr = 0, ti = 0;
- clib_bihash_kv_8_8_t kv, value;
- clib_bihash_kv_16_8_t s_kv, s_value;
- snat_unk_proto_ses_key_t key;
- snat_session_key_t m_key;
- snat_worker_key_t w_key;
- snat_static_mapping_t *m;
- ip_csum_t sum;
- snat_session_t *s;
-
- old_addr = ip->dst_address.as_u32;
- key.l_addr.as_u32 = ip->dst_address.as_u32;
- key.r_addr.as_u32 = ip->src_address.as_u32;
- key.fib_index = sm->outside_fib_index;
- key.proto = ip->protocol;
- key.rsvd[0] = key.rsvd[1] = key.rsvd[2] = 0;
- s_kv.key[0] = key.as_u64[0];
- s_kv.key[1] = key.as_u64[1];
- if (clib_bihash_search_16_8 (&sm->out2in_unk_proto, &s_kv, &s_value))
- {
- m_key.addr = ip->dst_address;
- m_key.fib_index = sm->outside_fib_index;
- m_key.port = 0;
- m_key.protocol = 0;
- kv.key = m_key.as_u64;
- if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
- return;
-
- m = pool_elt_at_index (sm->static_mappings, value.value);
- if (vnet_buffer(b)->sw_if_index[VLIB_TX] == ~0)
- vnet_buffer(b)->sw_if_index[VLIB_TX] = m->fib_index;
- new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32;
- }
- else
- {
- if (sm->num_workers > 1)
- {
- w_key.addr = ip->dst_address;
- w_key.port = 0;
- w_key.fib_index = sm->outside_fib_index;
- kv.key = w_key.as_u64;
- if (clib_bihash_search_8_8 (&sm->worker_by_out, &kv, &value))
- return;
- else
- ti = value.value;
- }
- else
- ti = sm->num_workers;
-
- s = pool_elt_at_index (sm->per_thread_data[ti].sessions, s_value.value);
- if (vnet_buffer(b)->sw_if_index[VLIB_TX] == ~0)
- vnet_buffer(b)->sw_if_index[VLIB_TX] = s->in2out.fib_index;
- new_addr = ip->dst_address.as_u32 = s->in2out.addr.as_u32;
- }
- sum = ip->checksum;
- sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, dst_address);
- ip->checksum = ip_csum_fold (sum);
-}
-
-static void
-snat_in2out_unknown_proto (snat_main_t *sm,
- vlib_buffer_t * b,
- ip4_header_t * ip,
- u32 rx_fib_index,
- u32 thread_index,
- f64 now,
- vlib_main_t * vm)
-{
- clib_bihash_kv_8_8_t kv, value;
- clib_bihash_kv_16_8_t s_kv, s_value;
- snat_static_mapping_t *m;
- snat_session_key_t m_key;
- u32 old_addr, new_addr = 0;
- ip_csum_t sum;
- snat_user_key_t u_key;
- snat_user_t *u;
- dlist_elt_t *head, *elt, *oldest;
- snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
- u32 elt_index, head_index, ses_index, oldest_index;
- snat_session_t * s;
- snat_unk_proto_ses_key_t key;
- u32 address_index = ~0;
- int i;
- u8 is_sm = 0;
-
- old_addr = ip->src_address.as_u32;
-
- key.l_addr = ip->src_address;
- key.r_addr = ip->dst_address;
- key.fib_index = rx_fib_index;
- key.proto = ip->protocol;
- key.rsvd[0] = key.rsvd[1] = key.rsvd[2] = 0;
- s_kv.key[0] = key.as_u64[0];
- s_kv.key[1] = key.as_u64[1];
-
- if (!clib_bihash_search_16_8 (&sm->in2out_unk_proto, &s_kv, &s_value))
- {
- s = pool_elt_at_index (tsm->sessions, s_value.value);
- new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
- }
- else
- {
- u_key.addr = ip->src_address;
- u_key.fib_index = rx_fib_index;
- kv.key = u_key.as_u64;
-
- /* Ever heard of the "user" = src ip4 address before? */
- if (clib_bihash_search_8_8 (&sm->user_hash, &kv, &value))
- {
- /* no, make a new one */
- pool_get (tsm->users, u);
- memset (u, 0, sizeof (*u));
- u->addr = ip->src_address;
- u->fib_index = rx_fib_index;
-
- pool_get (tsm->list_pool, head);
- u->sessions_per_user_list_head_index = head - tsm->list_pool;
-
- clib_dlist_init (tsm->list_pool,
- u->sessions_per_user_list_head_index);
-
- kv.value = u - tsm->users;
-
- /* add user */
- clib_bihash_add_del_8_8 (&sm->user_hash, &kv, 1);
- }
- else
- {
- u = pool_elt_at_index (tsm->users, value.value);
- }
-
- m_key.addr = ip->src_address;
- m_key.port = 0;
- m_key.protocol = 0;
- m_key.fib_index = rx_fib_index;
- kv.key = m_key.as_u64;
-
- /* Try to find static mapping first */
- if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value))
- {
- m = pool_elt_at_index (sm->static_mappings, value.value);
- new_addr = ip->src_address.as_u32 = m->external_addr.as_u32;
- is_sm = 1;
- goto create_ses;
- }
- /* Fallback to 3-tuple key */
- else
- {
- /* Choose same out address as for TCP/UDP session to same destination */
- if (!clib_bihash_search_8_8 (&sm->user_hash, &kv, &value))
- {
- head_index = u->sessions_per_user_list_head_index;
- head = pool_elt_at_index (tsm->list_pool, head_index);
- elt_index = head->next;
- elt = pool_elt_at_index (tsm->list_pool, elt_index);
- ses_index = elt->value;
- while (ses_index != ~0)
- {
- s = pool_elt_at_index (tsm->sessions, ses_index);
- elt_index = elt->next;
- elt = pool_elt_at_index (tsm->list_pool, elt_index);
- ses_index = elt->value;
-
- if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32)
- {
- new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
- address_index = s->outside_address_index;
-
- key.fib_index = sm->outside_fib_index;
- key.l_addr.as_u32 = new_addr;
- s_kv.key[0] = key.as_u64[0];
- s_kv.key[1] = key.as_u64[1];
- if (clib_bihash_search_16_8 (&sm->out2in_unk_proto, &s_kv, &s_value))
- break;
-
- goto create_ses;
- }
- }
- }
- key.fib_index = sm->outside_fib_index;
- for (i = 0; i < vec_len (sm->addresses); i++)
- {
- key.l_addr.as_u32 = sm->addresses[i].addr.as_u32;
- s_kv.key[0] = key.as_u64[0];
- s_kv.key[1] = key.as_u64[1];
- if (clib_bihash_search_16_8 (&sm->out2in_unk_proto, &s_kv, &s_value))
- {
- new_addr = ip->src_address.as_u32 = key.l_addr.as_u32;
- address_index = i;
- goto create_ses;
- }
- }
- return;
- }
-
-create_ses:
- /* Over quota? Recycle the least recently used dynamic translation */
- if (u->nsessions >= sm->max_translations_per_user && !is_sm)
- {
- /* Remove the oldest dynamic translation */
- do {
- oldest_index = clib_dlist_remove_head (
- tsm->list_pool, u->sessions_per_user_list_head_index);
-
- ASSERT (oldest_index != ~0);
-
- /* add it back to the end of the LRU list */
- clib_dlist_addtail (tsm->list_pool,
- u->sessions_per_user_list_head_index,
- oldest_index);
- /* Get the list element */
- oldest = pool_elt_at_index (tsm->list_pool, oldest_index);
-
- /* Get the session index from the list element */
- ses_index = oldest->value;
-
- /* Get the session */
- s = pool_elt_at_index (tsm->sessions, ses_index);
- } while (snat_is_session_static (s));
-
- if (snat_is_unk_proto_session (s))
- {
- /* Remove from lookup tables */
- key.l_addr = s->in2out.addr;
- key.r_addr = s->ext_host_addr;
- key.fib_index = s->in2out.fib_index;
- key.proto = s->in2out.port;
- s_kv.key[0] = key.as_u64[0];
- s_kv.key[1] = key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->in2out_unk_proto, &s_kv, 0))
- clib_warning ("in2out key del failed");
-
- key.l_addr = s->out2in.addr;
- key.fib_index = s->out2in.fib_index;
- s_kv.key[0] = key.as_u64[0];
- s_kv.key[1] = key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->out2in_unk_proto, &s_kv, 0))
- clib_warning ("out2in key del failed");
- }
- else
- {
- /* log NAT event */
- snat_ipfix_logging_nat44_ses_delete(s->in2out.addr.as_u32,
- s->out2in.addr.as_u32,
- s->in2out.protocol,
- s->in2out.port,
- s->out2in.port,
- s->in2out.fib_index);
-
- snat_free_outside_address_and_port (sm, &s->out2in,
- s->outside_address_index);
-
- /* Remove in2out, out2in keys */
- kv.key = s->in2out.as_u64;
- if (clib_bihash_add_del_8_8 (&sm->in2out, &kv, 0))
- clib_warning ("in2out key del failed");
- kv.key = s->out2in.as_u64;
- if (clib_bihash_add_del_8_8 (&sm->out2in, &kv, 0))
- clib_warning ("out2in key del failed");
- }
- }
- else
- {
- /* Create a new session */
- pool_get (tsm->sessions, s);
- memset (s, 0, sizeof (*s));
-
- /* Create list elts */
- pool_get (tsm->list_pool, elt);
- clib_dlist_init (tsm->list_pool, elt - tsm->list_pool);
- elt->value = s - tsm->sessions;
- s->per_user_index = elt - tsm->list_pool;
- s->per_user_list_head_index = u->sessions_per_user_list_head_index;
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
- }
-
- s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
- s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO;
- s->outside_address_index = address_index;
- s->out2in.addr.as_u32 = new_addr;
- s->out2in.fib_index = sm->outside_fib_index;
- s->in2out.addr.as_u32 = old_addr;
- s->in2out.fib_index = rx_fib_index;
- s->in2out.port = s->out2in.port = ip->protocol;
- if (is_sm)
- {
- u->nstaticsessions++;
- s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
- }
- else
- {
- u->nsessions++;
- }
-
- /* Add to lookup tables */
- key.l_addr.as_u32 = old_addr;
- key.r_addr = ip->dst_address;
- key.proto = ip->protocol;
- key.fib_index = rx_fib_index;
- s_kv.key[0] = key.as_u64[0];
- s_kv.key[1] = key.as_u64[1];
- s_kv.value = s - tsm->sessions;
- if (clib_bihash_add_del_16_8 (&sm->in2out_unk_proto, &s_kv, 1))
- clib_warning ("in2out key add failed");
-
- key.l_addr.as_u32 = new_addr;
- key.fib_index = sm->outside_fib_index;
- s_kv.key[0] = key.as_u64[0];
- s_kv.key[1] = key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->out2in_unk_proto, &s_kv, 1))
- clib_warning ("out2in key add failed");
- }
-
- /* Update IP checksum */
- sum = ip->checksum;
- sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, src_address);
- ip->checksum = ip_csum_fold (sum);
-
- /* Accounting */
- s->last_heard = now;
- s->total_pkts++;
- s->total_bytes += vlib_buffer_length_in_chain (vm, b);
- /* Per-user LRU list maintenance */
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
-
- /* Hairpinning */
- if (vnet_buffer(b)->sw_if_index[VLIB_TX] == ~0)
- snat_hairpinning_unknown_proto(sm, b, ip);
-
- if (vnet_buffer(b)->sw_if_index[VLIB_TX] == ~0)
- vnet_buffer(b)->sw_if_index[VLIB_TX] = sm->outside_fib_index;
-}
-
-static inline uword
-snat_in2out_node_fn_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame, int is_slow_path,
- int is_output_feature)
-{
- u32 n_left_from, * from, * to_next;
- snat_in2out_next_t next_index;
- u32 pkts_processed = 0;
- snat_main_t * sm = &snat_main;
- f64 now = vlib_time_now (vm);
- u32 stats_node_index;
- u32 thread_index = vlib_get_thread_index ();
-
- stats_node_index = is_slow_path ? snat_in2out_slowpath_node.index :
- snat_in2out_node.index;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 bi0, bi1;
- vlib_buffer_t * b0, * b1;
- u32 next0, next1;
- u32 sw_if_index0, sw_if_index1;
- ip4_header_t * ip0, * ip1;
- ip_csum_t sum0, sum1;
- u32 new_addr0, old_addr0, new_addr1, old_addr1;
- u16 old_port0, new_port0, old_port1, new_port1;
- udp_header_t * udp0, * udp1;
- tcp_header_t * tcp0, * tcp1;
- icmp46_header_t * icmp0, * icmp1;
- snat_session_key_t key0, key1;
- u32 rx_fib_index0, rx_fib_index1;
- u32 proto0, proto1;
- snat_session_t * s0 = 0, * s1 = 0;
- clib_bihash_kv_8_8_t kv0, value0, kv1, value1;
- u32 iph_offset0 = 0, iph_offset1 = 0;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t * p2, * p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
- }
-
- /* speculatively enqueue b0 and b1 to the current next frame */
- to_next[0] = bi0 = from[0];
- to_next[1] = bi1 = from[1];
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- if (is_output_feature)
- iph_offset0 = vnet_buffer (b0)->ip.save_rewrite_length;
-
- ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
- iph_offset0);
-
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
- icmp0 = (icmp46_header_t *) udp0;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
- sw_if_index0);
-
- next0 = next1 = SNAT_IN2OUT_NEXT_LOOKUP;
-
- if (PREDICT_FALSE(ip0->ttl == 1))
- {
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
- goto trace00;
- }
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- /* Next configured feature, probably ip4-lookup */
- if (is_slow_path)
- {
- if (PREDICT_FALSE (proto0 == ~0))
- {
- snat_in2out_unknown_proto (sm, b0, ip0, rx_fib_index0,
- thread_index, now, vm);
- goto trace00;
- }
-
- if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
- {
- next0 = icmp_in2out_slow_path
- (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
- node, next0, now, thread_index, &s0);
- goto trace00;
- }
- }
- else
- {
- if (PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
- {
- next0 = SNAT_IN2OUT_NEXT_SLOW_PATH;
- goto trace00;
- }
- }
-
- key0.addr = ip0->src_address;
- key0.port = udp0->src_port;
- key0.protocol = proto0;
- key0.fib_index = rx_fib_index0;
-
- kv0.key = key0.as_u64;
-
- if (PREDICT_FALSE (clib_bihash_search_8_8 (&sm->in2out, &kv0, &value0) != 0))
- {
- if (is_slow_path)
- {
- if (PREDICT_FALSE(snat_not_translate(sm, node, sw_if_index0,
- ip0, proto0, rx_fib_index0)) && !is_output_feature)
- goto trace00;
-
- next0 = slow_path (sm, b0, ip0, rx_fib_index0, &key0,
- &s0, node, next0, thread_index);
- if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
- goto trace00;
- }
- else
- {
- next0 = SNAT_IN2OUT_NEXT_SLOW_PATH;
- goto trace00;
- }
- }
- else
- s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
- value0.value);
-
- old_addr0 = ip0->src_address.as_u32;
- ip0->src_address = s0->out2in.addr;
- new_addr0 = ip0->src_address.as_u32;
- if (!is_output_feature)
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- src_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- old_port0 = tcp0->src_port;
- tcp0->src_port = s0->out2in.port;
- new_port0 = tcp0->src_port;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- old_port0 = udp0->src_port;
- udp0->src_port = s0->out2in.port;
- udp0->checksum = 0;
- }
-
- /* Hairpinning */
- if (!is_output_feature)
- snat_hairpinning (sm, b0, ip0, udp0, tcp0, proto0);
-
- /* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (vm, b0);
- /* Per-user LRU list maintenance for dynamic translation */
- if (!snat_is_session_static (s0))
- {
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
- }
- trace00:
-
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_in2out_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->is_slow_path = is_slow_path;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- t->session_index = ~0;
- if (s0)
- t->session_index = s0 - sm->per_thread_data[thread_index].sessions;
- }
-
- pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP;
-
- if (is_output_feature)
- iph_offset1 = vnet_buffer (b1)->ip.save_rewrite_length;
-
- ip1 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b1) +
- iph_offset1);
-
- udp1 = ip4_next_header (ip1);
- tcp1 = (tcp_header_t *) udp1;
- icmp1 = (icmp46_header_t *) udp1;
-
- sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
- rx_fib_index1 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
- sw_if_index1);
-
- if (PREDICT_FALSE(ip1->ttl == 1))
- {
- vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next1 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
- goto trace01;
- }
-
- proto1 = ip_proto_to_snat_proto (ip1->protocol);
-
- /* Next configured feature, probably ip4-lookup */
- if (is_slow_path)
- {
- if (PREDICT_FALSE (proto1 == ~0))
- {
- snat_in2out_unknown_proto (sm, b1, ip1, rx_fib_index1,
- thread_index, now, vm);
- goto trace01;
- }
-
- if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
- {
- next1 = icmp_in2out_slow_path
- (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
- next1, now, thread_index, &s1);
- goto trace01;
- }
- }
- else
- {
- if (PREDICT_FALSE (proto1 == ~0 || proto1 == SNAT_PROTOCOL_ICMP))
- {
- next1 = SNAT_IN2OUT_NEXT_SLOW_PATH;
- goto trace01;
- }
- }
-
- key1.addr = ip1->src_address;
- key1.port = udp1->src_port;
- key1.protocol = proto1;
- key1.fib_index = rx_fib_index1;
-
- kv1.key = key1.as_u64;
-
- if (PREDICT_FALSE(clib_bihash_search_8_8 (&sm->in2out, &kv1, &value1) != 0))
- {
- if (is_slow_path)
- {
- if (PREDICT_FALSE(snat_not_translate(sm, node, sw_if_index1,
- ip1, proto1, rx_fib_index1)) && !is_output_feature)
- goto trace01;
-
- next1 = slow_path (sm, b1, ip1, rx_fib_index1, &key1,
- &s1, node, next1, thread_index);
- if (PREDICT_FALSE (next1 == SNAT_IN2OUT_NEXT_DROP))
- goto trace01;
- }
- else
- {
- next1 = SNAT_IN2OUT_NEXT_SLOW_PATH;
- goto trace01;
- }
- }
- else
- s1 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
- value1.value);
-
- old_addr1 = ip1->src_address.as_u32;
- ip1->src_address = s1->out2in.addr;
- new_addr1 = ip1->src_address.as_u32;
- if (!is_output_feature)
- vnet_buffer(b1)->sw_if_index[VLIB_TX] = s1->out2in.fib_index;
-
- sum1 = ip1->checksum;
- sum1 = ip_csum_update (sum1, old_addr1, new_addr1,
- ip4_header_t,
- src_address /* changed member */);
- ip1->checksum = ip_csum_fold (sum1);
-
- if (PREDICT_TRUE(proto1 == SNAT_PROTOCOL_TCP))
- {
- old_port1 = tcp1->src_port;
- tcp1->src_port = s1->out2in.port;
- new_port1 = tcp1->src_port;
-
- sum1 = tcp1->checksum;
- sum1 = ip_csum_update (sum1, old_addr1, new_addr1,
- ip4_header_t,
- dst_address /* changed member */);
- sum1 = ip_csum_update (sum1, old_port1, new_port1,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp1->checksum = ip_csum_fold(sum1);
- }
- else
- {
- old_port1 = udp1->src_port;
- udp1->src_port = s1->out2in.port;
- udp1->checksum = 0;
- }
-
- /* Hairpinning */
- if (!is_output_feature)
- snat_hairpinning (sm, b1, ip1, udp1, tcp1, proto1);
-
- /* Accounting */
- s1->last_heard = now;
- s1->total_pkts++;
- s1->total_bytes += vlib_buffer_length_in_chain (vm, b1);
- /* Per-user LRU list maintenance for dynamic translation */
- if (!snat_is_session_static (s1))
- {
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s1->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s1->per_user_list_head_index,
- s1->per_user_index);
- }
- trace01:
-
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b1->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_in2out_trace_t *t =
- vlib_add_trace (vm, node, b1, sizeof (*t));
- t->sw_if_index = sw_if_index1;
- t->next_index = next1;
- t->session_index = ~0;
- if (s1)
- t->session_index = s1 - sm->per_thread_data[thread_index].sessions;
- }
-
- pkts_processed += next1 != SNAT_IN2OUT_NEXT_DROP;
-
- /* verify speculative enqueues, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, bi1, next0, next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t * b0;
- u32 next0;
- u32 sw_if_index0;
- ip4_header_t * ip0;
- ip_csum_t sum0;
- u32 new_addr0, old_addr0;
- u16 old_port0, new_port0;
- udp_header_t * udp0;
- tcp_header_t * tcp0;
- icmp46_header_t * icmp0;
- snat_session_key_t key0;
- u32 rx_fib_index0;
- u32 proto0;
- snat_session_t * s0 = 0;
- clib_bihash_kv_8_8_t kv0, value0;
- u32 iph_offset0 = 0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
- next0 = SNAT_IN2OUT_NEXT_LOOKUP;
-
- if (is_output_feature)
- iph_offset0 = vnet_buffer (b0)->ip.save_rewrite_length;
-
- ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
- iph_offset0);
-
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
- icmp0 = (icmp46_header_t *) udp0;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
- sw_if_index0);
-
- if (PREDICT_FALSE(ip0->ttl == 1))
- {
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
- goto trace0;
- }
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- /* Next configured feature, probably ip4-lookup */
- if (is_slow_path)
- {
- if (PREDICT_FALSE (proto0 == ~0))
- {
- snat_in2out_unknown_proto (sm, b0, ip0, rx_fib_index0,
- thread_index, now, vm);
- goto trace0;
- }
-
- if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
- {
- next0 = icmp_in2out_slow_path
- (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
- next0, now, thread_index, &s0);
- goto trace0;
- }
- }
- else
- {
- if (PREDICT_FALSE (proto0 == ~0 || proto0 == SNAT_PROTOCOL_ICMP))
- {
- next0 = SNAT_IN2OUT_NEXT_SLOW_PATH;
- goto trace0;
- }
- }
-
- key0.addr = ip0->src_address;
- key0.port = udp0->src_port;
- key0.protocol = proto0;
- key0.fib_index = rx_fib_index0;
-
- kv0.key = key0.as_u64;
-
- if (clib_bihash_search_8_8 (&sm->in2out, &kv0, &value0))
- {
- if (is_slow_path)
- {
- if (PREDICT_FALSE(snat_not_translate(sm, node, sw_if_index0,
- ip0, proto0, rx_fib_index0)) && !is_output_feature)
- goto trace0;
-
- next0 = slow_path (sm, b0, ip0, rx_fib_index0, &key0,
- &s0, node, next0, thread_index);
-
- if (PREDICT_FALSE (next0 == SNAT_IN2OUT_NEXT_DROP))
- goto trace0;
- }
- else
- {
- next0 = SNAT_IN2OUT_NEXT_SLOW_PATH;
- goto trace0;
- }
- }
- else
- s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
- value0.value);
-
- old_addr0 = ip0->src_address.as_u32;
- ip0->src_address = s0->out2in.addr;
- new_addr0 = ip0->src_address.as_u32;
- if (!is_output_feature)
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- src_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- old_port0 = tcp0->src_port;
- tcp0->src_port = s0->out2in.port;
- new_port0 = tcp0->src_port;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- old_port0 = udp0->src_port;
- udp0->src_port = s0->out2in.port;
- udp0->checksum = 0;
- }
-
- /* Hairpinning */
- if (!is_output_feature)
- snat_hairpinning (sm, b0, ip0, udp0, tcp0, proto0);
-
- /* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (vm, b0);
- /* Per-user LRU list maintenance for dynamic translation */
- if (!snat_is_session_static (s0))
- {
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
- }
-
- trace0:
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_in2out_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->is_slow_path = is_slow_path;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- t->session_index = ~0;
- if (s0)
- t->session_index = s0 - sm->per_thread_data[thread_index].sessions;
- }
-
- pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP;
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vlib_node_increment_counter (vm, stats_node_index,
- SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
- pkts_processed);
- return frame->n_vectors;
-}
-
-static uword
-snat_in2out_fast_path_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return snat_in2out_node_fn_inline (vm, node, frame, 0 /* is_slow_path */, 0);
-}
-
-VLIB_REGISTER_NODE (snat_in2out_node) = {
- .function = snat_in2out_fast_path_fn,
- .name = "snat-in2out",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_in2out_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_errors = ARRAY_LEN(snat_in2out_error_strings),
- .error_strings = snat_in2out_error_strings,
-
- .runtime_data_bytes = sizeof (snat_runtime_t),
-
- .n_next_nodes = SNAT_IN2OUT_N_NEXT,
-
- /* edit / add dispositions here */
- .next_nodes = {
- [SNAT_IN2OUT_NEXT_DROP] = "error-drop",
- [SNAT_IN2OUT_NEXT_LOOKUP] = "ip4-lookup",
- [SNAT_IN2OUT_NEXT_SLOW_PATH] = "snat-in2out-slowpath",
- [SNAT_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_in2out_node, snat_in2out_fast_path_fn);
-
-static uword
-snat_in2out_output_fast_path_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return snat_in2out_node_fn_inline (vm, node, frame, 0 /* is_slow_path */, 1);
-}
-
-VLIB_REGISTER_NODE (snat_in2out_output_node) = {
- .function = snat_in2out_output_fast_path_fn,
- .name = "snat-in2out-output",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_in2out_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_errors = ARRAY_LEN(snat_in2out_error_strings),
- .error_strings = snat_in2out_error_strings,
-
- .runtime_data_bytes = sizeof (snat_runtime_t),
-
- .n_next_nodes = SNAT_IN2OUT_N_NEXT,
-
- /* edit / add dispositions here */
- .next_nodes = {
- [SNAT_IN2OUT_NEXT_DROP] = "error-drop",
- [SNAT_IN2OUT_NEXT_LOOKUP] = "interface-output",
- [SNAT_IN2OUT_NEXT_SLOW_PATH] = "snat-in2out-output-slowpath",
- [SNAT_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_in2out_output_node,
- snat_in2out_output_fast_path_fn);
-
-static uword
-snat_in2out_slow_path_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return snat_in2out_node_fn_inline (vm, node, frame, 1 /* is_slow_path */, 0);
-}
-
-VLIB_REGISTER_NODE (snat_in2out_slowpath_node) = {
- .function = snat_in2out_slow_path_fn,
- .name = "snat-in2out-slowpath",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_in2out_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_errors = ARRAY_LEN(snat_in2out_error_strings),
- .error_strings = snat_in2out_error_strings,
-
- .runtime_data_bytes = sizeof (snat_runtime_t),
-
- .n_next_nodes = SNAT_IN2OUT_N_NEXT,
-
- /* edit / add dispositions here */
- .next_nodes = {
- [SNAT_IN2OUT_NEXT_DROP] = "error-drop",
- [SNAT_IN2OUT_NEXT_LOOKUP] = "ip4-lookup",
- [SNAT_IN2OUT_NEXT_SLOW_PATH] = "snat-in2out-slowpath",
- [SNAT_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_in2out_slowpath_node,
- snat_in2out_slow_path_fn);
-
-static uword
-snat_in2out_output_slow_path_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return snat_in2out_node_fn_inline (vm, node, frame, 1 /* is_slow_path */, 1);
-}
-
-VLIB_REGISTER_NODE (snat_in2out_output_slowpath_node) = {
- .function = snat_in2out_output_slow_path_fn,
- .name = "snat-in2out-output-slowpath",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_in2out_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_errors = ARRAY_LEN(snat_in2out_error_strings),
- .error_strings = snat_in2out_error_strings,
-
- .runtime_data_bytes = sizeof (snat_runtime_t),
-
- .n_next_nodes = SNAT_IN2OUT_N_NEXT,
-
- /* edit / add dispositions here */
- .next_nodes = {
- [SNAT_IN2OUT_NEXT_DROP] = "error-drop",
- [SNAT_IN2OUT_NEXT_LOOKUP] = "interface-output",
- [SNAT_IN2OUT_NEXT_SLOW_PATH] = "snat-in2out-output-slowpath",
- [SNAT_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_in2out_output_slowpath_node,
- snat_in2out_output_slow_path_fn);
-
-/**************************/
-/*** deterministic mode ***/
-/**************************/
-static uword
-snat_det_in2out_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- u32 n_left_from, * from, * to_next;
- snat_in2out_next_t next_index;
- u32 pkts_processed = 0;
- snat_main_t * sm = &snat_main;
- u32 now = (u32) vlib_time_now (vm);
- u32 thread_index = vlib_get_thread_index ();
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 bi0, bi1;
- vlib_buffer_t * b0, * b1;
- u32 next0, next1;
- u32 sw_if_index0, sw_if_index1;
- ip4_header_t * ip0, * ip1;
- ip_csum_t sum0, sum1;
- ip4_address_t new_addr0, old_addr0, new_addr1, old_addr1;
- u16 old_port0, new_port0, lo_port0, i0;
- u16 old_port1, new_port1, lo_port1, i1;
- udp_header_t * udp0, * udp1;
- tcp_header_t * tcp0, * tcp1;
- u32 proto0, proto1;
- snat_det_out_key_t key0, key1;
- snat_det_map_t * dm0, * dm1;
- snat_det_session_t * ses0 = 0, * ses1 = 0;
- u32 rx_fib_index0, rx_fib_index1;
- icmp46_header_t * icmp0, * icmp1;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t * p2, * p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
- }
-
- /* speculatively enqueue b0 and b1 to the current next frame */
- to_next[0] = bi0 = from[0];
- to_next[1] = bi1 = from[1];
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- next0 = SNAT_IN2OUT_NEXT_LOOKUP;
- next1 = SNAT_IN2OUT_NEXT_LOOKUP;
-
- ip0 = vlib_buffer_get_current (b0);
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
-
- if (PREDICT_FALSE(ip0->ttl == 1))
- {
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
- goto trace0;
- }
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- if (PREDICT_FALSE(proto0 == SNAT_PROTOCOL_ICMP))
- {
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0);
- icmp0 = (icmp46_header_t *) udp0;
-
- next0 = icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
- rx_fib_index0, node, next0, thread_index,
- &ses0, &dm0);
- goto trace0;
- }
-
- dm0 = snat_det_map_by_user(sm, &ip0->src_address);
- if (PREDICT_FALSE(!dm0))
- {
- clib_warning("no match for internal host %U",
- format_ip4_address, &ip0->src_address);
- next0 = SNAT_IN2OUT_NEXT_DROP;
- b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
- goto trace0;
- }
-
- snat_det_forward(dm0, &ip0->src_address, &new_addr0, &lo_port0);
-
- key0.ext_host_addr = ip0->dst_address;
- key0.ext_host_port = tcp0->dst;
-
- ses0 = snat_det_find_ses_by_in(dm0, &ip0->src_address, tcp0->src, key0);
- if (PREDICT_FALSE(!ses0))
- {
- for (i0 = 0; i0 < dm0->ports_per_host; i0++)
- {
- key0.out_port = clib_host_to_net_u16 (lo_port0 +
- ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->ports_per_host));
-
- if (snat_det_get_ses_by_out (dm0, &ip0->src_address, key0.as_u64))
- continue;
-
- ses0 = snat_det_ses_create(dm0, &ip0->src_address, tcp0->src, &key0);
- break;
- }
- if (PREDICT_FALSE(!ses0))
- {
- /* too many sessions for user, send ICMP error packet */
-
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_destination_unreachable_host,
- 0);
- next0 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
- goto trace0;
- }
- }
-
- new_port0 = ses0->out.out_port;
-
- old_addr0.as_u32 = ip0->src_address.as_u32;
- ip0->src_address.as_u32 = new_addr0.as_u32;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm->outside_fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
- ip4_header_t,
- src_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- if (tcp0->flags & TCP_FLAG_SYN)
- ses0->state = SNAT_SESSION_TCP_SYN_SENT;
- else if (tcp0->flags & TCP_FLAG_ACK && ses0->state == SNAT_SESSION_TCP_SYN_SENT)
- ses0->state = SNAT_SESSION_TCP_ESTABLISHED;
- else if (tcp0->flags & TCP_FLAG_FIN && ses0->state == SNAT_SESSION_TCP_ESTABLISHED)
- ses0->state = SNAT_SESSION_TCP_FIN_WAIT;
- else if (tcp0->flags & TCP_FLAG_ACK && ses0->state == SNAT_SESSION_TCP_FIN_WAIT)
- snat_det_ses_close(dm0, ses0);
- else if (tcp0->flags & TCP_FLAG_FIN && ses0->state == SNAT_SESSION_TCP_CLOSE_WAIT)
- ses0->state = SNAT_SESSION_TCP_LAST_ACK;
- else if (tcp0->flags == 0 && ses0->state == SNAT_SESSION_UNKNOWN)
- ses0->state = SNAT_SESSION_TCP_ESTABLISHED;
-
- old_port0 = tcp0->src;
- tcp0->src = new_port0;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
- ip4_header_t,
- dst_address /* changed member */);
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- ses0->state = SNAT_SESSION_UDP_ACTIVE;
- old_port0 = udp0->src_port;
- udp0->src_port = new_port0;
- udp0->checksum = 0;
- }
-
- switch(ses0->state)
- {
- case SNAT_SESSION_UDP_ACTIVE:
- ses0->expire = now + sm->udp_timeout;
- break;
- case SNAT_SESSION_TCP_SYN_SENT:
- case SNAT_SESSION_TCP_FIN_WAIT:
- case SNAT_SESSION_TCP_CLOSE_WAIT:
- case SNAT_SESSION_TCP_LAST_ACK:
- ses0->expire = now + sm->tcp_transitory_timeout;
- break;
- case SNAT_SESSION_TCP_ESTABLISHED:
- ses0->expire = now + sm->tcp_established_timeout;
- break;
- }
-
- trace0:
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_in2out_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->is_slow_path = 0;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- t->session_index = ~0;
- if (ses0)
- t->session_index = ses0 - dm0->sessions;
- }
-
- pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP;
-
- ip1 = vlib_buffer_get_current (b1);
- udp1 = ip4_next_header (ip1);
- tcp1 = (tcp_header_t *) udp1;
-
- sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
-
- if (PREDICT_FALSE(ip1->ttl == 1))
- {
- vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next1 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
- goto trace1;
- }
-
- proto1 = ip_proto_to_snat_proto (ip1->protocol);
-
- if (PREDICT_FALSE(proto1 == SNAT_PROTOCOL_ICMP))
- {
- rx_fib_index1 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index1);
- icmp1 = (icmp46_header_t *) udp1;
-
- next1 = icmp_in2out(sm, b1, ip1, icmp1, sw_if_index1,
- rx_fib_index1, node, next1, thread_index,
- &ses1, &dm1);
- goto trace1;
- }
-
- dm1 = snat_det_map_by_user(sm, &ip1->src_address);
- if (PREDICT_FALSE(!dm1))
- {
- clib_warning("no match for internal host %U",
- format_ip4_address, &ip0->src_address);
- next1 = SNAT_IN2OUT_NEXT_DROP;
- b1->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
- goto trace1;
- }
-
- snat_det_forward(dm1, &ip1->src_address, &new_addr1, &lo_port1);
-
- key1.ext_host_addr = ip1->dst_address;
- key1.ext_host_port = tcp1->dst;
-
- ses1 = snat_det_find_ses_by_in(dm1, &ip1->src_address, tcp1->src, key1);
- if (PREDICT_FALSE(!ses1))
- {
- for (i1 = 0; i1 < dm1->ports_per_host; i1++)
- {
- key1.out_port = clib_host_to_net_u16 (lo_port1 +
- ((i1 + clib_net_to_host_u16 (tcp1->src)) % dm1->ports_per_host));
-
- if (snat_det_get_ses_by_out (dm1, &ip1->src_address, key1.as_u64))
- continue;
-
- ses1 = snat_det_ses_create(dm1, &ip1->src_address, tcp1->src, &key1);
- break;
- }
- if (PREDICT_FALSE(!ses1))
- {
- /* too many sessions for user, send ICMP error packet */
-
- vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b1, ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_destination_unreachable_host,
- 0);
- next1 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
- goto trace1;
- }
- }
-
- new_port1 = ses1->out.out_port;
-
- old_addr1.as_u32 = ip1->src_address.as_u32;
- ip1->src_address.as_u32 = new_addr1.as_u32;
- vnet_buffer(b1)->sw_if_index[VLIB_TX] = sm->outside_fib_index;
-
- sum1 = ip1->checksum;
- sum1 = ip_csum_update (sum1, old_addr1.as_u32, new_addr1.as_u32,
- ip4_header_t,
- src_address /* changed member */);
- ip1->checksum = ip_csum_fold (sum1);
-
- if (PREDICT_TRUE(proto1 == SNAT_PROTOCOL_TCP))
- {
- if (tcp1->flags & TCP_FLAG_SYN)
- ses1->state = SNAT_SESSION_TCP_SYN_SENT;
- else if (tcp1->flags & TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_SYN_SENT)
- ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
- else if (tcp1->flags & TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_ESTABLISHED)
- ses1->state = SNAT_SESSION_TCP_FIN_WAIT;
- else if (tcp1->flags & TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_FIN_WAIT)
- snat_det_ses_close(dm1, ses1);
- else if (tcp1->flags & TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_CLOSE_WAIT)
- ses1->state = SNAT_SESSION_TCP_LAST_ACK;
- else if (tcp1->flags == 0 && ses1->state == SNAT_SESSION_UNKNOWN)
- ses1->state = SNAT_SESSION_TCP_ESTABLISHED;
-
- old_port1 = tcp1->src;
- tcp1->src = new_port1;
-
- sum1 = tcp1->checksum;
- sum1 = ip_csum_update (sum1, old_addr1.as_u32, new_addr1.as_u32,
- ip4_header_t,
- dst_address /* changed member */);
- sum1 = ip_csum_update (sum1, old_port1, new_port1,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp1->checksum = ip_csum_fold(sum1);
- }
- else
- {
- ses1->state = SNAT_SESSION_UDP_ACTIVE;
- old_port1 = udp1->src_port;
- udp1->src_port = new_port1;
- udp1->checksum = 0;
- }
-
- switch(ses1->state)
- {
- case SNAT_SESSION_UDP_ACTIVE:
- ses1->expire = now + sm->udp_timeout;
- break;
- case SNAT_SESSION_TCP_SYN_SENT:
- case SNAT_SESSION_TCP_FIN_WAIT:
- case SNAT_SESSION_TCP_CLOSE_WAIT:
- case SNAT_SESSION_TCP_LAST_ACK:
- ses1->expire = now + sm->tcp_transitory_timeout;
- break;
- case SNAT_SESSION_TCP_ESTABLISHED:
- ses1->expire = now + sm->tcp_established_timeout;
- break;
- }
-
- trace1:
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b1->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_in2out_trace_t *t =
- vlib_add_trace (vm, node, b1, sizeof (*t));
- t->is_slow_path = 0;
- t->sw_if_index = sw_if_index1;
- t->next_index = next1;
- t->session_index = ~0;
- if (ses1)
- t->session_index = ses1 - dm1->sessions;
- }
-
- pkts_processed += next1 != SNAT_IN2OUT_NEXT_DROP;
-
- /* verify speculative enqueues, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, bi1, next0, next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t * b0;
- u32 next0;
- u32 sw_if_index0;
- ip4_header_t * ip0;
- ip_csum_t sum0;
- ip4_address_t new_addr0, old_addr0;
- u16 old_port0, new_port0, lo_port0, i0;
- udp_header_t * udp0;
- tcp_header_t * tcp0;
- u32 proto0;
- snat_det_out_key_t key0;
- snat_det_map_t * dm0;
- snat_det_session_t * ses0 = 0;
- u32 rx_fib_index0;
- icmp46_header_t * icmp0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
- next0 = SNAT_IN2OUT_NEXT_LOOKUP;
-
- ip0 = vlib_buffer_get_current (b0);
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
-
- if (PREDICT_FALSE(ip0->ttl == 1))
- {
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
- goto trace00;
- }
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- if (PREDICT_FALSE(proto0 == SNAT_PROTOCOL_ICMP))
- {
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0);
- icmp0 = (icmp46_header_t *) udp0;
-
- next0 = icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
- rx_fib_index0, node, next0, thread_index,
- &ses0, &dm0);
- goto trace00;
- }
-
- dm0 = snat_det_map_by_user(sm, &ip0->src_address);
- if (PREDICT_FALSE(!dm0))
- {
- clib_warning("no match for internal host %U",
- format_ip4_address, &ip0->src_address);
- next0 = SNAT_IN2OUT_NEXT_DROP;
- b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
- goto trace00;
- }
-
- snat_det_forward(dm0, &ip0->src_address, &new_addr0, &lo_port0);
-
- key0.ext_host_addr = ip0->dst_address;
- key0.ext_host_port = tcp0->dst;
-
- ses0 = snat_det_find_ses_by_in(dm0, &ip0->src_address, tcp0->src, key0);
- if (PREDICT_FALSE(!ses0))
- {
- for (i0 = 0; i0 < dm0->ports_per_host; i0++)
- {
- key0.out_port = clib_host_to_net_u16 (lo_port0 +
- ((i0 + clib_net_to_host_u16 (tcp0->src)) % dm0->ports_per_host));
-
- if (snat_det_get_ses_by_out (dm0, &ip0->src_address, key0.as_u64))
- continue;
-
- ses0 = snat_det_ses_create(dm0, &ip0->src_address, tcp0->src, &key0);
- break;
- }
- if (PREDICT_FALSE(!ses0))
- {
- /* too many sessions for user, send ICMP error packet */
-
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_destination_unreachable,
- ICMP4_destination_unreachable_destination_unreachable_host,
- 0);
- next0 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
- goto trace00;
- }
- }
-
- new_port0 = ses0->out.out_port;
-
- old_addr0.as_u32 = ip0->src_address.as_u32;
- ip0->src_address.as_u32 = new_addr0.as_u32;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm->outside_fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
- ip4_header_t,
- src_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- if (tcp0->flags & TCP_FLAG_SYN)
- ses0->state = SNAT_SESSION_TCP_SYN_SENT;
- else if (tcp0->flags & TCP_FLAG_ACK && ses0->state == SNAT_SESSION_TCP_SYN_SENT)
- ses0->state = SNAT_SESSION_TCP_ESTABLISHED;
- else if (tcp0->flags & TCP_FLAG_FIN && ses0->state == SNAT_SESSION_TCP_ESTABLISHED)
- ses0->state = SNAT_SESSION_TCP_FIN_WAIT;
- else if (tcp0->flags & TCP_FLAG_ACK && ses0->state == SNAT_SESSION_TCP_FIN_WAIT)
- snat_det_ses_close(dm0, ses0);
- else if (tcp0->flags & TCP_FLAG_FIN && ses0->state == SNAT_SESSION_TCP_CLOSE_WAIT)
- ses0->state = SNAT_SESSION_TCP_LAST_ACK;
- else if (tcp0->flags == 0 && ses0->state == SNAT_SESSION_UNKNOWN)
- ses0->state = SNAT_SESSION_TCP_ESTABLISHED;
-
- old_port0 = tcp0->src;
- tcp0->src = new_port0;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
- ip4_header_t,
- dst_address /* changed member */);
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- ses0->state = SNAT_SESSION_UDP_ACTIVE;
- old_port0 = udp0->src_port;
- udp0->src_port = new_port0;
- udp0->checksum = 0;
- }
-
- switch(ses0->state)
- {
- case SNAT_SESSION_UDP_ACTIVE:
- ses0->expire = now + sm->udp_timeout;
- break;
- case SNAT_SESSION_TCP_SYN_SENT:
- case SNAT_SESSION_TCP_FIN_WAIT:
- case SNAT_SESSION_TCP_CLOSE_WAIT:
- case SNAT_SESSION_TCP_LAST_ACK:
- ses0->expire = now + sm->tcp_transitory_timeout;
- break;
- case SNAT_SESSION_TCP_ESTABLISHED:
- ses0->expire = now + sm->tcp_established_timeout;
- break;
- }
-
- trace00:
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_in2out_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->is_slow_path = 0;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- t->session_index = ~0;
- if (ses0)
- t->session_index = ses0 - dm0->sessions;
- }
-
- pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP;
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vlib_node_increment_counter (vm, snat_det_in2out_node.index,
- SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
- pkts_processed);
- return frame->n_vectors;
-}
-
-VLIB_REGISTER_NODE (snat_det_in2out_node) = {
- .function = snat_det_in2out_node_fn,
- .name = "snat-det-in2out",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_in2out_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_errors = ARRAY_LEN(snat_in2out_error_strings),
- .error_strings = snat_in2out_error_strings,
-
- .runtime_data_bytes = sizeof (snat_runtime_t),
-
- .n_next_nodes = 3,
-
- /* edit / add dispositions here */
- .next_nodes = {
- [SNAT_IN2OUT_NEXT_DROP] = "error-drop",
- [SNAT_IN2OUT_NEXT_LOOKUP] = "ip4-lookup",
- [SNAT_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_det_in2out_node, snat_det_in2out_node_fn);
-
-/**
- * Get address and port values to be used for packet SNAT translation
- * and create session if needed
- *
- * @param[in,out] sm SNAT main
- * @param[in,out] node SNAT node runtime
- * @param[in] thread_index thread index
- * @param[in,out] b0 buffer containing packet to be translated
- * @param[out] p_proto protocol used for matching
- * @param[out] p_value address and port after NAT translation
- * @param[out] p_dont_translate if packet should not be translated
- * @param d optional parameter
- * @param e optional parameter
- */
-u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e)
-{
- ip4_header_t *ip0;
- icmp46_header_t *icmp0;
- u32 sw_if_index0;
- u32 rx_fib_index0;
- u8 protocol;
- snat_det_out_key_t key0;
- u8 dont_translate = 0;
- u32 next0 = ~0;
- icmp_echo_header_t *echo0, *inner_echo0 = 0;
- ip4_header_t *inner_ip0;
- void *l4_header = 0;
- icmp46_header_t *inner_icmp0;
- snat_det_map_t * dm0 = 0;
- ip4_address_t new_addr0;
- u16 lo_port0, i0;
- snat_det_session_t * ses0 = 0;
- ip4_address_t in_addr;
- u16 in_port;
-
- ip0 = vlib_buffer_get_current (b0);
- icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
- echo0 = (icmp_echo_header_t *)(icmp0+1);
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
-
- if (!icmp_is_error_message (icmp0))
- {
- protocol = SNAT_PROTOCOL_ICMP;
- in_addr = ip0->src_address;
- in_port = echo0->identifier;
- }
- else
- {
- inner_ip0 = (ip4_header_t *)(echo0+1);
- l4_header = ip4_next_header (inner_ip0);
- protocol = ip_proto_to_snat_proto (inner_ip0->protocol);
- in_addr = inner_ip0->dst_address;
- switch (protocol)
- {
- case SNAT_PROTOCOL_ICMP:
- inner_icmp0 = (icmp46_header_t*)l4_header;
- inner_echo0 = (icmp_echo_header_t *)(inner_icmp0+1);
- in_port = inner_echo0->identifier;
- break;
- case SNAT_PROTOCOL_UDP:
- case SNAT_PROTOCOL_TCP:
- in_port = ((tcp_udp_header_t*)l4_header)->dst_port;
- break;
- default:
- b0->error = node->errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
- }
-
- dm0 = snat_det_map_by_user(sm, &in_addr);
- if (PREDICT_FALSE(!dm0))
- {
- clib_warning("no match for internal host %U",
- format_ip4_address, &in_addr);
- if (PREDICT_FALSE(snat_not_translate_fast(sm, node, sw_if_index0, ip0,
- IP_PROTOCOL_ICMP, rx_fib_index0)))
- {
- dont_translate = 1;
- goto out;
- }
- next0 = SNAT_IN2OUT_NEXT_DROP;
- b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
- goto out;
- }
-
- snat_det_forward(dm0, &in_addr, &new_addr0, &lo_port0);
-
- key0.ext_host_addr = ip0->dst_address;
- key0.ext_host_port = 0;
-
- ses0 = snat_det_find_ses_by_in(dm0, &in_addr, in_port, key0);
- if (PREDICT_FALSE(!ses0))
- {
- if (PREDICT_FALSE(snat_not_translate_fast(sm, node, sw_if_index0, ip0,
- IP_PROTOCOL_ICMP, rx_fib_index0)))
- {
- dont_translate = 1;
- goto out;
- }
- if (icmp0->type != ICMP4_echo_request)
- {
- b0->error = node->errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
- for (i0 = 0; i0 < dm0->ports_per_host; i0++)
- {
- key0.out_port = clib_host_to_net_u16 (lo_port0 +
- ((i0 + clib_net_to_host_u16 (echo0->identifier)) % dm0->ports_per_host));
-
- if (snat_det_get_ses_by_out (dm0, &in_addr, key0.as_u64))
- continue;
-
- ses0 = snat_det_ses_create(dm0, &in_addr, echo0->identifier, &key0);
- break;
- }
- if (PREDICT_FALSE(!ses0))
- {
- next0 = SNAT_IN2OUT_NEXT_DROP;
- b0->error = node->errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
- goto out;
- }
- }
-
- if (PREDICT_FALSE(icmp0->type != ICMP4_echo_request &&
- !icmp_is_error_message (icmp0)))
- {
- b0->error = node->errors[SNAT_IN2OUT_ERROR_BAD_ICMP_TYPE];
- next0 = SNAT_IN2OUT_NEXT_DROP;
- goto out;
- }
-
- u32 now = (u32) vlib_time_now (sm->vlib_main);
-
- ses0->state = SNAT_SESSION_ICMP_ACTIVE;
- ses0->expire = now + sm->icmp_timeout;
-
-out:
- *p_proto = protocol;
- if (ses0)
- {
- p_value->addr = new_addr0;
- p_value->fib_index = sm->outside_fib_index;
- p_value->port = ses0->out.out_port;
- }
- *p_dont_translate = dont_translate;
- if (d)
- *(snat_det_session_t**)d = ses0;
- if (e)
- *(snat_det_map_t**)e = dm0;
- return next0;
-}
-
-/**********************/
-/*** worker handoff ***/
-/**********************/
-static inline uword
-snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame,
- u8 is_output)
-{
- snat_main_t *sm = &snat_main;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- u32 n_left_from, *from, *to_next = 0;
- static __thread vlib_frame_queue_elt_t **handoff_queue_elt_by_worker_index;
- static __thread vlib_frame_queue_t **congested_handoff_queue_by_worker_index
- = 0;
- vlib_frame_queue_elt_t *hf = 0;
- vlib_frame_t *f = 0;
- int i;
- u32 n_left_to_next_worker = 0, *to_next_worker = 0;
- u32 next_worker_index = 0;
- u32 current_worker_index = ~0;
- u32 thread_index = vlib_get_thread_index ();
- u32 fq_index;
- u32 to_node_index;
-
- ASSERT (vec_len (sm->workers));
-
- if (is_output)
- {
- fq_index = sm->fq_in2out_output_index;
- to_node_index = sm->in2out_output_node_index;
- }
- else
- {
- fq_index = sm->fq_in2out_index;
- to_node_index = sm->in2out_node_index;
- }
-
- if (PREDICT_FALSE (handoff_queue_elt_by_worker_index == 0))
- {
- vec_validate (handoff_queue_elt_by_worker_index, tm->n_vlib_mains - 1);
-
- vec_validate_init_empty (congested_handoff_queue_by_worker_index,
- sm->first_worker_index + sm->num_workers - 1,
- (vlib_frame_queue_t *) (~0));
- }
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
-
- while (n_left_from > 0)
- {
- u32 bi0;
- vlib_buffer_t *b0;
- u32 sw_if_index0;
- u32 rx_fib_index0;
- ip4_header_t * ip0;
- u8 do_handoff;
-
- bi0 = from[0];
- from += 1;
- n_left_from -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0);
-
- ip0 = vlib_buffer_get_current (b0);
-
- next_worker_index = sm->worker_in2out_cb(ip0, rx_fib_index0);
-
- if (PREDICT_FALSE (next_worker_index != thread_index))
- {
- do_handoff = 1;
-
- if (next_worker_index != current_worker_index)
- {
- if (hf)
- hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker;
-
- hf = vlib_get_worker_handoff_queue_elt (fq_index,
- next_worker_index,
- handoff_queue_elt_by_worker_index);
-
- n_left_to_next_worker = VLIB_FRAME_SIZE - hf->n_vectors;
- to_next_worker = &hf->buffer_index[hf->n_vectors];
- current_worker_index = next_worker_index;
- }
-
- /* enqueue to correct worker thread */
- to_next_worker[0] = bi0;
- to_next_worker++;
- n_left_to_next_worker--;
-
- if (n_left_to_next_worker == 0)
- {
- hf->n_vectors = VLIB_FRAME_SIZE;
- vlib_put_frame_queue_elt (hf);
- current_worker_index = ~0;
- handoff_queue_elt_by_worker_index[next_worker_index] = 0;
- hf = 0;
- }
- }
- else
- {
- do_handoff = 0;
- /* if this is 1st frame */
- if (!f)
- {
- f = vlib_get_frame_to_node (vm, to_node_index);
- to_next = vlib_frame_vector_args (f);
- }
-
- to_next[0] = bi0;
- to_next += 1;
- f->n_vectors++;
- }
-
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_in2out_worker_handoff_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->next_worker_index = next_worker_index;
- t->do_handoff = do_handoff;
- }
- }
-
- if (f)
- vlib_put_frame_to_node (vm, to_node_index, f);
-
- if (hf)
- hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker;
-
- /* Ship frames to the worker nodes */
- for (i = 0; i < vec_len (handoff_queue_elt_by_worker_index); i++)
- {
- if (handoff_queue_elt_by_worker_index[i])
- {
- hf = handoff_queue_elt_by_worker_index[i];
- /*
- * It works better to let the handoff node
- * rate-adapt, always ship the handoff queue element.
- */
- if (1 || hf->n_vectors == hf->last_n_vectors)
- {
- vlib_put_frame_queue_elt (hf);
- handoff_queue_elt_by_worker_index[i] = 0;
- }
- else
- hf->last_n_vectors = hf->n_vectors;
- }
- congested_handoff_queue_by_worker_index[i] =
- (vlib_frame_queue_t *) (~0);
- }
- hf = 0;
- current_worker_index = ~0;
- return frame->n_vectors;
-}
-
-static uword
-snat_in2out_worker_handoff_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return snat_in2out_worker_handoff_fn_inline (vm, node, frame, 0);
-}
-
-VLIB_REGISTER_NODE (snat_in2out_worker_handoff_node) = {
- .function = snat_in2out_worker_handoff_fn,
- .name = "snat-in2out-worker-handoff",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_in2out_worker_handoff_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_next_nodes = 1,
-
- .next_nodes = {
- [0] = "error-drop",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_in2out_worker_handoff_node,
- snat_in2out_worker_handoff_fn);
-
-static uword
-snat_in2out_output_worker_handoff_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return snat_in2out_worker_handoff_fn_inline (vm, node, frame, 1);
-}
-
-VLIB_REGISTER_NODE (snat_in2out_output_worker_handoff_node) = {
- .function = snat_in2out_output_worker_handoff_fn,
- .name = "snat-in2out-output-worker-handoff",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_in2out_worker_handoff_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_next_nodes = 1,
-
- .next_nodes = {
- [0] = "error-drop",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_in2out_output_worker_handoff_node,
- snat_in2out_output_worker_handoff_fn);
-
-static_always_inline int
-is_hairpinning (snat_main_t *sm, ip4_address_t * dst_addr)
-{
- snat_address_t * ap;
- clib_bihash_kv_8_8_t kv, value;
- snat_session_key_t m_key;
-
- vec_foreach (ap, sm->addresses)
- {
- if (ap->addr.as_u32 == dst_addr->as_u32)
- return 1;
- }
-
- m_key.addr.as_u32 = dst_addr->as_u32;
- m_key.fib_index = sm->outside_fib_index;
- m_key.port = 0;
- m_key.protocol = 0;
- kv.key = m_key.as_u64;
- if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
- return 1;
-
- return 0;
-}
-
-static uword
-snat_hairpin_dst_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- u32 n_left_from, * from, * to_next;
- snat_in2out_next_t next_index;
- u32 pkts_processed = 0;
- snat_main_t * sm = &snat_main;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t * b0;
- u32 next0;
- ip4_header_t * ip0;
- u32 proto0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
- next0 = SNAT_IN2OUT_NEXT_LOOKUP;
- ip0 = vlib_buffer_get_current (b0);
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- vnet_buffer (b0)->snat.flags = 0;
- if (PREDICT_FALSE (is_hairpinning (sm, &ip0->dst_address)))
- {
- if (proto0 == SNAT_PROTOCOL_TCP || proto0 == SNAT_PROTOCOL_UDP)
- {
- udp_header_t * udp0 = ip4_next_header (ip0);
- tcp_header_t * tcp0 = (tcp_header_t *) udp0;
-
- snat_hairpinning (sm, b0, ip0, udp0, tcp0, proto0);
- }
- else if (proto0 == SNAT_PROTOCOL_ICMP)
- {
- icmp46_header_t * icmp0 = ip4_next_header (ip0);
-
- snat_icmp_hairpinning (sm, b0, ip0, icmp0);
- }
- else
- {
- snat_hairpinning_unknown_proto (sm, b0, ip0);
- }
-
- vnet_buffer (b0)->snat.flags = SNAT_FLAG_HAIRPINNING;
- clib_warning("is hairpinning");
- }
-
- pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP;
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vlib_node_increment_counter (vm, snat_hairpin_dst_node.index,
- SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
- pkts_processed);
- return frame->n_vectors;
-}
-
-VLIB_REGISTER_NODE (snat_hairpin_dst_node) = {
- .function = snat_hairpin_dst_fn,
- .name = "snat-hairpin-dst",
- .vector_size = sizeof (u32),
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(snat_in2out_error_strings),
- .error_strings = snat_in2out_error_strings,
- .n_next_nodes = 2,
- .next_nodes = {
- [SNAT_IN2OUT_NEXT_DROP] = "error-drop",
- [SNAT_IN2OUT_NEXT_LOOKUP] = "ip4-lookup",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_hairpin_dst_node,
- snat_hairpin_dst_fn);
-
-static uword
-snat_hairpin_src_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- u32 n_left_from, * from, * to_next;
- snat_in2out_next_t next_index;
- u32 pkts_processed = 0;
- snat_main_t *sm = &snat_main;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t * b0;
- u32 next0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
- next0 = SNAT_HAIRPIN_SRC_NEXT_INTERFACE_OUTPUT;
-
- if (PREDICT_FALSE ((vnet_buffer (b0)->snat.flags) & SNAT_FLAG_HAIRPINNING))
- {
- if (PREDICT_TRUE (sm->num_workers > 1))
- next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH;
- else
- next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT;
- }
-
- pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP;
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vlib_node_increment_counter (vm, snat_hairpin_src_node.index,
- SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
- pkts_processed);
- return frame->n_vectors;
-}
-
-VLIB_REGISTER_NODE (snat_hairpin_src_node) = {
- .function = snat_hairpin_src_fn,
- .name = "snat-hairpin-src",
- .vector_size = sizeof (u32),
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(snat_in2out_error_strings),
- .error_strings = snat_in2out_error_strings,
- .n_next_nodes = SNAT_HAIRPIN_SRC_N_NEXT,
- .next_nodes = {
- [SNAT_HAIRPIN_SRC_NEXT_DROP] = "error-drop",
- [SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT] = "snat-in2out-output",
- [SNAT_HAIRPIN_SRC_NEXT_INTERFACE_OUTPUT] = "interface-output",
- [SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH] = "snat-in2out-output-worker-handoff",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_hairpin_src_node,
- snat_hairpin_src_fn);
-
-static uword
-snat_in2out_fast_static_map_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- u32 n_left_from, * from, * to_next;
- snat_in2out_next_t next_index;
- u32 pkts_processed = 0;
- snat_main_t * sm = &snat_main;
- u32 stats_node_index;
-
- stats_node_index = snat_in2out_fast_node.index;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t * b0;
- u32 next0;
- u32 sw_if_index0;
- ip4_header_t * ip0;
- ip_csum_t sum0;
- u32 new_addr0, old_addr0;
- u16 old_port0, new_port0;
- udp_header_t * udp0;
- tcp_header_t * tcp0;
- icmp46_header_t * icmp0;
- snat_session_key_t key0, sm0;
- u32 proto0;
- u32 rx_fib_index0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
- next0 = SNAT_IN2OUT_NEXT_LOOKUP;
-
- ip0 = vlib_buffer_get_current (b0);
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
- icmp0 = (icmp46_header_t *) udp0;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0);
-
- if (PREDICT_FALSE(ip0->ttl == 1))
- {
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
- goto trace0;
- }
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- if (PREDICT_FALSE (proto0 == ~0))
- goto trace0;
-
- if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
- {
- next0 = icmp_in2out(sm, b0, ip0, icmp0, sw_if_index0,
- rx_fib_index0, node, next0, ~0, 0, 0);
- goto trace0;
- }
-
- key0.addr = ip0->src_address;
- key0.port = udp0->src_port;
- key0.fib_index = rx_fib_index0;
-
- if (snat_static_mapping_match(sm, key0, &sm0, 0, 0))
- {
- b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
- next0= SNAT_IN2OUT_NEXT_DROP;
- goto trace0;
- }
-
- new_addr0 = sm0.addr.as_u32;
- new_port0 = sm0.port;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm0.fib_index;
- old_addr0 = ip0->src_address.as_u32;
- ip0->src_address.as_u32 = new_addr0;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- src_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_FALSE(new_port0 != udp0->dst_port))
- {
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- old_port0 = tcp0->src_port;
- tcp0->src_port = new_port0;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- old_port0 = udp0->src_port;
- udp0->src_port = new_port0;
- udp0->checksum = 0;
- }
- }
- else
- {
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- }
-
- /* Hairpinning */
- snat_hairpinning (sm, b0, ip0, udp0, tcp0, proto0);
-
- trace0:
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_in2out_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- }
-
- pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP;
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vlib_node_increment_counter (vm, stats_node_index,
- SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
- pkts_processed);
- return frame->n_vectors;
-}
-
-
-VLIB_REGISTER_NODE (snat_in2out_fast_node) = {
- .function = snat_in2out_fast_static_map_fn,
- .name = "snat-in2out-fast",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_in2out_fast_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_errors = ARRAY_LEN(snat_in2out_error_strings),
- .error_strings = snat_in2out_error_strings,
-
- .runtime_data_bytes = sizeof (snat_runtime_t),
-
- .n_next_nodes = SNAT_IN2OUT_N_NEXT,
-
- /* edit / add dispositions here */
- .next_nodes = {
- [SNAT_IN2OUT_NEXT_DROP] = "error-drop",
- [SNAT_IN2OUT_NEXT_LOOKUP] = "ip4-lookup",
- [SNAT_IN2OUT_NEXT_SLOW_PATH] = "snat-in2out-slowpath",
- [SNAT_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_in2out_fast_node, snat_in2out_fast_static_map_fn);
diff --git a/src/plugins/snat/nat64.c b/src/plugins/snat/nat64.c
deleted file mode 100644
index bd915b590d0..00000000000
--- a/src/plugins/snat/nat64.c
+++ /dev/null
@@ -1,858 +0,0 @@
-/*
- * Copyright (c) 2017 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.
- */
-/**
- * @file
- * @brief NAT64 implementation
- */
-
-#include <snat/nat64.h>
-#include <snat/nat64_db.h>
-#include <vnet/fib/ip4_fib.h>
-
-
-nat64_main_t nat64_main;
-
-/* *INDENT-OFF* */
-
-/* Hook up input features */
-VNET_FEATURE_INIT (nat64_in2out, static) = {
- .arc_name = "ip6-unicast",
- .node_name = "nat64-in2out",
- .runs_before = VNET_FEATURES ("ip6-lookup"),
-};
-VNET_FEATURE_INIT (nat64_out2in, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "nat64-out2in",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
-};
-
-static u8 well_known_prefix[] = {
- 0x00, 0x64, 0xff, 0x9b,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-/* *INDENT-ON* */
-
-clib_error_t *
-nat64_init (vlib_main_t * vm)
-{
- nat64_main_t *nm = &nat64_main;
- clib_error_t *error = 0;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
-
- nm->is_disabled = 0;
-
- if (tm->n_vlib_mains > 1)
- {
- nm->is_disabled = 1;
- goto error;
- }
-
- if (nat64_db_init (&nm->db))
- {
- error = clib_error_return (0, "NAT64 DB init failed");
- goto error;
- }
-
- /* set session timeouts to default values */
- nm->udp_timeout = SNAT_UDP_TIMEOUT;
- nm->icmp_timeout = SNAT_ICMP_TIMEOUT;
- nm->tcp_trans_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
- nm->tcp_est_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
- nm->tcp_incoming_syn_timeout = SNAT_TCP_INCOMING_SYN;
-
-error:
- return error;
-}
-
-int
-nat64_add_del_pool_addr (ip4_address_t * addr, u32 vrf_id, u8 is_add)
-{
- nat64_main_t *nm = &nat64_main;
- snat_address_t *a = 0;
- snat_interface_t *interface;
- int i;
-
- /* Check if address already exists */
- for (i = 0; i < vec_len (nm->addr_pool); i++)
- {
- if (nm->addr_pool[i].addr.as_u32 == addr->as_u32)
- {
- a = nm->addr_pool + i;
- break;
- }
- }
-
- if (is_add)
- {
- if (a)
- return VNET_API_ERROR_VALUE_EXIST;
-
- vec_add2 (nm->addr_pool, a, 1);
- a->addr = *addr;
- a->fib_index = 0;
- if (vrf_id != ~0)
- a->fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id);
-#define _(N, i, n, s) \
- clib_bitmap_alloc (a->busy_##n##_port_bitmap, 65535);
- foreach_snat_protocol
-#undef _
- }
- else
- {
- if (!a)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- if (a->fib_index)
- fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP6);
-
-#define _(N, id, n, s) \
- clib_bitmap_free (a->busy_##n##_port_bitmap);
- foreach_snat_protocol
-#undef _
- /* Delete sessions using address */
- nat64_db_free_out_addr (&nm->db, &a->addr);
- vec_del1 (nm->addr_pool, i);
- }
-
- /* Add/del external address to FIB */
- /* *INDENT-OFF* */
- pool_foreach (interface, nm->interfaces,
- ({
- if (interface->is_inside)
- continue;
-
- snat_add_del_addr_to_fib (addr, 32, interface->sw_if_index, is_add);
- break;
- }));
- /* *INDENT-ON* */
-
- return 0;
-}
-
-void
-nat64_pool_addr_walk (nat64_pool_addr_walk_fn_t fn, void *ctx)
-{
- nat64_main_t *nm = &nat64_main;
- snat_address_t *a = 0;
-
- /* *INDENT-OFF* */
- vec_foreach (a, nm->addr_pool)
- {
- if (fn (a, ctx))
- break;
- };
- /* *INDENT-ON* */
-}
-
-int
-nat64_add_del_interface (u32 sw_if_index, u8 is_inside, u8 is_add)
-{
- nat64_main_t *nm = &nat64_main;
- snat_interface_t *interface = 0, *i;
- snat_address_t *ap;
- const char *feature_name, *arc_name;
-
- /* Check if address already exists */
- /* *INDENT-OFF* */
- pool_foreach (i, nm->interfaces,
- ({
- if (i->sw_if_index == sw_if_index)
- {
- interface = i;
- break;
- }
- }));
- /* *INDENT-ON* */
-
- if (is_add)
- {
- if (interface)
- return VNET_API_ERROR_VALUE_EXIST;
-
- pool_get (nm->interfaces, interface);
- interface->sw_if_index = sw_if_index;
- interface->is_inside = is_inside;
-
- }
- else
- {
- if (!interface)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- pool_put (nm->interfaces, interface);
- }
-
- if (!is_inside)
- {
- /* *INDENT-OFF* */
- vec_foreach (ap, nm->addr_pool)
- snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, is_add);
- /* *INDENT-ON* */
- }
-
- arc_name = is_inside ? "ip6-unicast" : "ip4-unicast";
- feature_name = is_inside ? "nat64-in2out" : "nat64-out2in";
-
- return vnet_feature_enable_disable (arc_name, feature_name, sw_if_index,
- is_add, 0, 0);
-}
-
-void
-nat64_interfaces_walk (nat64_interface_walk_fn_t fn, void *ctx)
-{
- nat64_main_t *nm = &nat64_main;
- snat_interface_t *i = 0;
-
- /* *INDENT-OFF* */
- pool_foreach (i, nm->interfaces,
- ({
- if (fn (i, ctx))
- break;
- }));
- /* *INDENT-ON* */
-}
-
-int
-nat64_alloc_out_addr_and_port (u32 fib_index, snat_protocol_t proto,
- ip4_address_t * addr, u16 * port)
-{
- nat64_main_t *nm = &nat64_main;
- snat_main_t *sm = &snat_main;
- int i;
- snat_address_t *a, *ga = 0;
- u32 portnum;
-
- for (i = 0; i < vec_len (nm->addr_pool); i++)
- {
- a = nm->addr_pool + i;
- switch (proto)
- {
-#define _(N, j, n, s) \
- case SNAT_PROTOCOL_##N: \
- if (a->busy_##n##_ports < (65535-1024)) \
- { \
- if (a->fib_index == fib_index) \
- { \
- while (1) \
- { \
- portnum = random_u32 (&sm->random_seed); \
- portnum &= 0xFFFF; \
- if (portnum < 1024) \
- continue; \
- if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
- portnum)) \
- continue; \
- clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
- portnum, 1); \
- a->busy_##n##_ports++; \
- *port = portnum; \
- addr->as_u32 = a->addr.as_u32; \
- return 0; \
- } \
- } \
- else if (a->fib_index == 0) \
- ga = a; \
- } \
- break;
- foreach_snat_protocol
-#undef _
- default:
- clib_warning ("unknown protocol");
- return 1;
- }
- }
-
- if (ga)
- {
- switch (proto)
- {
-#define _(N, j, n, s) \
- case SNAT_PROTOCOL_##N: \
- while (1) \
- { \
- portnum = random_u32 (&sm->random_seed); \
- portnum &= 0xFFFF; \
- if (portnum < 1024) \
- continue; \
- if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
- portnum)) \
- continue; \
- clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
- portnum, 1); \
- a->busy_##n##_ports++; \
- *port = portnum; \
- addr->as_u32 = a->addr.as_u32; \
- return 0; \
- }
- break;
- foreach_snat_protocol
-#undef _
- default:
- clib_warning ("unknown protocol");
- return 1;
- }
- }
-
- /* Totally out of translations to use... */
- //TODO: IPFix
- return 1;
-}
-
-void
-nat64_free_out_addr_and_port (ip4_address_t * addr, u16 port,
- snat_protocol_t proto)
-{
- nat64_main_t *nm = &nat64_main;
- int i;
- snat_address_t *a;
-
- for (i = 0; i < vec_len (nm->addr_pool); i++)
- {
- a = nm->addr_pool + i;
- if (addr->as_u32 != a->addr.as_u32)
- continue;
- switch (proto)
- {
-#define _(N, j, n, s) \
- case SNAT_PROTOCOL_##N: \
- ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
- port) == 1); \
- clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, port, 0); \
- a->busy_##n##_ports--; \
- break;
- foreach_snat_protocol
-#undef _
- default:
- clib_warning ("unknown protocol");
- return;
- }
- break;
- }
-}
-
-int
-nat64_add_del_static_bib_entry (ip6_address_t * in_addr,
- ip4_address_t * out_addr, u16 in_port,
- u16 out_port, u8 proto, u32 vrf_id, u8 is_add)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_db_bib_entry_t *bibe;
- u32 fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id);
- snat_protocol_t p = ip_proto_to_snat_proto (proto);
- ip46_address_t addr;
- int i;
- snat_address_t *a;
-
- addr.as_u64[0] = in_addr->as_u64[0];
- addr.as_u64[1] = in_addr->as_u64[1];
- bibe =
- nat64_db_bib_entry_find (&nm->db, &addr, clib_host_to_net_u16 (in_port),
- proto, fib_index, 1);
-
- if (is_add)
- {
- if (bibe)
- return VNET_API_ERROR_VALUE_EXIST;
-
- for (i = 0; i < vec_len (nm->addr_pool); i++)
- {
- a = nm->addr_pool + i;
- if (out_addr->as_u32 != a->addr.as_u32)
- continue;
- switch (p)
- {
-#define _(N, j, n, s) \
- case SNAT_PROTOCOL_##N: \
- if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
- out_port)) \
- return VNET_API_ERROR_INVALID_VALUE; \
- clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
- out_port, 1); \
- if (out_port > 1024) \
- a->busy_##n##_ports++; \
- break;
- foreach_snat_protocol
-#undef _
- default:
- memset (&addr, 0, sizeof (addr));
- addr.ip4.as_u32 = out_addr->as_u32;
- if (nat64_db_bib_entry_find
- (&nm->db, &addr, 0, proto, fib_index, 0))
- return VNET_API_ERROR_INVALID_VALUE;
- }
- break;
- }
- bibe =
- nat64_db_bib_entry_create (&nm->db, in_addr, out_addr,
- clib_host_to_net_u16 (in_port),
- clib_host_to_net_u16 (out_port), fib_index,
- proto, 1);
- if (!bibe)
- return VNET_API_ERROR_UNSPECIFIED;
- }
- else
- {
- if (!bibe)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- nat64_free_out_addr_and_port (out_addr, out_port, p);
- nat64_db_bib_entry_free (&nm->db, bibe);
- }
-
- return 0;
-}
-
-int
-nat64_set_udp_timeout (u32 timeout)
-{
- nat64_main_t *nm = &nat64_main;
-
- if (timeout == 0)
- nm->udp_timeout = SNAT_UDP_TIMEOUT;
- else if (timeout < SNAT_UDP_TIMEOUT_MIN)
- return VNET_API_ERROR_INVALID_VALUE;
- else
- nm->udp_timeout = timeout;
-
- return 0;
-}
-
-u32
-nat64_get_udp_timeout (void)
-{
- nat64_main_t *nm = &nat64_main;
-
- return nm->udp_timeout;
-}
-
-int
-nat64_set_icmp_timeout (u32 timeout)
-{
- nat64_main_t *nm = &nat64_main;
-
- if (timeout == 0)
- nm->icmp_timeout = SNAT_ICMP_TIMEOUT;
- else
- nm->icmp_timeout = timeout;
-
- return 0;
-}
-
-u32
-nat64_get_icmp_timeout (void)
-{
- nat64_main_t *nm = &nat64_main;
-
- return nm->icmp_timeout;
-}
-
-int
-nat64_set_tcp_timeouts (u32 trans, u32 est, u32 incoming_syn)
-{
- nat64_main_t *nm = &nat64_main;
-
- if (trans == 0)
- nm->tcp_trans_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
- else
- nm->tcp_trans_timeout = trans;
-
- if (est == 0)
- nm->tcp_est_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
- else
- nm->tcp_est_timeout = est;
-
- if (incoming_syn == 0)
- nm->tcp_incoming_syn_timeout = SNAT_TCP_INCOMING_SYN;
- else
- nm->tcp_incoming_syn_timeout = incoming_syn;
-
- return 0;
-}
-
-u32
-nat64_get_tcp_trans_timeout (void)
-{
- nat64_main_t *nm = &nat64_main;
-
- return nm->tcp_trans_timeout;
-}
-
-u32
-nat64_get_tcp_est_timeout (void)
-{
- nat64_main_t *nm = &nat64_main;
-
- return nm->tcp_est_timeout;
-}
-
-u32
-nat64_get_tcp_incoming_syn_timeout (void)
-{
- nat64_main_t *nm = &nat64_main;
-
- return nm->tcp_incoming_syn_timeout;
-}
-
-void
-nat64_session_reset_timeout (nat64_db_st_entry_t * ste, vlib_main_t * vm)
-{
- nat64_main_t *nm = &nat64_main;
- u32 now = (u32) vlib_time_now (vm);
-
- switch (ip_proto_to_snat_proto (ste->proto))
- {
- case SNAT_PROTOCOL_ICMP:
- ste->expire = now + nm->icmp_timeout;
- return;
- case SNAT_PROTOCOL_TCP:
- {
- switch (ste->tcp_state)
- {
- case NAT64_TCP_STATE_V4_INIT:
- case NAT64_TCP_STATE_V6_INIT:
- case NAT64_TCP_STATE_V4_FIN_RCV:
- case NAT64_TCP_STATE_V6_FIN_RCV:
- case NAT64_TCP_STATE_V6_FIN_V4_FIN_RCV:
- case NAT64_TCP_STATE_TRANS:
- ste->expire = now + nm->tcp_trans_timeout;
- return;
- case NAT64_TCP_STATE_ESTABLISHED:
- ste->expire = now + nm->tcp_est_timeout;
- return;
- default:
- return;
- }
- }
- case SNAT_PROTOCOL_UDP:
- ste->expire = now + nm->udp_timeout;
- return;
- default:
- ste->expire = now + nm->udp_timeout;
- return;
- }
-}
-
-void
-nat64_tcp_session_set_state (nat64_db_st_entry_t * ste, tcp_header_t * tcp,
- u8 is_ip6)
-{
- switch (ste->tcp_state)
- {
- case NAT64_TCP_STATE_CLOSED:
- {
- if (tcp->flags & TCP_FLAG_SYN)
- {
- if (is_ip6)
- ste->tcp_state = NAT64_TCP_STATE_V6_INIT;
- else
- ste->tcp_state = NAT64_TCP_STATE_V4_INIT;
- }
- return;
- }
- case NAT64_TCP_STATE_V4_INIT:
- {
- if (is_ip6 && (tcp->flags & TCP_FLAG_SYN))
- ste->tcp_state = NAT64_TCP_STATE_ESTABLISHED;
- return;
- }
- case NAT64_TCP_STATE_V6_INIT:
- {
- if (!is_ip6 && (tcp->flags & TCP_FLAG_SYN))
- ste->tcp_state = NAT64_TCP_STATE_ESTABLISHED;
- return;
- }
- case NAT64_TCP_STATE_ESTABLISHED:
- {
- if (tcp->flags & TCP_FLAG_FIN)
- {
- if (is_ip6)
- ste->tcp_state = NAT64_TCP_STATE_V6_FIN_RCV;
- else
- ste->tcp_state = NAT64_TCP_STATE_V4_FIN_RCV;
- }
- else if (tcp->flags & TCP_FLAG_RST)
- {
- ste->tcp_state = NAT64_TCP_STATE_TRANS;
- }
- return;
- }
- case NAT64_TCP_STATE_V4_FIN_RCV:
- {
- if (is_ip6 && (tcp->flags & TCP_FLAG_FIN))
- ste->tcp_state = NAT64_TCP_STATE_V6_FIN_V4_FIN_RCV;
- return;
- }
- case NAT64_TCP_STATE_V6_FIN_RCV:
- {
- if (!is_ip6 && (tcp->flags & TCP_FLAG_FIN))
- ste->tcp_state = NAT64_TCP_STATE_V6_FIN_V4_FIN_RCV;
- return;
- }
- case NAT64_TCP_STATE_TRANS:
- {
- if (!(tcp->flags & TCP_FLAG_RST))
- ste->tcp_state = NAT64_TCP_STATE_ESTABLISHED;
- return;
- }
- default:
- return;
- }
-}
-
-int
-nat64_add_del_prefix (ip6_address_t * prefix, u8 plen, u32 vrf_id, u8 is_add)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_prefix_t *p = 0;
- int i;
-
- /* Verify prefix length */
- if (plen != 32 && plen != 40 && plen != 48 && plen != 56 && plen != 64
- && plen != 96)
- return VNET_API_ERROR_INVALID_VALUE;
-
- /* Check if tenant already have prefix */
- for (i = 0; i < vec_len (nm->pref64); i++)
- {
- if (nm->pref64[i].vrf_id == vrf_id)
- {
- p = nm->pref64 + i;
- break;
- }
- }
-
- if (is_add)
- {
- if (!p)
- {
- vec_add2 (nm->pref64, p, 1);
- p->fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id);
- p->vrf_id = vrf_id;
- }
-
- p->prefix.as_u64[0] = prefix->as_u64[0];
- p->prefix.as_u64[1] = prefix->as_u64[1];
- p->plen = plen;
- }
- else
- {
- if (!p)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- vec_del1 (nm->pref64, i);
- }
-
- return 0;
-}
-
-void
-nat64_prefix_walk (nat64_prefix_walk_fn_t fn, void *ctx)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_prefix_t *p = 0;
-
- /* *INDENT-OFF* */
- vec_foreach (p, nm->pref64)
- {
- if (fn (p, ctx))
- break;
- };
- /* *INDENT-ON* */
-}
-
-void
-nat64_compose_ip6 (ip6_address_t * ip6, ip4_address_t * ip4, u32 fib_index)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_prefix_t *p, *gp = 0, *prefix = 0;
-
- /* *INDENT-OFF* */
- vec_foreach (p, nm->pref64)
- {
- if (p->fib_index == fib_index)
- {
- prefix = p;
- break;
- }
-
- if (p->fib_index == 0)
- gp = p;
- };
- /* *INDENT-ON* */
-
- if (!prefix)
- prefix = gp;
-
- if (prefix)
- {
- memset (ip6, 0, 16);
- memcpy (ip6, &p->prefix, p->plen);
- switch (p->plen)
- {
- case 32:
- ip6->as_u32[1] = ip4->as_u32;
- break;
- case 40:
- ip6->as_u8[5] = ip4->as_u8[0];
- ip6->as_u8[6] = ip4->as_u8[1];
- ip6->as_u8[7] = ip4->as_u8[2];
- ip6->as_u8[9] = ip4->as_u8[3];
- break;
- case 48:
- ip6->as_u8[6] = ip4->as_u8[0];
- ip6->as_u8[7] = ip4->as_u8[1];
- ip6->as_u8[9] = ip4->as_u8[2];
- ip6->as_u8[10] = ip4->as_u8[3];
- break;
- case 56:
- ip6->as_u8[7] = ip4->as_u8[0];
- ip6->as_u8[9] = ip4->as_u8[1];
- ip6->as_u8[10] = ip4->as_u8[2];
- ip6->as_u8[11] = ip4->as_u8[3];
- break;
- case 64:
- ip6->as_u8[9] = ip4->as_u8[0];
- ip6->as_u8[10] = ip4->as_u8[1];
- ip6->as_u8[11] = ip4->as_u8[2];
- ip6->as_u8[12] = ip4->as_u8[3];
- break;
- case 96:
- ip6->as_u32[3] = ip4->as_u32;
- break;
- default:
- clib_warning ("invalid prefix length");
- break;
- }
- }
- else
- {
- memcpy (ip6, well_known_prefix, 16);
- ip6->as_u32[3] = ip4->as_u32;
- }
-}
-
-void
-nat64_extract_ip4 (ip6_address_t * ip6, ip4_address_t * ip4, u32 fib_index)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_prefix_t *p, *gp = 0;
- u8 plen = 0;
-
- /* *INDENT-OFF* */
- vec_foreach (p, nm->pref64)
- {
- if (p->fib_index == fib_index)
- {
- plen = p->plen;
- break;
- }
-
- if (p->vrf_id == 0)
- gp = p;
- };
- /* *INDENT-ON* */
-
- if (!plen)
- {
- if (gp)
- plen = gp->plen;
- else
- plen = 96;
- }
-
- switch (plen)
- {
- case 32:
- ip4->as_u32 = ip6->as_u32[1];
- break;
- case 40:
- ip4->as_u8[0] = ip6->as_u8[5];
- ip4->as_u8[1] = ip6->as_u8[6];
- ip4->as_u8[2] = ip6->as_u8[7];
- ip4->as_u8[3] = ip6->as_u8[9];
- break;
- case 48:
- ip4->as_u8[0] = ip6->as_u8[6];
- ip4->as_u8[1] = ip6->as_u8[7];
- ip4->as_u8[2] = ip6->as_u8[9];
- ip4->as_u8[3] = ip6->as_u8[10];
- break;
- case 56:
- ip4->as_u8[0] = ip6->as_u8[7];
- ip4->as_u8[1] = ip6->as_u8[9];
- ip4->as_u8[2] = ip6->as_u8[10];
- ip4->as_u8[3] = ip6->as_u8[11];
- break;
- case 64:
- ip4->as_u8[0] = ip6->as_u8[9];
- ip4->as_u8[1] = ip6->as_u8[10];
- ip4->as_u8[2] = ip6->as_u8[11];
- ip4->as_u8[3] = ip6->as_u8[12];
- break;
- case 96:
- ip4->as_u32 = ip6->as_u32[3];
- break;
- default:
- clib_warning ("invalid prefix length");
- break;
- }
-}
-
-/**
- * @brief The 'nat64-expire-walk' process's main loop.
- *
- * Check expire time for NAT64 sessions.
- */
-static uword
-nat64_expire_walk_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
- vlib_frame_t * f)
-{
- nat64_main_t *nm = &nat64_main;
-
- while (!nm->is_disabled)
- {
- vlib_process_wait_for_event_or_clock (vm, 10.0);
- vlib_process_get_events (vm, NULL);
- u32 now = (u32) vlib_time_now (vm);
-
- nad64_db_st_free_expired (&nm->db, now);
- }
-
- return 0;
-}
-
-static vlib_node_registration_t nat64_expire_walk_node;
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (nat64_expire_walk_node, static) = {
- .function = nat64_expire_walk_fn,
- .type = VLIB_NODE_TYPE_PROCESS,
- .name = "nat64-expire-walk",
-};
-/* *INDENT-ON* */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/plugins/snat/nat64.h b/src/plugins/snat/nat64.h
deleted file mode 100644
index 771b9075405..00000000000
--- a/src/plugins/snat/nat64.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (c) 2017 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.
- */
-/**
- * @file
- * @brief NAT64 global declarations
- */
-#ifndef __included_nat64_h__
-#define __included_nat64_h__
-
-#include <snat/snat.h>
-#include <snat/nat64_db.h>
-
-#define foreach_nat64_tcp_ses_state \
- _(0, CLOSED, "closed") \
- _(1, V4_INIT, "v4-init") \
- _(2, V6_INIT, "v6-init") \
- _(3, ESTABLISHED, "established") \
- _(4, V4_FIN_RCV, "v4-fin-rcv") \
- _(5, V6_FIN_RCV, "v6-fin-rcv") \
- _(6, V6_FIN_V4_FIN_RCV, "v6-fin-v4-fin-rcv") \
- _(7, TRANS, "trans")
-
-typedef enum
-{
-#define _(v, N, s) NAT64_TCP_STATE_##N = v,
- foreach_nat64_tcp_ses_state
-#undef _
-} nat64_tcp_ses_state_t;
-
-typedef struct
-{
- ip6_address_t prefix;
- u8 plen;
- u32 vrf_id;
- u32 fib_index;
-} nat64_prefix_t;
-
-typedef struct
-{
- /** Interface pool */
- snat_interface_t *interfaces;
-
- /** Address pool vector */
- snat_address_t *addr_pool;
-
- /** Pref64 vector */
- nat64_prefix_t *pref64;
-
- /** BIB and session DB */
- nat64_db_t db;
-
- /* values of various timeouts */
- u32 udp_timeout;
- u32 icmp_timeout;
- u32 tcp_trans_timeout;
- u32 tcp_est_timeout;
- u32 tcp_incoming_syn_timeout;
-
- u8 is_disabled;
-
- snat_main_t *sm;
-} nat64_main_t;
-
-extern nat64_main_t nat64_main;
-extern vlib_node_registration_t nat64_in2out_node;
-extern vlib_node_registration_t nat64_out2in_node;
-
-/**
- * @brief Add/delete address to NAT64 pool.
- *
- * @param addr IPv4 address.
- * @param vrf_id VRF id of tenant, ~0 means independent of VRF.
- * @param is_add 1 if add, 0 if delete.
- *
- * @returns 0 on success, non-zero value otherwise.
- */
-int nat64_add_del_pool_addr (ip4_address_t * addr, u32 vrf_id, u8 is_add);
-
-/**
- * @brief Call back function when walking addresses in NAT64 pool, non-zero
- * return value stop walk.
- */
-typedef int (*nat64_pool_addr_walk_fn_t) (snat_address_t * addr, void *ctx);
-
-/**
- * @brief Walk NAT64 pool.
- *
- * @param fn The function to invoke on each entry visited.
- * @param ctx A context passed in the visit function.
- */
-void nat64_pool_addr_walk (nat64_pool_addr_walk_fn_t fn, void *ctx);
-
-/**
- * @brief Enable/disable NAT64 feature on the interface.
- *
- * @param sw_if_index Index of the interface.
- * @param is_inside 1 if inside, 0 if outside.
- * @param is_add 1 if add, 0 if delete.
- *
- * @returns 0 on success, non-zero value otherwise.
- */
-int nat64_add_del_interface (u32 sw_if_index, u8 is_inside, u8 is_add);
-
-/**
- * @brief Call back function when walking interfaces with NAT64 feature,
- * non-zero return value stop walk.
- */
-typedef int (*nat64_interface_walk_fn_t) (snat_interface_t * i, void *ctx);
-
-/**
- * @brief Walk NAT64 interfaces.
- *
- * @param fn The function to invoke on each entry visited.
- * @param ctx A context passed in the visit function.
- */
-void nat64_interfaces_walk (nat64_interface_walk_fn_t fn, void *ctx);
-
-/**
- * @brief Initialize NAT64.
- *
- * @param vm vlib main.
- *
- * @return error code.
- */
-clib_error_t *nat64_init (vlib_main_t * vm);
-
-/**
- * @brief Add/delete static NAT64 BIB entry.
- *
- * @param in_addr Inside IPv6 address.
- * @param out_addr Outside IPv4 address.
- * @param in_port Inside port number.
- * @param out_port Outside port number.
- * @param proto L4 protocol.
- * @param vrf_id VRF id of tenant.
- * @param is_add 1 if add, 0 if delete.
- *
- * @returns 0 on success, non-zero value otherwise.
- */
-int nat64_add_del_static_bib_entry (ip6_address_t * in_addr,
- ip4_address_t * out_addr, u16 in_port,
- u16 out_port, u8 proto, u32 vrf_id,
- u8 is_add);
-
-/**
- * @brief Alloce IPv4 address and port pair from NAT64 pool.
- *
- * @param fib_index FIB index of tenant.
- * @param proto L4 protocol.
- * @param addr Allocated IPv4 address.
- * @param port Allocated port number.
- *
- * @returns 0 on success, non-zero value otherwise.
- */
-int nat64_alloc_out_addr_and_port (u32 fib_index, snat_protocol_t proto,
- ip4_address_t * addr, u16 * port);
-
-/**
- * @brief Free IPv4 address and port pair from NAT64 pool.
- *
- * @param addr IPv4 address to free.
- * @param port Port number to free.
- * @param proto L4 protocol.
- *
- * @returns 0 on success, non-zero value otherwise.
- */
-void nat64_free_out_addr_and_port (ip4_address_t * addr, u16 port,
- snat_protocol_t proto);
-
-/**
- * @brief Set UDP session timeout.
- *
- * @param timeout Timeout value in seconds (if 0 reset to default value 300sec).
- *
- * @returns 0 on success, non-zero value otherwise.
- */
-int nat64_set_udp_timeout (u32 timeout);
-
-/**
- * @brief Get UDP session timeout.
- *
- * @returns UDP session timeout in seconds.
- */
-u32 nat64_get_udp_timeout (void);
-
-/**
- * @brief Set ICMP session timeout.
- *
- * @param timeout Timeout value in seconds (if 0 reset to default value 60sec).
- *
- * @returns 0 on success, non-zero value otherwise.
- */
-int nat64_set_icmp_timeout (u32 timeout);
-
-/**
- * @brief Get ICMP session timeout.
- *
- * @returns ICMP session timeout in seconds.
- */
-u32 nat64_get_icmp_timeout (void);
-
-/**
- * @brief Set TCP session timeouts.
- *
- * @param trans Transitory timeout in seconds (if 0 reset to default value 240sec).
- * @param est Established timeout in seconds (if 0 reset to default value 7440sec).
- * @param incoming_syn Incoming SYN timeout in seconds (if 0 reset to default value 6sec).
- *
- * @returns 0 on success, non-zero value otherwise.
- */
-int nat64_set_tcp_timeouts (u32 trans, u32 est, u32 incoming_syn);
-
-/**
- * @brief Get TCP transitory timeout.
- *
- * @returns TCP transitory timeout in seconds.
- */
-u32 nat64_get_tcp_trans_timeout (void);
-
-/**
- * @brief Get TCP established timeout.
- *
- * @returns TCP established timeout in seconds.
- */
-u32 nat64_get_tcp_est_timeout (void);
-
-/**
- * @brief Get TCP incoming SYN timeout.
- *
- * @returns TCP incoming SYN timeout in seconds.
- */
-u32 nat64_get_tcp_incoming_syn_timeout (void);
-
-/**
- * @brief Reset NAT64 session timeout.
- *
- * @param ste Session table entry.
- * @param vm VLIB main.
- **/
-void nat64_session_reset_timeout (nat64_db_st_entry_t * ste,
- vlib_main_t * vm);
-
-/**
- * @brief Set NAT64 TCP session state.
- *
- * @param ste Session table entry.
- * @param tcp TCP header.
- * @param is_ip6 1 if IPv6 packet, 0 if IPv4.
- */
-void nat64_tcp_session_set_state (nat64_db_st_entry_t * ste,
- tcp_header_t * tcp, u8 is_ip6);
-
-/**
- * @brief Add/delete NAT64 prefix.
- *
- * @param prefix NAT64 prefix.
- * @param plen Prefix length.
- * @param vrf_id VRF id of tenant.
- * @param is_add 1 if add, 0 if delete.
- *
- * @returns 0 on success, non-zero value otherwise.
- */
-int nat64_add_del_prefix (ip6_address_t * prefix, u8 plen, u32 vrf_id,
- u8 is_add);
-
-/**
- * @brief Call back function when walking addresses in NAT64 prefixes, non-zero
- * return value stop walk.
- */
-typedef int (*nat64_prefix_walk_fn_t) (nat64_prefix_t * pref64, void *ctx);
-
-/**
- * @brief Walk NAT64 prefixes.
- *
- * @param fn The function to invoke on each entry visited.
- * @param ctx A context passed in the visit function.
- */
-void nat64_prefix_walk (nat64_prefix_walk_fn_t fn, void *ctx);
-
-/**
- * Compose IPv4-embedded IPv6 addresses.
- * @param ip6 IPv4-embedded IPv6 addresses.
- * @param ip4 IPv4 address.
- * @param fib_index Tenant FIB index.
- */
-void nat64_compose_ip6 (ip6_address_t * ip6, ip4_address_t * ip4,
- u32 fib_index);
-
-/**
- * Extract IPv4 address from the IPv4-embedded IPv6 addresses.
- *
- * @param ip6 IPv4-embedded IPv6 addresses.
- * @param ip4 IPv4 address.
- * @param fib_index Tenant FIB index.
- */
-void nat64_extract_ip4 (ip6_address_t * ip6, ip4_address_t * ip4,
- u32 fib_index);
-
-#define u8_ptr_add(ptr, index) (((u8 *)ptr) + index)
-#define u16_net_add(u, val) clib_host_to_net_u16(clib_net_to_host_u16(u) + (val))
-
-#endif /* __included_nat64_h__ */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/plugins/snat/nat64_cli.c b/src/plugins/snat/nat64_cli.c
deleted file mode 100644
index ca60b12c189..00000000000
--- a/src/plugins/snat/nat64_cli.c
+++ /dev/null
@@ -1,983 +0,0 @@
-/*
- * Copyright (c) 2017 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.
- */
-/**
- * @file
- * @brief NAT64 CLI
- */
-
-#include <snat/nat64.h>
-#include <snat/snat.h>
-#include <vnet/fib/fib_table.h>
-
-static clib_error_t *
-nat64_add_del_pool_addr_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- ip4_address_t start_addr, end_addr, this_addr;
- u32 start_host_order, end_host_order;
- int i, count, rv;
- u32 vrf_id = ~0;
- u8 is_add = 1;
- clib_error_t *error = 0;
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "%U - %U",
- unformat_ip4_address, &start_addr,
- unformat_ip4_address, &end_addr))
- ;
- else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
- ;
- else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
- end_addr = start_addr;
- else if (unformat (line_input, "del"))
- is_add = 0;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
- end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
-
- if (end_host_order < start_host_order)
- {
- error = clib_error_return (0, "end address less than start address");
- goto done;
- }
-
- count = (end_host_order - start_host_order) + 1;
- this_addr = start_addr;
-
- for (i = 0; i < count; i++)
- {
- rv = nat64_add_del_pool_addr (&this_addr, vrf_id, is_add);
-
- switch (rv)
- {
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- error =
- clib_error_return (0, "NAT64 pool address %U not exist.",
- format_ip4_address, &this_addr);
- goto done;
- case VNET_API_ERROR_VALUE_EXIST:
- error =
- clib_error_return (0, "NAT64 pool address %U exist.",
- format_ip4_address, &this_addr);
- goto done;
- default:
- break;
-
- }
- increment_v4_address (&this_addr);
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-static int
-nat64_cli_pool_walk (snat_address_t * ap, void *ctx)
-{
- vlib_main_t *vm = ctx;
-
- if (ap->fib_index != ~0)
- {
- fib_table_t *fib;
- fib = fib_table_get (ap->fib_index, FIB_PROTOCOL_IP6);
- if (!fib)
- return -1;
- vlib_cli_output (vm, " %U tenant VRF: %u", format_ip4_address,
- &ap->addr, fib->ft_table_id);
- }
- else
- vlib_cli_output (vm, " %U", format_ip4_address, &ap->addr);
-
- return 0;
-}
-
-static clib_error_t *
-nat64_show_pool_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- vlib_cli_output (vm, "NAT64 pool:");
- nat64_pool_addr_walk (nat64_cli_pool_walk, vm);
-
- return 0;
-}
-
-static clib_error_t *
-nat64_interface_feature_command_fn (vlib_main_t * vm,
- unformat_input_t *
- input, vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- vnet_main_t *vnm = vnet_get_main ();
- clib_error_t *error = 0;
- u32 sw_if_index;
- u32 *inside_sw_if_indices = 0;
- u32 *outside_sw_if_indices = 0;
- u8 is_add = 1;
- int i, rv;
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
- vnm, &sw_if_index))
- vec_add1 (inside_sw_if_indices, sw_if_index);
- else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
- vnm, &sw_if_index))
- vec_add1 (outside_sw_if_indices, sw_if_index);
- else if (unformat (line_input, "del"))
- is_add = 0;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- if (vec_len (inside_sw_if_indices))
- {
- for (i = 0; i < vec_len (inside_sw_if_indices); i++)
- {
- sw_if_index = inside_sw_if_indices[i];
- rv = nat64_add_del_interface (sw_if_index, 1, is_add);
- switch (rv)
- {
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- error =
- clib_error_return (0, "%U NAT64 feature not enabled.",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, sw_if_index));
- goto done;
- case VNET_API_ERROR_VALUE_EXIST:
- error =
- clib_error_return (0, "%U NAT64 feature already enabled.",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, sw_if_index));
- goto done;
- case VNET_API_ERROR_INVALID_VALUE:
- case VNET_API_ERROR_INVALID_VALUE_2:
- error =
- clib_error_return (0,
- "%U NAT64 feature enable/disable failed.",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, sw_if_index));
- goto done;
- default:
- break;
-
- }
- }
- }
-
- if (vec_len (outside_sw_if_indices))
- {
- for (i = 0; i < vec_len (outside_sw_if_indices); i++)
- {
- sw_if_index = outside_sw_if_indices[i];
- rv = nat64_add_del_interface (sw_if_index, 0, is_add);
- switch (rv)
- {
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- error =
- clib_error_return (0, "%U NAT64 feature not enabled.",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, sw_if_index));
- goto done;
- case VNET_API_ERROR_VALUE_EXIST:
- error =
- clib_error_return (0, "%U NAT64 feature already enabled.",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, sw_if_index));
- goto done;
- case VNET_API_ERROR_INVALID_VALUE:
- case VNET_API_ERROR_INVALID_VALUE_2:
- error =
- clib_error_return (0,
- "%U NAT64 feature enable/disable failed.",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, sw_if_index));
- goto done;
- default:
- break;
-
- }
- }
- }
-
-done:
- unformat_free (line_input);
- vec_free (inside_sw_if_indices);
- vec_free (outside_sw_if_indices);
-
- return error;
-}
-
-static int
-nat64_cli_interface_walk (snat_interface_t * i, void *ctx)
-{
- vlib_main_t *vm = ctx;
- vnet_main_t *vnm = vnet_get_main ();
-
- vlib_cli_output (vm, " %U %s", format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, i->sw_if_index),
- i->is_inside ? "in" : "out");
- return 0;
-}
-
-static clib_error_t *
-nat64_show_interfaces_command_fn (vlib_main_t * vm,
- unformat_input_t *
- input, vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- vlib_cli_output (vm, "NAT64 interfaces:");
- nat64_interfaces_walk (nat64_cli_interface_walk, vm);
-
- return 0;
-}
-
-static clib_error_t *
-nat64_add_del_static_bib_command_fn (vlib_main_t *
- vm,
- unformat_input_t
- * input, vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- clib_error_t *error = 0;
- u8 is_add = 1;
- ip6_address_t in_addr;
- ip4_address_t out_addr;
- u16 in_port = 0;
- u16 out_port = 0;
- u32 vrf_id = 0, protocol;
- snat_protocol_t proto = 0;
- u8 p = 0;
- int rv;
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "%U %u", unformat_ip6_address,
- &in_addr, &in_port))
- ;
- else if (unformat (line_input, "%U %u", unformat_ip4_address,
- &out_addr, &out_port))
- ;
- else if (unformat (line_input, "vrf %u", &vrf_id))
- ;
- else if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
- ;
- else
- if (unformat
- (line_input, "%U %U %u", unformat_ip6_address, &in_addr,
- unformat_ip4_address, &out_addr, &protocol))
- p = (u8) protocol;
- else if (unformat (line_input, "del"))
- is_add = 0;
- else
- {
- error = clib_error_return (0, "unknown input: '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- if (!p)
- {
- if (!in_port)
- {
- error =
- clib_error_return (0, "inside port and address must be set");
- goto done;
- }
-
- if (!out_port)
- {
- error =
- clib_error_return (0, "outside port and address must be set");
- goto done;
- }
-
- p = snat_proto_to_ip_proto (proto);
- }
-
- rv =
- nat64_add_del_static_bib_entry (&in_addr, &out_addr, in_port, out_port, p,
- vrf_id, is_add);
-
- switch (rv)
- {
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- error = clib_error_return (0, "NAT64 BIB entry not exist.");
- goto done;
- case VNET_API_ERROR_VALUE_EXIST:
- error = clib_error_return (0, "NAT64 BIB entry exist.");
- goto done;
- case VNET_API_ERROR_UNSPECIFIED:
- error = clib_error_return (0, "Crerate NAT64 BIB entry failed.");
- goto done;
- case VNET_API_ERROR_INVALID_VALUE:
- error =
- clib_error_return (0, "Outside addres %U and port %u already in use.",
- format_ip4_address, &out_addr, out_port);
- goto done;
- default:
- break;
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-static int
-nat64_cli_bib_walk (nat64_db_bib_entry_t * bibe, void *ctx)
-{
- vlib_main_t *vm = ctx;
- fib_table_t *fib;
-
- fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
- if (!fib)
- return -1;
-
- switch (bibe->proto)
- {
- case IP_PROTOCOL_ICMP:
- case IP_PROTOCOL_TCP:
- case IP_PROTOCOL_UDP:
- vlib_cli_output (vm, " %U %u %U %u protocol %U vrf %u %s %u sessions",
- format_ip6_address, &bibe->in_addr,
- clib_net_to_host_u16 (bibe->in_port),
- format_ip4_address, &bibe->out_addr,
- clib_net_to_host_u16 (bibe->out_port),
- format_snat_protocol,
- ip_proto_to_snat_proto (bibe->proto), fib->ft_table_id,
- bibe->is_static ? "static" : "dynamic", bibe->ses_num);
- break;
- default:
- vlib_cli_output (vm, " %U %U protocol %u vrf %u %s %u sessions",
- format_ip6_address, &bibe->in_addr,
- format_ip4_address, &bibe->out_addr,
- bibe->proto, fib->ft_table_id,
- bibe->is_static ? "static" : "dynamic", bibe->ses_num);
- }
- return 0;
-}
-
-static clib_error_t *
-nat64_show_bib_command_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- clib_error_t *error = 0;
- u32 proto = ~0;
- u8 p = 255;
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
- p = snat_proto_to_ip_proto (proto);
- else if (unformat (line_input, "unknown"))
- p = 0;
- else if (unformat (line_input, "all"))
- ;
- else
- {
- error = clib_error_return (0, "unknown input: '%U'",
- format_unformat_error, line_input);
- goto done;
- }
-
- if (p == 255)
- vlib_cli_output (vm, "NAT64 BIB entries:");
- else
- vlib_cli_output (vm, "NAT64 %U BIB entries:", format_snat_protocol,
- proto);
- nat64_db_bib_walk (&nm->db, p, nat64_cli_bib_walk, vm);
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-static clib_error_t *
-nat64_set_timeouts_command_fn (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- clib_error_t *error = 0;
- u32 timeout, tcp_trans, tcp_est, tcp_incoming_syn;
-
- tcp_trans = nat64_get_tcp_trans_timeout ();
- tcp_est = nat64_get_tcp_est_timeout ();
- tcp_incoming_syn = nat64_get_tcp_incoming_syn_timeout ();
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "udp %u", &timeout))
- {
- if (nat64_set_udp_timeout (timeout))
- {
- error = clib_error_return (0, "Invalid UDP timeout value");
- goto done;
- }
- }
- else if (unformat (line_input, "icmp %u", &timeout))
- {
- if (nat64_set_icmp_timeout (timeout))
- {
- error = clib_error_return (0, "Invalid ICMP timeout value");
- goto done;
- }
- }
- else if (unformat (line_input, "tcp-trans %u", &tcp_trans))
- {
- if (nat64_set_tcp_timeouts (tcp_trans, tcp_est, tcp_incoming_syn))
- {
- error =
- clib_error_return (0, "Invalid TCP transitory tiemout value");
- goto done;
- }
- }
- else if (unformat (line_input, "tcp-est %u", &tcp_est))
- {
- if (nat64_set_tcp_timeouts (tcp_trans, tcp_est, tcp_incoming_syn))
- {
- error =
- clib_error_return (0,
- "Invalid TCP established tiemout value");
- goto done;
- }
- }
- else
- if (unformat (line_input, "tcp-incoming-syn %u", &tcp_incoming_syn))
- {
- if (nat64_set_tcp_timeouts (tcp_trans, tcp_est, tcp_incoming_syn))
- {
- error =
- clib_error_return (0,
- "Invalid TCP incoming SYN tiemout value");
- goto done;
- }
- }
- else if (unformat (line_input, "reset"))
- {
- nat64_set_udp_timeout (0);
- nat64_set_icmp_timeout (0);
- nat64_set_tcp_timeouts (0, 0, 0);
- }
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-static clib_error_t *
-nat64_show_timeouts_command_fn (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- vlib_cli_output (vm, "NAT64 session timeouts:");
- vlib_cli_output (vm, " UDP %usec", nat64_get_udp_timeout ());
- vlib_cli_output (vm, " ICMP %usec", nat64_get_icmp_timeout ());
- vlib_cli_output (vm, " TCP transitory %usec",
- nat64_get_tcp_trans_timeout ());
- vlib_cli_output (vm, " TCP established %usec",
- nat64_get_tcp_est_timeout ());
- vlib_cli_output (vm, " TCP incoming SYN %usec",
- nat64_get_tcp_incoming_syn_timeout ());
-
- return 0;
-}
-
-static int
-nat64_cli_st_walk (nat64_db_st_entry_t * ste, void *ctx)
-{
- vlib_main_t *vm = ctx;
- nat64_main_t *nm = &nat64_main;
- nat64_db_bib_entry_t *bibe;
- fib_table_t *fib;
-
- bibe = nat64_db_bib_entry_by_index (&nm->db, ste->proto, ste->bibe_index);
- if (!bibe)
- return -1;
-
- fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
- if (!fib)
- return -1;
-
- u32 vrf_id = fib->ft_table_id;
-
- if (ste->proto == IP_PROTOCOL_ICMP)
- vlib_cli_output (vm, " %U %U %u %U %U %u protocol %U vrf %u",
- format_ip6_address, &bibe->in_addr,
- format_ip6_address, &ste->in_r_addr,
- clib_net_to_host_u16 (bibe->in_port),
- format_ip4_address, &bibe->out_addr,
- format_ip4_address, &ste->out_r_addr,
- clib_net_to_host_u16 (bibe->out_port),
- format_snat_protocol,
- ip_proto_to_snat_proto (bibe->proto), vrf_id);
- else if (ste->proto == IP_PROTOCOL_TCP || ste->proto == IP_PROTOCOL_UDP)
- vlib_cli_output (vm, " %U %u %U %u %U %u %U %u protcol %U vrf %u",
- format_ip6_address, &bibe->in_addr,
- clib_net_to_host_u16 (bibe->in_port),
- format_ip6_address, &ste->in_r_addr,
- clib_net_to_host_u16 (ste->r_port),
- format_ip4_address, &bibe->out_addr,
- clib_net_to_host_u16 (bibe->out_port),
- format_ip4_address, &ste->out_r_addr,
- clib_net_to_host_u16 (ste->r_port),
- format_snat_protocol,
- ip_proto_to_snat_proto (bibe->proto), vrf_id);
- else
- vlib_cli_output (vm, " %U %U %U %U protocol %u vrf %u",
- format_ip6_address, &bibe->in_addr,
- format_ip6_address, &ste->in_r_addr,
- format_ip4_address, &bibe->out_addr,
- format_ip4_address, &ste->out_r_addr,
- bibe->proto, vrf_id);
-
- return 0;
-}
-
-static clib_error_t *
-nat64_show_st_command_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- clib_error_t *error = 0;
- u32 proto = ~0;
- u8 p = 255;
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
- p = snat_proto_to_ip_proto (proto);
- else if (unformat (line_input, "unknown"))
- p = 0;
- else if (unformat (line_input, "all"))
- ;
- else
- {
- error = clib_error_return (0, "unknown input: '%U'",
- format_unformat_error, line_input);
- goto done;
- }
-
- if (p == 255)
- vlib_cli_output (vm, "NAT64 sessions:");
- else
- vlib_cli_output (vm, "NAT64 %U sessions:", format_snat_protocol, proto);
- nat64_db_st_walk (&nm->db, p, nat64_cli_st_walk, vm);
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-static clib_error_t *
-nat64_add_del_prefix_command_fn (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
- clib_error_t *error = 0;
- unformat_input_t _line_input, *line_input = &_line_input;
- u8 is_add = 1;
- u32 vrf_id = 0;
- ip6_address_t prefix;
- u32 plen = 0;
- int rv;
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat
- (line_input, "%U/%u", unformat_ip6_address, &prefix, &plen))
- ;
- else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
- ;
- else if (unformat (line_input, "del"))
- is_add = 0;
- else
- {
- error = clib_error_return (0, "unknown input: '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- if (!plen)
- {
- error = clib_error_return (0, "NAT64 prefix must be set.");
- goto done;
- }
-
- rv = nat64_add_del_prefix (&prefix, (u8) plen, vrf_id, is_add);
-
- switch (rv)
- {
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- error = clib_error_return (0, "NAT64 prefix not exist.");
- goto done;
- case VNET_API_ERROR_INVALID_VALUE:
- error = clib_error_return (0, "Invalid prefix length.");
- goto done;
- default:
- break;
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-static int
-nat64_cli_prefix_walk (nat64_prefix_t * p, void *ctx)
-{
- vlib_main_t *vm = ctx;
-
- vlib_cli_output (vm, " %U/%u tenant-vrf %u",
- format_ip6_address, &p->prefix, p->plen, p->vrf_id);
-
- return 0;
-}
-
-static clib_error_t *
-nat64_show_prefix_command_fn (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- nat64_main_t *nm = &nat64_main;
-
- if (nm->is_disabled)
- return clib_error_return (0,
- "NAT64 disabled, multi thread not supported");
-
- vlib_cli_output (vm, "NAT64 prefix:");
- nat64_prefix_walk (nat64_cli_prefix_walk, vm);
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-
-/*?
- * @cliexpar
- * @cliexstart{nat64 add pool address}
- * Add/delete NAT64 pool address.
- * To add single NAT64 pool address use:
- * vpp# nat64 add pool address 10.1.1.10
- * To add NAT64 pool address range use:
- * vpp# nat64 add pool address 10.1.1.2 - 10.1.1.5
- * To add NAT64 pool address for specific tenant use:
- * vpp# nat64 add pool address 10.1.1.100 tenant-vrf 100
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (nat64_add_pool_address_command, static) = {
- .path = "nat64 add pool address",
- .short_help = "nat64 add pool address <ip4-range-start> [- <ip4-range-end>] "
- "[tenant-vrf <vrf-id>] [del]",
- .function = nat64_add_del_pool_addr_command_fn,
-};
-
-/*?
- * @cliexpar
- * @cliexstart{show nat64 pool}
- * Show NAT64 pool.
- * vpp# show nat64 pool
- * NAT64 pool:
- * 10.1.1.3 tenant VRF: 0
- * 10.1.1.10 tenant VRF: 10
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (show_nat64_pool_command, static) = {
- .path = "show nat64 pool",
- .short_help = "show nat64 pool",
- .function = nat64_show_pool_command_fn,
-};
-
-/*?
- * @cliexpar
- * @cliexstart{set interface nat64}
- * Enable/disable NAT64 feature on the interface.
- * To enable NAT64 feature with local (IPv6) network interface
- * GigabitEthernet0/8/0 and external (IPv4) network interface
- * GigabitEthernet0/a/0 use:
- * vpp# set interface nat64 in GigabitEthernet0/8/0 out GigabitEthernet0/a/0
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (set_interface_nat64_command, static) = {
- .path = "set interface nat64",
- .short_help = "set interface nat64 in|out <intfc> [del]",
- .function = nat64_interface_feature_command_fn,
-};
-
-/*?
- * @cliexpar
- * @cliexstart{show nat64 interfaces}
- * Show interfaces with NAT64 feature.
- * To show interfaces with NAT64 feature use:
- * vpp# show nat64 interfaces
- * NAT64 interfaces:
- * GigabitEthernet0/8/0 in
- * GigabitEthernet0/a/0 out
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (show_nat64_interfaces_command, static) = {
- .path = "show nat64 interfaces",
- .short_help = "show nat64 interfaces",
- .function = nat64_show_interfaces_command_fn,
-};
-
-/*?
- * @cliexpar
- * @cliexstart{nat64 add static bib}
- * Add/delete NAT64 static BIB entry.
- * To create NAT64 satatic BIB entry use:
- * vpp# nat64 add static bib 2001:db8:c000:221:: 1234 10.1.1.3 5678 tcp
- * vpp# nat64 add static bib 2001:db8:c000:221:: 1234 10.1.1.3 5678 udp vrf 10
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (nat64_add_del_static_bib_command, static) = {
- .path = "nat64 add static bib",
- .short_help = "nat64 add static bib <ip6-addr> <port> <ip4-addr> <port> "
- "tcp|udp|icmp [vfr <table-id>] [del]",
- .function = nat64_add_del_static_bib_command_fn,
-};
-
-/*?
- * @cliexpar
- * @cliexstart{show nat64 bib}
- * Show NAT64 BIB entries.
- * To show NAT64 TCP BIB entries use:
- * vpp# show nat64 bib tcp
- * NAT64 tcp BIB:
- * fd01:1::2 6303 10.0.0.3 62303 tcp vrf 0 dynamic 1 sessions
- * 2001:db8:c000:221:: 1234 10.1.1.3 5678 tcp vrf 0 static 2 sessions
- * To show NAT64 UDP BIB entries use:
- * vpp# show nat64 bib udp
- * NAT64 udp BIB:
- * fd01:1::2 6304 10.0.0.3 10546 udp vrf 0 dynamic 10 sessions
- * 2001:db8:c000:221:: 1234 10.1.1.3 5678 udp vrf 10 static 0 sessions
- * To show NAT64 ICMP BIB entries use:
- * vpp# show nat64 bib icmp
- * NAT64 icmp BIB:
- * fd01:1::2 6305 10.0.0.3 63209 icmp vrf 10 dynamic 1 sessions
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (show_nat64_bib_command, static) = {
- .path = "show nat64 bib",
- .short_help = "show nat64 bib all|tcp|udp|icmp|unknown",
- .function = nat64_show_bib_command_fn,
-};
-
-/*?
- * @cliexpar
- * @cliexstart{set nat64 timeouts}
- * Set NAT64 session timeouts (in seconds).
- * To set NAT64 session timeoutes use use:
- * vpp# set nat64 timeouts udp 200 icmp 30 tcp-trans 250 tcp-est 7450
- * To reset NAT64 session timeoutes to default values use:
- * vpp# set nat64 timeouts reset
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (set_nat64_timeouts_command, static) = {
- .path = "set nat64 timeouts",
- .short_help = "set nat64 timeouts udp <sec> icmp <sec> tcp-trans <sec> "
- "tcp-est <sec> tcp-incoming-syn <sec> | reset",
- .function = nat64_set_timeouts_command_fn,
-};
-
-/*?
- * @cliexpar
- * @cliexstart{show nat64 tiemouts}
- * Show NAT64 session timeouts:
- * vpp# show nat64 tiemouts
- * NAT64 session timeouts:
- * UDP 300sec
- * ICMP 60sec
- * TCP transitory 240sec
- * TCP established 7440sec
- * TCP incoming SYN 6sec
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (show_nat64_timeouts_command, static) = {
- .path = "show nat64 tiemouts",
- .short_help = "show nat64 tiemouts",
- .function = nat64_show_timeouts_command_fn,
-};
-
-/*?
- * @cliexpar
- * @cliexstart{show nat64 session table}
- * Show NAT64 session table.
- * To show NAT64 TCP session table use:
- * vpp# show nat64 session table tcp
- * NAT64 tcp session table:
- * fd01:1::2 6303 64:ff9b::ac10:202 20 10.0.0.3 62303 172.16.2.2 20 tcp vrf 0
- * fd01:3::2 6303 64:ff9b::ac10:202 20 10.0.10.3 21300 172.16.2.2 20 tcp vrf 10
- * To show NAT64 UDP session table use:
- * #vpp show nat64 session table udp
- * NAT64 udp session table:
- * fd01:1::2 6304 64:ff9b::ac10:202 20 10.0.0.3 10546 172.16.2.2 20 udp vrf 0
- * fd01:3::2 6304 64:ff9b::ac10:202 20 10.0.10.3 58627 172.16.2.2 20 udp vrf 10
- * fd01:1::2 1235 64:ff9b::a00:3 4023 10.0.0.3 24488 10.0.0.3 4023 udp vrf 0
- * fd01:1::3 23 64:ff9b::a00:3 24488 10.0.0.3 4023 10.0.0.3 24488 udp vrf 0
- * To show NAT64 ICMP session table use:
- * #vpp show nat64 session table icmp
- * NAT64 icmp session table:
- * fd01:1::2 64:ff9b::ac10:202 6305 10.0.0.3 172.16.2.2 63209 icmp vrf 0
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (show_nat64_st_command, static) = {
- .path = "show nat64 session table",
- .short_help = "show nat64 session table all|tcp|udp|icmp|unknown",
- .function = nat64_show_st_command_fn,
-};
-
-/*?
- * @cliexpar
- * @cliexstart{nat64 add prefix}
- * Set NAT64 prefix for generating IPv6 representations of IPv4 addresses.
- * To set NAT64 global prefix use:
- * vpp# nat64 add prefix 2001:db8::/32
- * To set NAT64 prefix for specific tenant use:
- * vpp# nat64 add prefix 2001:db8:122:300::/56 tenant-vrf 10
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (nat64_add_del_prefix_command, static) = {
- .path = "nat64 add prefix",
- .short_help = "nat64 add prefix <ip6-prefix>/<plen> [tenant-vrf <vrf-id>] "
- "[del]",
- .function = nat64_add_del_prefix_command_fn,
-};
-
-/*?
- * @cliexpar
- * @cliexstart{show nat64 prefix}
- * Show NAT64 prefix.
- * To show NAT64 prefix use:
- * vpp# show nat64 prefix
- * NAT64 prefix:
- * 2001:db8::/32 tenant-vrf 0
- * 2001:db8:122:300::/56 tenant-vrf 10
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (show_nat64_prefix_command, static) = {
- .path = "show nat64 prefix",
- .short_help = "show nat64 prefix",
- .function = nat64_show_prefix_command_fn,
-};
-
-/* *INDENT-ON* */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/plugins/snat/nat64_db.c b/src/plugins/snat/nat64_db.c
deleted file mode 100644
index 9584827e4da..00000000000
--- a/src/plugins/snat/nat64_db.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * Copyright (c) 2017 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.
- */
-/**
- * @file
- * @brief NAT64 DB
- */
-#include <snat/nat64_db.h>
-
-int
-nat64_db_init (nat64_db_t * db)
-{
- u32 bib_buckets = 1024;
- u32 bib_memory_size = 128 << 20;
- u32 st_buckets = 2048;
- u32 st_memory_size = 256 << 20;
-
- clib_bihash_init_24_8 (&db->bib.in2out, "bib-in2out", bib_buckets,
- bib_memory_size);
-
- clib_bihash_init_24_8 (&db->bib.out2in, "bib-out2in", bib_buckets,
- bib_memory_size);
-
- clib_bihash_init_48_8 (&db->st.in2out, "st-in2out", st_buckets,
- st_memory_size);
-
- clib_bihash_init_48_8 (&db->st.out2in, "st-out2in", st_buckets,
- st_memory_size);
-
- return 0;
-}
-
-nat64_db_bib_entry_t *
-nat64_db_bib_entry_create (nat64_db_t * db, ip6_address_t * in_addr,
- ip4_address_t * out_addr, u16 in_port,
- u16 out_port, u32 fib_index, u8 proto,
- u8 is_static)
-{
- nat64_db_bib_entry_t *bibe;
- nat64_db_bib_entry_key_t bibe_key;
- clib_bihash_kv_24_8_t kv;
-
- /* create pool entry */
- switch (ip_proto_to_snat_proto (proto))
- {
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- case SNAT_PROTOCOL_##N: \
- pool_get (db->bib._##n##_bib, bibe); \
- kv.value = bibe - db->bib._##n##_bib; \
- break;
- foreach_snat_protocol
-#undef _
-/* *INDENT-ON* */
- default:
- pool_get (db->bib._unk_proto_bib, bibe);
- kv.value = bibe - db->bib._unk_proto_bib;
- break;
- }
- memset (bibe, 0, sizeof (*bibe));
- bibe->in_addr.as_u64[0] = in_addr->as_u64[0];
- bibe->in_addr.as_u64[1] = in_addr->as_u64[1];
- bibe->in_port = in_port;
- bibe->out_addr.as_u32 = out_addr->as_u32;
- bibe->out_port = out_port;
- bibe->fib_index = fib_index;
- bibe->proto = proto;
- bibe->is_static = is_static;
-
- /* create hash lookup */
- bibe_key.addr.as_u64[0] = bibe->in_addr.as_u64[0];
- bibe_key.addr.as_u64[1] = bibe->in_addr.as_u64[1];
- bibe_key.fib_index = bibe->fib_index;
- bibe_key.port = bibe->in_port;
- bibe_key.proto = bibe->proto;
- bibe_key.rsvd = 0;
- kv.key[0] = bibe_key.as_u64[0];
- kv.key[1] = bibe_key.as_u64[1];
- kv.key[2] = bibe_key.as_u64[2];
- clib_bihash_add_del_24_8 (&db->bib.in2out, &kv, 1);
-
- memset (&bibe_key.addr, 0, sizeof (bibe_key.addr));
- bibe_key.addr.ip4.as_u32 = bibe->out_addr.as_u32;
- bibe_key.fib_index = 0;
- bibe_key.port = bibe->out_port;
- kv.key[0] = bibe_key.as_u64[0];
- kv.key[1] = bibe_key.as_u64[1];
- kv.key[2] = bibe_key.as_u64[2];
- clib_bihash_add_del_24_8 (&db->bib.out2in, &kv, 1);
-
- return bibe;
-}
-
-void
-nat64_db_bib_entry_free (nat64_db_t * db, nat64_db_bib_entry_t * bibe)
-{
- nat64_db_bib_entry_key_t bibe_key;
- clib_bihash_kv_24_8_t kv;
- nat64_db_bib_entry_t *bib;
- u32 *ste_to_be_free = 0, *ste_index, bibe_index;
- nat64_db_st_entry_t *st, *ste;
-
- switch (ip_proto_to_snat_proto (bibe->proto))
- {
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- case SNAT_PROTOCOL_##N: \
- bib = db->bib._##n##_bib; \
- st = db->st._##n##_st; \
- break;
- foreach_snat_protocol
-#undef _
-/* *INDENT-ON* */
- default:
- bib = db->bib._unk_proto_bib;
- st = db->st._unk_proto_st;
- break;
- }
-
- bibe_index = bibe - bib;
-
- /* delete ST entries for static BIB entry */
- if (bibe->is_static)
- {
- pool_foreach (ste, st, (
- {
- if (ste->bibe_index == bibe_index)
- vec_add1 (ste_to_be_free, ste - st);}
- ));
- vec_foreach (ste_index, ste_to_be_free)
- nat64_db_st_entry_free (db, pool_elt_at_index (st, ste_index[0]));
- vec_free (ste_to_be_free);
- }
-
- /* delete hash lookup */
- bibe_key.addr.as_u64[0] = bibe->in_addr.as_u64[0];
- bibe_key.addr.as_u64[1] = bibe->in_addr.as_u64[1];
- bibe_key.fib_index = bibe->fib_index;
- bibe_key.port = bibe->in_port;
- bibe_key.proto = bibe->proto;
- bibe_key.rsvd = 0;
- kv.key[0] = bibe_key.as_u64[0];
- kv.key[1] = bibe_key.as_u64[1];
- kv.key[2] = bibe_key.as_u64[2];
- clib_bihash_add_del_24_8 (&db->bib.in2out, &kv, 0);
-
- memset (&bibe_key.addr, 0, sizeof (bibe_key.addr));
- bibe_key.addr.ip4.as_u32 = bibe->out_addr.as_u32;
- bibe_key.fib_index = 0;
- bibe_key.port = bibe->out_port;
- kv.key[0] = bibe_key.as_u64[0];
- kv.key[1] = bibe_key.as_u64[1];
- kv.key[2] = bibe_key.as_u64[2];
- clib_bihash_add_del_24_8 (&db->bib.out2in, &kv, 0);
-
- /* delete from pool */
- pool_put (bib, bibe);
-
-}
-
-nat64_db_bib_entry_t *
-nat64_db_bib_entry_find (nat64_db_t * db, ip46_address_t * addr, u16 port,
- u8 proto, u32 fib_index, u8 is_ip6)
-{
- nat64_db_bib_entry_t *bibe = 0;
- nat64_db_bib_entry_key_t bibe_key;
- clib_bihash_kv_24_8_t kv, value;
- nat64_db_bib_entry_t *bib;
-
- switch (ip_proto_to_snat_proto (proto))
- {
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- case SNAT_PROTOCOL_##N: \
- bib = db->bib._##n##_bib; \
- break;
- foreach_snat_protocol
-#undef _
-/* *INDENT-ON* */
- default:
- bib = db->bib._unk_proto_bib;
- break;
- }
-
- bibe_key.addr.as_u64[0] = addr->as_u64[0];
- bibe_key.addr.as_u64[1] = addr->as_u64[1];
- bibe_key.fib_index = fib_index;
- bibe_key.port = port;
- bibe_key.proto = proto;
- bibe_key.rsvd = 0;
-
- kv.key[0] = bibe_key.as_u64[0];
- kv.key[1] = bibe_key.as_u64[1];
- kv.key[2] = bibe_key.as_u64[2];
-
- if (!clib_bihash_search_24_8
- (is_ip6 ? &db->bib.in2out : &db->bib.out2in, &kv, &value))
- bibe = pool_elt_at_index (bib, value.value);
-
- return bibe;
-}
-
-void
-nat64_db_bib_walk (nat64_db_t * db, u8 proto,
- nat64_db_bib_walk_fn_t fn, void *ctx)
-{
- nat64_db_bib_entry_t *bib, *bibe;
-
- if (proto == 255)
- {
- /* *INDENT-OFF* */
- #define _(N, i, n, s) \
- bib = db->bib._##n##_bib; \
- pool_foreach (bibe, bib, ({ \
- if (fn (bibe, ctx)) \
- return; \
- }));
- foreach_snat_protocol
- #undef _
- bib = db->bib._unk_proto_bib;
- pool_foreach (bibe, bib, ({
- if (fn (bibe, ctx))
- return;
- }));
- /* *INDENT-ON* */
- }
- else
- {
- switch (ip_proto_to_snat_proto (proto))
- {
- /* *INDENT-OFF* */
- #define _(N, i, n, s) \
- case SNAT_PROTOCOL_##N: \
- bib = db->bib._##n##_bib; \
- break;
- foreach_snat_protocol
- #undef _
- /* *INDENT-ON* */
- default:
- bib = db->bib._unk_proto_bib;
- break;
- }
-
- /* *INDENT-OFF* */
- pool_foreach (bibe, bib,
- ({
- if (fn (bibe, ctx))
- return;
- }));
- /* *INDENT-ON* */
- }
-}
-
-nat64_db_bib_entry_t *
-nat64_db_bib_entry_by_index (nat64_db_t * db, u8 proto, u32 bibe_index)
-{
- nat64_db_bib_entry_t *bib;
-
- switch (ip_proto_to_snat_proto (proto))
- {
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- case SNAT_PROTOCOL_##N: \
- bib = db->bib._##n##_bib; \
- break;
- foreach_snat_protocol
-#undef _
-/* *INDENT-ON* */
- default:
- bib = db->bib._unk_proto_bib;
- break;
- }
-
- return pool_elt_at_index (bib, bibe_index);
-}
-
-void
-nat64_db_st_walk (nat64_db_t * db, u8 proto,
- nat64_db_st_walk_fn_t fn, void *ctx)
-{
- nat64_db_st_entry_t *st, *ste;
-
- if (proto == 255)
- {
- /* *INDENT-OFF* */
- #define _(N, i, n, s) \
- st = db->st._##n##_st; \
- pool_foreach (ste, st, ({ \
- if (fn (ste, ctx)) \
- return; \
- }));
- foreach_snat_protocol
- #undef _
- st = db->st._unk_proto_st;
- pool_foreach (ste, st, ({
- if (fn (ste, ctx))
- return;
- }));
- /* *INDENT-ON* */
- }
- else
- {
- switch (ip_proto_to_snat_proto (proto))
- {
- /* *INDENT-OFF* */
- #define _(N, i, n, s) \
- case SNAT_PROTOCOL_##N: \
- st = db->st._##n##_st; \
- break;
- foreach_snat_protocol
- #undef _
- /* *INDENT-ON* */
- default:
- st = db->st._unk_proto_st;
- break;
- }
-
- /* *INDENT-OFF* */
- pool_foreach (ste, st,
- ({
- if (fn (ste, ctx))
- return;
- }));
- /* *INDENT-ON* */
- }
-}
-
-nat64_db_st_entry_t *
-nat64_db_st_entry_create (nat64_db_t * db, nat64_db_bib_entry_t * bibe,
- ip6_address_t * in_r_addr,
- ip4_address_t * out_r_addr, u16 r_port)
-{
- nat64_db_st_entry_t *ste;
- nat64_db_bib_entry_t *bib;
- nat64_db_st_entry_key_t ste_key;
- clib_bihash_kv_48_8_t kv;
-
- /* create pool entry */
- switch (ip_proto_to_snat_proto (bibe->proto))
- {
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- case SNAT_PROTOCOL_##N: \
- pool_get (db->st._##n##_st, ste); \
- kv.value = ste - db->st._##n##_st; \
- bib = db->bib._##n##_bib; \
- break;
- foreach_snat_protocol
-#undef _
-/* *INDENT-ON* */
- default:
- pool_get (db->st._unk_proto_st, ste);
- kv.value = ste - db->st._unk_proto_st;
- bib = db->bib._unk_proto_bib;
- break;
- }
- memset (ste, 0, sizeof (*ste));
- ste->in_r_addr.as_u64[0] = in_r_addr->as_u64[0];
- ste->in_r_addr.as_u64[1] = in_r_addr->as_u64[1];
- ste->out_r_addr.as_u32 = out_r_addr->as_u32;
- ste->r_port = r_port;
- ste->bibe_index = bibe - bib;
- ste->proto = bibe->proto;
-
- /* increment session number for BIB entry */
- bibe->ses_num++;
-
- /* create hash lookup */
- memset (&ste_key, 0, sizeof (ste_key));
- ste_key.l_addr.as_u64[0] = bibe->in_addr.as_u64[0];
- ste_key.l_addr.as_u64[1] = bibe->in_addr.as_u64[1];
- ste_key.r_addr.as_u64[0] = ste->in_r_addr.as_u64[0];
- ste_key.r_addr.as_u64[1] = ste->in_r_addr.as_u64[1];
- ste_key.fib_index = bibe->fib_index;
- ste_key.l_port = bibe->in_port;
- ste_key.r_port = ste->r_port;
- ste_key.proto = ste->proto;
- kv.key[0] = ste_key.as_u64[0];
- kv.key[1] = ste_key.as_u64[1];
- kv.key[2] = ste_key.as_u64[2];
- kv.key[3] = ste_key.as_u64[3];
- kv.key[4] = ste_key.as_u64[4];
- kv.key[5] = ste_key.as_u64[5];
- clib_bihash_add_del_48_8 (&db->st.in2out, &kv, 1);
-
- memset (&ste_key, 0, sizeof (ste_key));
- ste_key.l_addr.ip4.as_u32 = bibe->out_addr.as_u32;
- ste_key.r_addr.ip4.as_u32 = ste->out_r_addr.as_u32;
- ste_key.l_port = bibe->out_port;
- ste_key.r_port = ste->r_port;
- ste_key.proto = ste->proto;
- kv.key[0] = ste_key.as_u64[0];
- kv.key[1] = ste_key.as_u64[1];
- kv.key[2] = ste_key.as_u64[2];
- kv.key[3] = ste_key.as_u64[3];
- kv.key[4] = ste_key.as_u64[4];
- kv.key[5] = ste_key.as_u64[5];
- clib_bihash_add_del_48_8 (&db->st.out2in, &kv, 1);
-
- return ste;
-}
-
-void
-nat64_db_st_entry_free (nat64_db_t * db, nat64_db_st_entry_t * ste)
-{
- nat64_db_st_entry_t *st;
- nat64_db_bib_entry_t *bib, *bibe;
- nat64_db_st_entry_key_t ste_key;
- clib_bihash_kv_48_8_t kv;
-
- switch (ip_proto_to_snat_proto (ste->proto))
- {
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- case SNAT_PROTOCOL_##N: \
- st = db->st._##n##_st; \
- bib = db->bib._##n##_bib; \
- break;
- foreach_snat_protocol
-#undef _
-/* *INDENT-ON* */
- default:
- st = db->st._unk_proto_st;
- bib = db->bib._unk_proto_bib;
- break;
- }
-
- bibe = pool_elt_at_index (bib, ste->bibe_index);
-
- /* delete hash lookup */
- memset (&ste_key, 0, sizeof (ste_key));
- ste_key.l_addr.as_u64[0] = bibe->in_addr.as_u64[0];
- ste_key.l_addr.as_u64[1] = bibe->in_addr.as_u64[1];
- ste_key.r_addr.as_u64[0] = ste->in_r_addr.as_u64[0];
- ste_key.r_addr.as_u64[1] = ste->in_r_addr.as_u64[1];
- ste_key.fib_index = bibe->fib_index;
- ste_key.l_port = bibe->in_port;
- ste_key.r_port = ste->r_port;
- ste_key.proto = ste->proto;
- kv.key[0] = ste_key.as_u64[0];
- kv.key[1] = ste_key.as_u64[1];
- kv.key[2] = ste_key.as_u64[2];
- kv.key[3] = ste_key.as_u64[3];
- kv.key[4] = ste_key.as_u64[4];
- kv.key[5] = ste_key.as_u64[5];
- clib_bihash_add_del_48_8 (&db->st.in2out, &kv, 0);
-
- memset (&ste_key, 0, sizeof (ste_key));
- ste_key.l_addr.ip4.as_u32 = bibe->out_addr.as_u32;
- ste_key.r_addr.ip4.as_u32 = ste->out_r_addr.as_u32;
- ste_key.l_port = bibe->out_port;
- ste_key.r_port = ste->r_port;
- ste_key.proto = ste->proto;
- kv.key[0] = ste_key.as_u64[0];
- kv.key[1] = ste_key.as_u64[1];
- kv.key[2] = ste_key.as_u64[2];
- kv.key[3] = ste_key.as_u64[3];
- kv.key[4] = ste_key.as_u64[4];
- kv.key[5] = ste_key.as_u64[5];
- clib_bihash_add_del_48_8 (&db->st.out2in, &kv, 0);
-
- /* delete from pool */
- pool_put (st, ste);
-
- /* decrement session number for BIB entry */
- bibe->ses_num--;
-
- /* delete BIB entry if last session and dynamic */
- if (!bibe->is_static && !bibe->ses_num)
- nat64_db_bib_entry_free (db, bibe);
-}
-
-nat64_db_st_entry_t *
-nat64_db_st_entry_find (nat64_db_t * db, ip46_address_t * l_addr,
- ip46_address_t * r_addr, u16 l_port, u16 r_port,
- u8 proto, u32 fib_index, u8 is_ip6)
-{
- nat64_db_st_entry_t *ste = 0;
- nat64_db_st_entry_t *st;
- nat64_db_st_entry_key_t ste_key;
- clib_bihash_kv_48_8_t kv, value;
-
- switch (ip_proto_to_snat_proto (proto))
- {
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- case SNAT_PROTOCOL_##N: \
- st = db->st._##n##_st; \
- break;
- foreach_snat_protocol
-#undef _
-/* *INDENT-ON* */
- default:
- st = db->st._unk_proto_st;
- break;
- }
-
- memset (&ste_key, 0, sizeof (ste_key));
- ste_key.l_addr.as_u64[0] = l_addr->as_u64[0];
- ste_key.l_addr.as_u64[1] = l_addr->as_u64[1];
- ste_key.r_addr.as_u64[0] = r_addr->as_u64[0];
- ste_key.r_addr.as_u64[1] = r_addr->as_u64[1];
- ste_key.fib_index = fib_index;
- ste_key.l_port = l_port;
- ste_key.r_port = r_port;
- ste_key.proto = proto;
- kv.key[0] = ste_key.as_u64[0];
- kv.key[1] = ste_key.as_u64[1];
- kv.key[2] = ste_key.as_u64[2];
- kv.key[3] = ste_key.as_u64[3];
- kv.key[4] = ste_key.as_u64[4];
- kv.key[5] = ste_key.as_u64[5];
-
- if (!clib_bihash_search_48_8
- (is_ip6 ? &db->st.in2out : &db->st.out2in, &kv, &value))
- ste = pool_elt_at_index (st, value.value);
-
- return ste;
-}
-
-void
-nad64_db_st_free_expired (nat64_db_t * db, u32 now)
-{
- u32 *ste_to_be_free = 0, *ste_index;
- nat64_db_st_entry_t *st, *ste;
-
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- st = db->st._##n##_st; \
- pool_foreach (ste, st, ({\
- if (i == SNAT_PROTOCOL_TCP && !ste->tcp_state) \
- continue; \
- if (ste->expire < now) \
- vec_add1 (ste_to_be_free, ste - st); \
- })); \
- vec_foreach (ste_index, ste_to_be_free) \
- nat64_db_st_entry_free (db, pool_elt_at_index(st, ste_index[0])); \
- vec_free (ste_to_be_free); \
- ste_to_be_free = 0;
- foreach_snat_protocol
-#undef _
- st = db->st._unk_proto_st;
- pool_foreach (ste, st, ({
- if (ste->expire < now)
- vec_add1 (ste_to_be_free, ste - st);
- }));
- vec_foreach (ste_index, ste_to_be_free)
- nat64_db_st_entry_free (db, pool_elt_at_index(st, ste_index[0]));
- vec_free (ste_to_be_free);
-/* *INDENT-ON* */
-}
-
-void
-nat64_db_free_out_addr (nat64_db_t * db, ip4_address_t * out_addr)
-{
- u32 *ste_to_be_free = 0, *ste_index;
- nat64_db_st_entry_t *st, *ste;
- nat64_db_bib_entry_t *bibe;
-
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- st = db->st._##n##_st; \
- pool_foreach (ste, st, ({ \
- bibe = pool_elt_at_index (db->bib._##n##_bib, ste->bibe_index); \
- if (bibe->out_addr.as_u32 == out_addr->as_u32) \
- vec_add1 (ste_to_be_free, ste - st); \
- })); \
- vec_foreach (ste_index, ste_to_be_free) \
- nat64_db_st_entry_free (db, pool_elt_at_index(st, ste_index[0])); \
- vec_free (ste_to_be_free); \
- ste_to_be_free = 0;
- foreach_snat_protocol
-#undef _
- st = db->st._unk_proto_st;
- pool_foreach (ste, st, ({
- bibe = pool_elt_at_index (db->bib._unk_proto_bib, ste->bibe_index);
- if (bibe->out_addr.as_u32 == out_addr->as_u32)
- vec_add1 (ste_to_be_free, ste - st);
- }));
- vec_foreach (ste_index, ste_to_be_free)
- nat64_db_st_entry_free (db, pool_elt_at_index(st, ste_index[0]));
- vec_free (ste_to_be_free);
-/* *INDENT-ON* */
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/plugins/snat/nat64_db.h b/src/plugins/snat/nat64_db.h
deleted file mode 100644
index 1e2dcc930d8..00000000000
--- a/src/plugins/snat/nat64_db.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright (c) 2017 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.
- */
-/**
- * @file
- * @brief NAT64 DB
- */
-#ifndef __included_nat64_db_h__
-#define __included_nat64_db_h__
-
-#include <vppinfra/bihash_24_8.h>
-#include <vppinfra/bihash_48_8.h>
-#include <snat/snat.h>
-
-
-typedef struct
-{
- union
- {
- struct
- {
- ip46_address_t addr;
- u32 fib_index;
- u16 port;
- u8 proto;
- u8 rsvd;
- };
- u64 as_u64[3];
- };
-} nat64_db_bib_entry_key_t;
-
-/* *INDENT-OFF* */
-typedef CLIB_PACKED(struct
-{
- ip6_address_t in_addr;
- u16 in_port;
- ip4_address_t out_addr;
- u16 out_port;
- u32 fib_index;
- u32 ses_num;
- u8 proto;
- u8 is_static;
-}) nat64_db_bib_entry_t;
-/* *INDENT-ON* */
-
-typedef struct
-{
- /* BIBs */
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- nat64_db_bib_entry_t *_##n##_bib;
- foreach_snat_protocol
-#undef _
-/* *INDENT-ON* */
- nat64_db_bib_entry_t *_unk_proto_bib;
-
- /* BIB lookup */
- clib_bihash_24_8_t in2out;
- clib_bihash_24_8_t out2in;
-} nat64_db_bib_t;
-
-typedef struct
-{
- union
- {
- struct
- {
- ip46_address_t l_addr;
- ip46_address_t r_addr;
- u32 fib_index;
- u16 l_port;
- u16 r_port;
- u8 proto;
- u8 rsvd[7];
- };
- u64 as_u64[6];
- };
-} nat64_db_st_entry_key_t;
-
-/* *INDENT-OFF* */
-typedef CLIB_PACKED(struct
-{
- ip6_address_t in_r_addr;
- ip4_address_t out_r_addr;
- u16 r_port;
- u32 bibe_index;
- u32 expire;
- u8 proto;
- u8 tcp_state;
-}) nat64_db_st_entry_t;
-/* *INDENT-ON* */
-
-typedef struct
-{
- /* session tables */
-/* *INDENT-OFF* */
-#define _(N, i, n, s) \
- nat64_db_st_entry_t *_##n##_st;
- foreach_snat_protocol
-#undef _
-/* *INDENT-ON* */
- nat64_db_st_entry_t *_unk_proto_st;
-
- /* session lookup */
- clib_bihash_48_8_t in2out;
- clib_bihash_48_8_t out2in;
-} nat64_db_st_t;
-
-typedef struct
-{
- nat64_db_bib_t bib;
- nat64_db_st_t st;
-} nat64_db_t;
-
-/**
- * @brief Initialize NAT64 DB.
- *
- * @param db NAT64 DB.
- *
- * @returns 0 on success, non-zero value otherwise.
- */
-int nat64_db_init (nat64_db_t * db);
-
-/**
- * @brief Create new NAT64 BIB entry.
- *
- * @param db NAT64 DB.
- * @param in_addr Inside IPv6 address.
- * @param out_addr Outside IPv4 address.
- * @param in_port Inside port number.
- * @param out_port Outside port number.
- * @param fib_index FIB index.
- * @param proto L4 protocol.
- * @param is_static 1 if static, 0 if dynamic.
- *
- * @returns BIB entry on success, 0 otherwise.
- */
-nat64_db_bib_entry_t *nat64_db_bib_entry_create (nat64_db_t * db,
- ip6_address_t * in_addr,
- ip4_address_t * out_addr,
- u16 in_port, u16 out_port,
- u32 fib_index,
- u8 proto, u8 is_static);
-
-/**
- * @brief Free NAT64 BIB entry.
- *
- * @param db NAT64 DB.
- * @param bibe BIB entry.
- */
-void nat64_db_bib_entry_free (nat64_db_t * db, nat64_db_bib_entry_t * bibe);
-
-/**
- * @brief Call back function when walking NAT64 BIB, non-zero
- * return value stop walk.
- */
-typedef int (*nat64_db_bib_walk_fn_t) (nat64_db_bib_entry_t * bibe,
- void *ctx);
-/**
- * @brief Walk NAT64 BIB.
- *
- * @param db NAT64 DB.
- * @param proto BIB L4 protocol:
- * - 255 all BIBs
- * - 6 TCP BIB
- * - 17 UDP BIB
- * - 1/58 ICMP BIB
- * - otherwise "unknown" protocol BIB
- * @param fn The function to invoke on each entry visited.
- * @param ctx A context passed in the visit function.
- */
-void nat64_db_bib_walk (nat64_db_t * db, u8 proto,
- nat64_db_bib_walk_fn_t fn, void *ctx);
-
-/**
- * @brief Find NAT64 BIB entry.
- *
- * @param db NAT64 DB.
- * @param addr IP address.
- * @param port Port number.
- * @param proto L4 protocol.
- * @param fib_index FIB index.
- * @param is_ip6 1 if find by IPv6 (inside) address, 0 by IPv4 (outside).
- *
- * @return BIB entry if found.
- */
-nat64_db_bib_entry_t *nat64_db_bib_entry_find (nat64_db_t * db,
- ip46_address_t * addr,
- u16 port,
- u8 proto,
- u32 fib_index, u8 is_ip6);
-
-/**
- * @brief Get BIB entry by index and protocol.
- *
- * @param db NAT64 DB.
- * @param proto L4 protocol.
- * @param bibe_index BIB entry index.
- *
- * @return BIB entry if found.
- */
-nat64_db_bib_entry_t *nat64_db_bib_entry_by_index (nat64_db_t * db,
- u8 proto, u32 bibe_index);
-/**
- * @brief Create new NAT64 session table entry.
- *
- * @param db NAT64 DB.
- * @param bibe Corresponding BIB entry.
- * @param in_r_addr Inside IPv6 address of the remote host.
- * @param out_r_addr Outside IPv4 address of the remote host.
- * @param r_port Remote host port number.
- *
- * @returns BIB entry on success, 0 otherwise.
- */
-nat64_db_st_entry_t *nat64_db_st_entry_create (nat64_db_t * db,
- nat64_db_bib_entry_t * bibe,
- ip6_address_t * in_r_addr,
- ip4_address_t * out_r_addr,
- u16 r_port);
-
-/**
- * @brief Free NAT64 session table entry.
- *
- * @param db NAT64 DB.
- * @param ste Session table entry.
- */
-void nat64_db_st_entry_free (nat64_db_t * db, nat64_db_st_entry_t * ste);
-
-/**
- * @brief Find NAT64 session table entry.
- *
- * @param db NAT64 DB.
- * @param l_addr Local host address.
- * @param r_addr Remote host address.
- * @param l_port Local host port number.
- * @param r_port Remote host port number.
- * @param proto L4 protocol.
- * @param fib_index FIB index.
- * @param is_ip6 1 if find by IPv6 (inside) address, 0 by IPv4 (outside).
- *
- * @return BIB entry if found.
- */
-nat64_db_st_entry_t *nat64_db_st_entry_find (nat64_db_t * db,
- ip46_address_t * l_addr,
- ip46_address_t * r_addr,
- u16 l_port, u16 r_port,
- u8 proto,
- u32 fib_index, u8 is_ip6);
-
-/**
- * @brief Call back function when walking NAT64 session table, non-zero
- * return value stop walk.
- */
-typedef int (*nat64_db_st_walk_fn_t) (nat64_db_st_entry_t * ste, void *ctx);
-
-/**
- * @brief Walk NAT64 session table.
- *
- * @param db NAT64 DB.
- * @param proto L4 protocol:
- * - 255 all session tables
- * - 6 TCP session table
- * - 17 UDP session table
- * - 1/58 ICMP session table
- * - otherwise "unknown" protocol session table
- * @param fn The function to invoke on each entry visited.
- * @param ctx A context passed in the visit function.
- */
-void nat64_db_st_walk (nat64_db_t * db, u8 proto,
- nat64_db_st_walk_fn_t fn, void *ctx);
-
-/**
- * @brief Free expired session entries in session tables.
- *
- * @param db NAT64 DB.
- * @param now Current time.
- */
-void nad64_db_st_free_expired (nat64_db_t * db, u32 now);
-
-/**
- * @brief Free sessions using specific outside address.
- *
- * @param db NAT64 DB.
- * @param out_addr Outside address to match.
- */
-void nat64_db_free_out_addr (nat64_db_t * db, ip4_address_t * out_addr);
-
-#endif /* __included_nat64_db_h__ */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/plugins/snat/nat64_doc.md b/src/plugins/snat/nat64_doc.md
deleted file mode 100644
index f94467dade1..00000000000
--- a/src/plugins/snat/nat64_doc.md
+++ /dev/null
@@ -1,73 +0,0 @@
-# Stateful NAT64: Network Address and Protocol Translation from IPv6 Clients to IPv4 Servers {#nat64_doc}
-
-## Introduction
-
-Stateful NAT64 in VPP allows IPv6-only clients to contact IPv4 servers using unicast UDP, TCP, or ICMP based on RFC 6146.
-
-## Configuration
-
-### Enable/disable NAT64 feature on the interface
-
-> set interface nat64 in|out <intfc> [del]
-
-in: inside/local/IPv6 network
-out: outside/external/IPv4 network
-intfc: interface name
-
-### Add/delete NAT64 pool address
-
-One or more public IPv4 addresses assigned to a NAT64 are shared among several IPv6-only clients.
-
-> nat64 add pool address <ip4-range-start> [- <ip4-range-end>] [tenant-vrf <tenant-vrf-id>] [del]
-
-ip4-range-start: First IPv4 address of the range
-ip4-range-end: Last IPv4 address of the range (optional, not used for single address)
-tenant-vrf-id: VRF id of the tenant associated with the pool address (optional, if not set pool address is global)
-
-### Add/delete static BIB entry
-
-Stateful NAT64 also supports IPv4-initiated communications to a subset of the IPv6 hosts through staticaly configured bindings.
-
-> nat64 add static bib <ip6-addr> <in-port> <ip4-addr> <out-port> tcp|udp|icmp [vfr <table-id>] [del]
-
-ip6-addr: inside IPv6 address of the host
-in-port: inside port or ICMPv6 identifier
-ip4-addr: outside IPv4 address of the host
-out-port: outside port or ICMPv4 identifier
-table-id: VRF id of the tenant associated with the BIB entry (optional, default use global VRF)
-
-### Set NAT64 session timeouts
-
-Session is deleted when timer expires. If all sessions corresponding to a dynamically create BIB entry are deleted, then the BIB entry is also deleted. When packets are flowing sessiom timer is refreshed to keep the session alive.
-
-> set nat64 timeouts udp <sec> icmp <sec> tcp-trans <sec> tcp-est <sec> tcp-incoming-syn <sec> | reset
-
-udp: UDP session timeout value (default 300sec)
-icmp: ICMP session timeout value (default 60sec)
-tcp-trans: transitory TCP session timeout value (default 240sec)
-tcp-est: established TCP session timeout value (default 7440sec)
-tcp-incoming-syn: incoming SYN TCP session timeout value (default 6sec)
-reset: reset timers to default values
-
-### Set NAT64 prefix
-
-Stateful NAT64 support the algorithm for generating IPv6 representations of IPv4 addresses defined in RFC 6052. If no prefix is configured, Well-Known Prefix (64:ff9b::/96) is used.
-
-> nat64 add prefix <ip6-prefix>/<plen> [tenant-vrf <vrf-id>] [del]
-
-ip6-prefix: IPv6 prefix
-plen: prefix length (valid values: 32, 40, 48, 56, 64, or 96)
-tenant-vrf: VRF id of the tenant associated with the prefix
-
-### Show commands
-
-> show nat64 pool
-> show nat64 interfaces
-> show nat64 bib tcp|udp|icmp
-> show nat64 session table tcp|udp|icmp
-> show nat64 tiemouts
-> show nat64 prefix
-
-## Notes
-
-Multi thread is not supported yet (CLI/API commands are disabled when VPP runs with multiple threads).
diff --git a/src/plugins/snat/nat64_in2out.c b/src/plugins/snat/nat64_in2out.c
deleted file mode 100644
index 8c67fec2b29..00000000000
--- a/src/plugins/snat/nat64_in2out.c
+++ /dev/null
@@ -1,1118 +0,0 @@
-/*
- * Copyright (c) 2017 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.
- */
-/**
- * @file
- * @brief NAT64 IPv6 to IPv4 translation (inside to outside network)
- */
-
-#include <snat/nat64.h>
-#include <vnet/ip/ip6_to_ip4.h>
-#include <vnet/fib/fib_table.h>
-
-typedef struct
-{
- u32 sw_if_index;
- u32 next_index;
- u8 is_slow_path;
-} nat64_in2out_trace_t;
-
-static u8 *
-format_nat64_in2out_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 *);
- nat64_in2out_trace_t *t = va_arg (*args, nat64_in2out_trace_t *);
- char *tag;
-
- tag = t->is_slow_path ? "NAT64-in2out-slowpath" : "NAT64-in2out";
-
- s =
- format (s, "%s: sw_if_index %d, next index %d", tag, t->sw_if_index,
- t->next_index);
-
- return s;
-}
-
-vlib_node_registration_t nat64_in2out_node;
-vlib_node_registration_t nat64_in2out_slowpath_node;
-
-#define foreach_nat64_in2out_error \
-_(UNSUPPORTED_PROTOCOL, "unsupported protocol") \
-_(IN2OUT_PACKETS, "good in2out packets processed") \
-_(NO_TRANSLATION, "no translation") \
-_(UNKNOWN, "unknown")
-
-typedef enum
-{
-#define _(sym,str) NAT64_IN2OUT_ERROR_##sym,
- foreach_nat64_in2out_error
-#undef _
- NAT64_IN2OUT_N_ERROR,
-} nat64_in2out_error_t;
-
-static char *nat64_in2out_error_strings[] = {
-#define _(sym,string) string,
- foreach_nat64_in2out_error
-#undef _
-};
-
-typedef enum
-{
- NAT64_IN2OUT_NEXT_IP4_LOOKUP,
- NAT64_IN2OUT_NEXT_IP6_LOOKUP,
- NAT64_IN2OUT_NEXT_DROP,
- NAT64_IN2OUT_NEXT_SLOWPATH,
- NAT64_IN2OUT_N_NEXT,
-} nat64_in2out_next_t;
-
-typedef struct nat64_in2out_set_ctx_t_
-{
- vlib_buffer_t *b;
- vlib_main_t *vm;
-} nat64_in2out_set_ctx_t;
-
-/**
- * @brief Check whether is a hairpinning.
- *
- * If the destination IP address of the packet is an IPv4 address assigned to
- * the NAT64 itself, then the packet is a hairpin packet.
- *
- * param dst_addr Destination address of the packet.
- *
- * @returns 1 if hairpinning, otherwise 0.
- */
-static_always_inline int
-is_hairpinning (ip6_address_t * dst_addr)
-{
- nat64_main_t *nm = &nat64_main;
- int i;
-
- for (i = 0; i < vec_len (nm->addr_pool); i++)
- {
- if (nm->addr_pool[i].addr.as_u32 == dst_addr->as_u32[3])
- return 1;
- }
-
- return 0;
-}
-
-static int
-nat64_in2out_tcp_udp_set_cb (ip6_header_t * ip6, ip4_header_t * ip4,
- void *arg)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_in2out_set_ctx_t *ctx = arg;
- nat64_db_bib_entry_t *bibe;
- nat64_db_st_entry_t *ste;
- ip46_address_t saddr, daddr;
- u32 sw_if_index, fib_index;
- udp_header_t *udp = ip6_next_header (ip6);
- u8 proto = ip6->protocol;
- u16 sport = udp->src_port;
- u16 dport = udp->dst_port;
-
- sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
- fib_index =
- fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
-
- saddr.as_u64[0] = ip6->src_address.as_u64[0];
- saddr.as_u64[1] = ip6->src_address.as_u64[1];
- daddr.as_u64[0] = ip6->dst_address.as_u64[0];
- daddr.as_u64[1] = ip6->dst_address.as_u64[1];
-
- ste =
- nat64_db_st_entry_find (&nm->db, &saddr, &daddr, sport, dport, proto,
- fib_index, 1);
-
- if (ste)
- {
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
- }
- else
- {
- bibe =
- nat64_db_bib_entry_find (&nm->db, &saddr, sport, proto, fib_index, 1);
-
- if (!bibe)
- {
- u16 out_port;
- ip4_address_t out_addr;
- if (nat64_alloc_out_addr_and_port
- (fib_index, ip_proto_to_snat_proto (proto), &out_addr,
- &out_port))
- return -1;
-
- bibe =
- nat64_db_bib_entry_create (&nm->db, &ip6->src_address, &out_addr,
- sport, clib_host_to_net_u16 (out_port),
- fib_index, proto, 0);
- if (!bibe)
- return -1;
- }
-
- nat64_extract_ip4 (&ip6->dst_address, &daddr.ip4, fib_index);
- ste =
- nat64_db_st_entry_create (&nm->db, bibe, &ip6->dst_address,
- &daddr.ip4, dport);
- if (!ste)
- return -1;
- }
-
- nat64_session_reset_timeout (ste, ctx->vm);
-
- ip4->src_address.as_u32 = bibe->out_addr.as_u32;
- udp->src_port = bibe->out_port;
-
- ip4->dst_address.as_u32 = ste->out_r_addr.as_u32;
-
- if (proto == IP_PROTOCOL_TCP)
- {
- u16 *checksum;
- ip_csum_t csum;
- tcp_header_t *tcp = ip6_next_header (ip6);
-
- checksum = &tcp->checksum;
- csum = ip_csum_sub_even (*checksum, sport);
- csum = ip_csum_add_even (csum, udp->src_port);
- *checksum = ip_csum_fold (csum);
- }
-
- return 0;
-}
-
-static int
-nat64_in2out_icmp_set_cb (ip6_header_t * ip6, ip4_header_t * ip4, void *arg)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_in2out_set_ctx_t *ctx = arg;
- nat64_db_bib_entry_t *bibe;
- nat64_db_st_entry_t *ste;
- ip46_address_t saddr, daddr;
- u32 sw_if_index, fib_index;
- icmp46_header_t *icmp = ip6_next_header (ip6);
-
- sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
- fib_index =
- fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
-
- saddr.as_u64[0] = ip6->src_address.as_u64[0];
- saddr.as_u64[1] = ip6->src_address.as_u64[1];
- daddr.as_u64[0] = ip6->dst_address.as_u64[0];
- daddr.as_u64[1] = ip6->dst_address.as_u64[1];
-
- if (icmp->type == ICMP4_echo_request || icmp->type == ICMP4_echo_reply)
- {
- u16 in_id = ((u16 *) (icmp))[2];
- ste =
- nat64_db_st_entry_find (&nm->db, &saddr, &daddr, in_id, 0,
- IP_PROTOCOL_ICMP, fib_index, 1);
-
- if (ste)
- {
- bibe =
- nat64_db_bib_entry_by_index (&nm->db, IP_PROTOCOL_ICMP,
- ste->bibe_index);
- if (!bibe)
- return -1;
- }
- else
- {
- bibe =
- nat64_db_bib_entry_find (&nm->db, &saddr, in_id,
- IP_PROTOCOL_ICMP, fib_index, 1);
-
- if (!bibe)
- {
- u16 out_id;
- ip4_address_t out_addr;
- if (nat64_alloc_out_addr_and_port
- (fib_index, SNAT_PROTOCOL_ICMP, &out_addr, &out_id))
- return -1;
-
- bibe =
- nat64_db_bib_entry_create (&nm->db, &ip6->src_address,
- &out_addr, in_id,
- clib_host_to_net_u16 (out_id),
- fib_index, IP_PROTOCOL_ICMP, 0);
- if (!bibe)
- return -1;
- }
-
- nat64_extract_ip4 (&ip6->dst_address, &daddr.ip4, fib_index);
- ste =
- nat64_db_st_entry_create (&nm->db, bibe, &ip6->dst_address,
- &daddr.ip4, 0);
- if (!ste)
- return -1;
- }
-
- nat64_session_reset_timeout (ste, ctx->vm);
-
- ip4->src_address.as_u32 = bibe->out_addr.as_u32;
- ((u16 *) (icmp))[2] = bibe->out_port;
-
- ip4->dst_address.as_u32 = ste->out_r_addr.as_u32;
- }
- else
- {
- if (!vec_len (nm->addr_pool))
- return -1;
-
- ip4->src_address.as_u32 = nm->addr_pool[0].addr.as_u32;
- nat64_extract_ip4 (&ip6->dst_address, &ip4->dst_address, fib_index);
- }
-
- return 0;
-}
-
-static int
-nat64_in2out_inner_icmp_set_cb (ip6_header_t * ip6, ip4_header_t * ip4,
- void *arg)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_in2out_set_ctx_t *ctx = arg;
- nat64_db_st_entry_t *ste;
- nat64_db_bib_entry_t *bibe;
- ip46_address_t saddr, daddr;
- u32 sw_if_index, fib_index;
- u8 proto = ip6->protocol;
-
- sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
- fib_index =
- fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
-
- saddr.as_u64[0] = ip6->src_address.as_u64[0];
- saddr.as_u64[1] = ip6->src_address.as_u64[1];
- daddr.as_u64[0] = ip6->dst_address.as_u64[0];
- daddr.as_u64[1] = ip6->dst_address.as_u64[1];
-
- if (proto == IP_PROTOCOL_ICMP6)
- {
- icmp46_header_t *icmp = ip6_next_header (ip6);
- u16 in_id = ((u16 *) (icmp))[2];
- proto = IP_PROTOCOL_ICMP;
-
- if (!
- (icmp->type == ICMP4_echo_request
- || icmp->type == ICMP4_echo_reply))
- return -1;
-
- ste =
- nat64_db_st_entry_find (&nm->db, &daddr, &saddr, in_id, 0, proto,
- fib_index, 1);
- if (!ste)
- return -1;
-
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
-
- ip4->dst_address.as_u32 = bibe->out_addr.as_u32;
- ((u16 *) (icmp))[2] = bibe->out_port;
- ip4->src_address.as_u32 = ste->out_r_addr.as_u32;
- }
- else
- {
- udp_header_t *udp = ip6_next_header (ip6);
- tcp_header_t *tcp = ip6_next_header (ip6);
- u16 *checksum;
- ip_csum_t csum;
-
- u16 sport = udp->src_port;
- u16 dport = udp->dst_port;
-
- ste =
- nat64_db_st_entry_find (&nm->db, &daddr, &saddr, dport, sport, proto,
- fib_index, 1);
- if (!ste)
- return -1;
-
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
-
- ip4->dst_address.as_u32 = bibe->out_addr.as_u32;
- udp->dst_port = bibe->out_port;
- ip4->src_address.as_u32 = ste->out_r_addr.as_u32;
-
- if (proto == IP_PROTOCOL_TCP)
- checksum = &tcp->checksum;
- else
- checksum = &udp->checksum;
- csum = ip_csum_sub_even (*checksum, dport);
- csum = ip_csum_add_even (csum, udp->dst_port);
- *checksum = ip_csum_fold (csum);
- }
-
- return 0;
-}
-
-typedef struct unk_proto_st_walk_ctx_t_
-{
- ip6_address_t src_addr;
- ip6_address_t dst_addr;
- ip4_address_t out_addr;
- u32 fib_index;
- u8 proto;
-} unk_proto_st_walk_ctx_t;
-
-static int
-unk_proto_st_walk (nat64_db_st_entry_t * ste, void *arg)
-{
- nat64_main_t *nm = &nat64_main;
- unk_proto_st_walk_ctx_t *ctx = arg;
- nat64_db_bib_entry_t *bibe;
- ip46_address_t saddr, daddr;
-
- if (ip46_address_is_equal (&ste->in_r_addr, &ctx->dst_addr))
- {
- bibe =
- nat64_db_bib_entry_by_index (&nm->db, ste->proto, ste->bibe_index);
- if (!bibe)
- return -1;
-
- if (ip46_address_is_equal (&bibe->in_addr, &ctx->src_addr)
- && bibe->fib_index == ctx->fib_index)
- {
- memset (&saddr, 0, sizeof (saddr));
- saddr.ip4.as_u32 = bibe->out_addr.as_u32;
- memset (&daddr, 0, sizeof (daddr));
- nat64_extract_ip4 (&ctx->dst_addr, &daddr.ip4, ctx->fib_index);
-
- if (nat64_db_st_entry_find
- (&nm->db, &daddr, &saddr, 0, 0, ctx->proto, ctx->fib_index, 0))
- return -1;
-
- ctx->out_addr.as_u32 = bibe->out_addr.as_u32;
- return 1;
- }
- }
-
- return 0;
-}
-
-static int
-nat64_in2out_unk_proto_set_cb (ip6_header_t * ip6, ip4_header_t * ip4,
- void *arg)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_in2out_set_ctx_t *ctx = arg;
- nat64_db_bib_entry_t *bibe;
- nat64_db_st_entry_t *ste;
- ip46_address_t saddr, daddr, addr;
- u32 sw_if_index, fib_index;
- u8 proto = ip6->protocol;
- int i;
-
- sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
- fib_index =
- fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
-
- saddr.as_u64[0] = ip6->src_address.as_u64[0];
- saddr.as_u64[1] = ip6->src_address.as_u64[1];
- daddr.as_u64[0] = ip6->dst_address.as_u64[0];
- daddr.as_u64[1] = ip6->dst_address.as_u64[1];
-
- ste =
- nat64_db_st_entry_find (&nm->db, &saddr, &daddr, 0, 0, proto, fib_index,
- 1);
-
- if (ste)
- {
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
- }
- else
- {
- bibe =
- nat64_db_bib_entry_find (&nm->db, &saddr, 0, proto, fib_index, 1);
-
- if (!bibe)
- {
- /* Choose same out address as for TCP/UDP session to same dst */
- unk_proto_st_walk_ctx_t ctx = {
- .src_addr.as_u64[0] = ip6->src_address.as_u64[0],
- .src_addr.as_u64[1] = ip6->src_address.as_u64[1],
- .dst_addr.as_u64[0] = ip6->dst_address.as_u64[0],
- .dst_addr.as_u64[1] = ip6->dst_address.as_u64[1],
- .out_addr.as_u32 = 0,
- .fib_index = fib_index,
- .proto = proto,
- };
-
- nat64_db_st_walk (&nm->db, IP_PROTOCOL_TCP, unk_proto_st_walk,
- &ctx);
-
- if (!ctx.out_addr.as_u32)
- nat64_db_st_walk (&nm->db, IP_PROTOCOL_UDP, unk_proto_st_walk,
- &ctx);
-
- /* Verify if out address is not already in use for protocol */
- memset (&addr, 0, sizeof (addr));
- addr.ip4.as_u32 = ctx.out_addr.as_u32;
- if (nat64_db_bib_entry_find (&nm->db, &addr, 0, proto, 0, 0))
- ctx.out_addr.as_u32 = 0;
-
- if (!ctx.out_addr.as_u32)
- {
- for (i = 0; i < vec_len (nm->addr_pool); i++)
- {
- addr.ip4.as_u32 = nm->addr_pool[i].addr.as_u32;
- if (!nat64_db_bib_entry_find
- (&nm->db, &addr, 0, proto, 0, 0))
- break;
- }
- }
-
- if (!ctx.out_addr.as_u32)
- return -1;
-
- bibe =
- nat64_db_bib_entry_create (&nm->db, &ip6->src_address,
- &ctx.out_addr, 0, 0, fib_index, proto,
- 0);
- if (!bibe)
- return -1;
- }
-
- nat64_extract_ip4 (&ip6->dst_address, &daddr.ip4, fib_index);
- ste =
- nat64_db_st_entry_create (&nm->db, bibe, &ip6->dst_address,
- &daddr.ip4, 0);
- if (!ste)
- return -1;
- }
-
- nat64_session_reset_timeout (ste, ctx->vm);
-
- ip4->src_address.as_u32 = bibe->out_addr.as_u32;
- ip4->dst_address.as_u32 = ste->out_r_addr.as_u32;
-
- return 0;
-}
-
-
-
-static int
-nat64_in2out_tcp_udp_hairpinning (vlib_main_t * vm, vlib_buffer_t * b,
- ip6_header_t * ip6)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_db_bib_entry_t *bibe;
- nat64_db_st_entry_t *ste;
- ip46_address_t saddr, daddr;
- u32 sw_if_index, fib_index;
- udp_header_t *udp = ip6_next_header (ip6);
- tcp_header_t *tcp = ip6_next_header (ip6);
- u8 proto = ip6->protocol;
- u16 sport = udp->src_port;
- u16 dport = udp->dst_port;
- u16 *checksum;
- ip_csum_t csum;
-
- sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
- fib_index =
- fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
-
- saddr.as_u64[0] = ip6->src_address.as_u64[0];
- saddr.as_u64[1] = ip6->src_address.as_u64[1];
- daddr.as_u64[0] = ip6->dst_address.as_u64[0];
- daddr.as_u64[1] = ip6->dst_address.as_u64[1];
-
- if (proto == IP_PROTOCOL_UDP)
- checksum = &udp->checksum;
- else
- checksum = &tcp->checksum;
-
- csum = ip_csum_sub_even (*checksum, ip6->src_address.as_u64[0]);
- csum = ip_csum_sub_even (csum, ip6->src_address.as_u64[1]);
- csum = ip_csum_sub_even (csum, ip6->dst_address.as_u64[0]);
- csum = ip_csum_sub_even (csum, ip6->dst_address.as_u64[1]);
- csum = ip_csum_sub_even (csum, sport);
- csum = ip_csum_sub_even (csum, dport);
-
- ste =
- nat64_db_st_entry_find (&nm->db, &saddr, &daddr, sport, dport, proto,
- fib_index, 1);
-
- if (ste)
- {
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
- }
- else
- {
- bibe =
- nat64_db_bib_entry_find (&nm->db, &saddr, sport, proto, fib_index, 1);
-
- if (!bibe)
- {
- u16 out_port;
- ip4_address_t out_addr;
- if (nat64_alloc_out_addr_and_port
- (fib_index, ip_proto_to_snat_proto (proto), &out_addr,
- &out_port))
- return -1;
-
- bibe =
- nat64_db_bib_entry_create (&nm->db, &ip6->src_address, &out_addr,
- sport, clib_host_to_net_u16 (out_port),
- fib_index, proto, 0);
- if (!bibe)
- return -1;
- }
-
- nat64_extract_ip4 (&ip6->dst_address, &daddr.ip4, fib_index);
- ste =
- nat64_db_st_entry_create (&nm->db, bibe, &ip6->dst_address,
- &daddr.ip4, dport);
- if (!ste)
- return -1;
- }
-
- nat64_session_reset_timeout (ste, vm);
-
- sport = udp->src_port = bibe->out_port;
- nat64_compose_ip6 (&ip6->src_address, &bibe->out_addr, fib_index);
-
- memset (&saddr, 0, sizeof (saddr));
- memset (&daddr, 0, sizeof (daddr));
- saddr.ip4.as_u32 = bibe->out_addr.as_u32;
- daddr.ip4.as_u32 = ste->out_r_addr.as_u32;
-
- ste =
- nat64_db_st_entry_find (&nm->db, &daddr, &saddr, dport, sport, proto, 0,
- 0);
-
- if (ste)
- {
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
- }
- else
- {
- bibe = nat64_db_bib_entry_find (&nm->db, &daddr, dport, proto, 0, 0);
-
- if (!bibe)
- return -1;
-
- ste =
- nat64_db_st_entry_create (&nm->db, bibe, &ip6->src_address,
- &saddr.ip4, sport);
- }
-
- ip6->dst_address.as_u64[0] = bibe->in_addr.as_u64[0];
- ip6->dst_address.as_u64[1] = bibe->in_addr.as_u64[1];
- udp->dst_port = bibe->in_port;
-
- csum = ip_csum_add_even (csum, ip6->src_address.as_u64[0]);
- csum = ip_csum_add_even (csum, ip6->src_address.as_u64[1]);
- csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[0]);
- csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[1]);
- csum = ip_csum_add_even (csum, udp->src_port);
- csum = ip_csum_add_even (csum, udp->dst_port);
- *checksum = ip_csum_fold (csum);
-
- return 0;
-}
-
-static int
-nat64_in2out_icmp_hairpinning (vlib_main_t * vm, vlib_buffer_t * b,
- ip6_header_t * ip6)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_db_bib_entry_t *bibe;
- nat64_db_st_entry_t *ste;
- icmp46_header_t *icmp = ip6_next_header (ip6);
- ip6_header_t *inner_ip6;
- ip46_address_t saddr, daddr;
- u32 sw_if_index, fib_index;
- u8 proto;
- udp_header_t *udp;
- tcp_header_t *tcp;
- u16 *checksum, sport, dport;
- ip_csum_t csum;
-
- if (icmp->type == ICMP6_echo_request || icmp->type == ICMP6_echo_reply)
- return -1;
-
- inner_ip6 = (ip6_header_t *) u8_ptr_add (icmp, 8);
-
- proto = inner_ip6->protocol;
-
- if (proto == IP_PROTOCOL_ICMP6)
- return -1;
-
- sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
- fib_index =
- fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
-
- saddr.as_u64[0] = inner_ip6->src_address.as_u64[0];
- saddr.as_u64[1] = inner_ip6->src_address.as_u64[1];
- daddr.as_u64[0] = inner_ip6->dst_address.as_u64[0];
- daddr.as_u64[1] = inner_ip6->dst_address.as_u64[1];
-
- udp = ip6_next_header (inner_ip6);
- tcp = ip6_next_header (inner_ip6);
-
- sport = udp->src_port;
- dport = udp->dst_port;
-
- if (proto == IP_PROTOCOL_UDP)
- checksum = &udp->checksum;
- else
- checksum = &tcp->checksum;
-
- csum = ip_csum_sub_even (*checksum, inner_ip6->src_address.as_u64[0]);
- csum = ip_csum_sub_even (csum, inner_ip6->src_address.as_u64[1]);
- csum = ip_csum_sub_even (csum, inner_ip6->dst_address.as_u64[0]);
- csum = ip_csum_sub_even (csum, inner_ip6->dst_address.as_u64[1]);
- csum = ip_csum_sub_even (csum, sport);
- csum = ip_csum_sub_even (csum, dport);
-
- ste =
- nat64_db_st_entry_find (&nm->db, &daddr, &saddr, dport, sport, proto,
- fib_index, 1);
- if (!ste)
- return -1;
-
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
-
- dport = udp->dst_port = bibe->out_port;
- nat64_compose_ip6 (&inner_ip6->dst_address, &bibe->out_addr, fib_index);
-
- memset (&saddr, 0, sizeof (saddr));
- memset (&daddr, 0, sizeof (daddr));
- saddr.ip4.as_u32 = ste->out_r_addr.as_u32;
- daddr.ip4.as_u32 = bibe->out_addr.as_u32;
-
- ste =
- nat64_db_st_entry_find (&nm->db, &saddr, &daddr, sport, dport, proto, 0,
- 0);
- if (!ste)
- return -1;
-
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
-
- inner_ip6->src_address.as_u64[0] = bibe->in_addr.as_u64[0];
- inner_ip6->src_address.as_u64[1] = bibe->in_addr.as_u64[1];
- udp->src_port = bibe->in_port;
-
- csum = ip_csum_add_even (csum, inner_ip6->src_address.as_u64[0]);
- csum = ip_csum_add_even (csum, inner_ip6->src_address.as_u64[1]);
- csum = ip_csum_add_even (csum, inner_ip6->dst_address.as_u64[0]);
- csum = ip_csum_add_even (csum, inner_ip6->dst_address.as_u64[1]);
- csum = ip_csum_add_even (csum, udp->src_port);
- csum = ip_csum_add_even (csum, udp->dst_port);
- *checksum = ip_csum_fold (csum);
-
- if (!vec_len (nm->addr_pool))
- return -1;
-
- nat64_compose_ip6 (&ip6->src_address, &nm->addr_pool[0].addr, fib_index);
- ip6->dst_address.as_u64[0] = inner_ip6->src_address.as_u64[0];
- ip6->dst_address.as_u64[1] = inner_ip6->src_address.as_u64[1];
-
- icmp->checksum = 0;
- csum = ip_csum_with_carry (0, ip6->payload_length);
- csum = ip_csum_with_carry (csum, clib_host_to_net_u16 (ip6->protocol));
- csum = ip_csum_with_carry (csum, ip6->src_address.as_u64[0]);
- csum = ip_csum_with_carry (csum, ip6->src_address.as_u64[1]);
- csum = ip_csum_with_carry (csum, ip6->dst_address.as_u64[0]);
- csum = ip_csum_with_carry (csum, ip6->dst_address.as_u64[1]);
- csum =
- ip_incremental_checksum (csum, icmp,
- clib_net_to_host_u16 (ip6->payload_length));
- icmp->checksum = ~ip_csum_fold (csum);
-
- return 0;
-}
-
-static int
-nat64_in2out_unk_proto_hairpinning (vlib_main_t * vm, vlib_buffer_t * b,
- ip6_header_t * ip6)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_db_bib_entry_t *bibe;
- nat64_db_st_entry_t *ste;
- ip46_address_t saddr, daddr, addr;
- u32 sw_if_index, fib_index;
- u8 proto = ip6->protocol;
- int i;
-
- sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
- fib_index =
- fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
-
- saddr.as_u64[0] = ip6->src_address.as_u64[0];
- saddr.as_u64[1] = ip6->src_address.as_u64[1];
- daddr.as_u64[0] = ip6->dst_address.as_u64[0];
- daddr.as_u64[1] = ip6->dst_address.as_u64[1];
-
- ste =
- nat64_db_st_entry_find (&nm->db, &saddr, &daddr, 0, 0, proto, fib_index,
- 1);
-
- if (ste)
- {
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
- }
- else
- {
- bibe =
- nat64_db_bib_entry_find (&nm->db, &saddr, 0, proto, fib_index, 1);
-
- if (!bibe)
- {
- /* Choose same out address as for TCP/UDP session to same dst */
- unk_proto_st_walk_ctx_t ctx = {
- .src_addr.as_u64[0] = ip6->src_address.as_u64[0],
- .src_addr.as_u64[1] = ip6->src_address.as_u64[1],
- .dst_addr.as_u64[0] = ip6->dst_address.as_u64[0],
- .dst_addr.as_u64[1] = ip6->dst_address.as_u64[1],
- .out_addr.as_u32 = 0,
- .fib_index = fib_index,
- .proto = proto,
- };
-
- nat64_db_st_walk (&nm->db, IP_PROTOCOL_TCP, unk_proto_st_walk,
- &ctx);
-
- if (!ctx.out_addr.as_u32)
- nat64_db_st_walk (&nm->db, IP_PROTOCOL_UDP, unk_proto_st_walk,
- &ctx);
-
- /* Verify if out address is not already in use for protocol */
- memset (&addr, 0, sizeof (addr));
- addr.ip4.as_u32 = ctx.out_addr.as_u32;
- if (nat64_db_bib_entry_find (&nm->db, &addr, 0, proto, 0, 0))
- ctx.out_addr.as_u32 = 0;
-
- if (!ctx.out_addr.as_u32)
- {
- for (i = 0; i < vec_len (nm->addr_pool); i++)
- {
- addr.ip4.as_u32 = nm->addr_pool[i].addr.as_u32;
- if (!nat64_db_bib_entry_find
- (&nm->db, &addr, 0, proto, 0, 0))
- break;
- }
- }
-
- if (!ctx.out_addr.as_u32)
- return -1;
-
- bibe =
- nat64_db_bib_entry_create (&nm->db, &ip6->src_address,
- &ctx.out_addr, 0, 0, fib_index, proto,
- 0);
- if (!bibe)
- return -1;
- }
-
- nat64_extract_ip4 (&ip6->dst_address, &daddr.ip4, fib_index);
- ste =
- nat64_db_st_entry_create (&nm->db, bibe, &ip6->dst_address,
- &daddr.ip4, 0);
- if (!ste)
- return -1;
- }
-
- nat64_session_reset_timeout (ste, vm);
-
- nat64_compose_ip6 (&ip6->src_address, &bibe->out_addr, fib_index);
-
- memset (&saddr, 0, sizeof (saddr));
- memset (&daddr, 0, sizeof (daddr));
- saddr.ip4.as_u32 = bibe->out_addr.as_u32;
- daddr.ip4.as_u32 = ste->out_r_addr.as_u32;
-
- ste = nat64_db_st_entry_find (&nm->db, &daddr, &saddr, 0, 0, proto, 0, 0);
-
- if (ste)
- {
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
- }
- else
- {
- bibe = nat64_db_bib_entry_find (&nm->db, &daddr, 0, proto, 0, 0);
-
- if (!bibe)
- return -1;
-
- ste =
- nat64_db_st_entry_create (&nm->db, bibe, &ip6->src_address,
- &saddr.ip4, 0);
- }
-
- ip6->dst_address.as_u64[0] = bibe->in_addr.as_u64[0];
- ip6->dst_address.as_u64[1] = bibe->in_addr.as_u64[1];
-
- return 0;
-}
-
-static inline uword
-nat64_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame, u8 is_slow_path)
-{
- u32 n_left_from, *from, *to_next;
- nat64_in2out_next_t next_index;
- u32 pkts_processed = 0;
- u32 stats_node_index;
-
- stats_node_index =
- is_slow_path ? nat64_in2out_slowpath_node.index : nat64_in2out_node.index;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t *b0;
- u32 next0;
- ip6_header_t *ip60;
- u16 l4_offset0, frag_offset0;
- u8 l4_protocol0;
- u32 proto0;
- nat64_in2out_set_ctx_t ctx0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
- ip60 = vlib_buffer_get_current (b0);
-
- ctx0.b = b0;
- ctx0.vm = vm;
-
- next0 = NAT64_IN2OUT_NEXT_IP4_LOOKUP;
-
- if (PREDICT_FALSE
- (ip6_parse
- (ip60, b0->current_length, &l4_protocol0, &l4_offset0,
- &frag_offset0)))
- {
- next0 = NAT64_IN2OUT_NEXT_DROP;
- b0->error = node->errors[NAT64_IN2OUT_ERROR_UNKNOWN];
- goto trace0;
- }
-
- proto0 = ip_proto_to_snat_proto (l4_protocol0);
- if (frag_offset0 != 0)
- {
- next0 = NAT64_IN2OUT_NEXT_DROP;
- b0->error =
- node->errors[NAT64_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
- goto trace0;
- }
-
- if (is_slow_path)
- {
- if (PREDICT_TRUE (proto0 == ~0))
- {
- if (is_hairpinning (&ip60->dst_address))
- {
- next0 = NAT64_IN2OUT_NEXT_IP6_LOOKUP;
- if (nat64_in2out_unk_proto_hairpinning (vm, b0, ip60))
- {
- next0 = NAT64_IN2OUT_NEXT_DROP;
- b0->error =
- node->errors[NAT64_IN2OUT_ERROR_NO_TRANSLATION];
- }
- goto trace0;
- }
-
- if (ip6_to_ip4 (b0, nat64_in2out_unk_proto_set_cb, &ctx0))
- {
- next0 = NAT64_IN2OUT_NEXT_DROP;
- b0->error =
- node->errors[NAT64_IN2OUT_ERROR_NO_TRANSLATION];
- goto trace0;
- }
- }
- goto trace0;
- }
- else
- {
- if (PREDICT_FALSE (proto0 == ~0))
- {
- next0 = NAT64_IN2OUT_NEXT_SLOWPATH;
- goto trace0;
- }
- }
-
- if (proto0 == SNAT_PROTOCOL_ICMP)
- {
- if (is_hairpinning (&ip60->dst_address))
- {
- next0 = NAT64_IN2OUT_NEXT_IP6_LOOKUP;
- if (nat64_in2out_icmp_hairpinning (vm, b0, ip60))
- {
- next0 = NAT64_IN2OUT_NEXT_DROP;
- b0->error =
- node->errors[NAT64_IN2OUT_ERROR_NO_TRANSLATION];
- }
- goto trace0;
- }
-
- if (icmp6_to_icmp
- (b0, nat64_in2out_icmp_set_cb, &ctx0,
- nat64_in2out_inner_icmp_set_cb, &ctx0))
- {
- next0 = NAT64_IN2OUT_NEXT_DROP;
- b0->error = node->errors[NAT64_IN2OUT_ERROR_NO_TRANSLATION];
- goto trace0;
- }
- }
- else if (proto0 == SNAT_PROTOCOL_TCP || proto0 == SNAT_PROTOCOL_UDP)
- {
- if (is_hairpinning (&ip60->dst_address))
- {
- next0 = NAT64_IN2OUT_NEXT_IP6_LOOKUP;
- if (nat64_in2out_tcp_udp_hairpinning (vm, b0, ip60))
- {
- next0 = NAT64_IN2OUT_NEXT_DROP;
- b0->error =
- node->errors[NAT64_IN2OUT_ERROR_NO_TRANSLATION];
- }
- goto trace0;
- }
-
- if (ip6_to_ip4_tcp_udp
- (b0, nat64_in2out_tcp_udp_set_cb, &ctx0, 0))
- {
- next0 = NAT64_IN2OUT_NEXT_DROP;
- b0->error = node->errors[NAT64_IN2OUT_ERROR_NO_TRANSLATION];
- goto trace0;
- }
- }
-
- trace0:
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- nat64_in2out_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- t->next_index = next0;
- t->is_slow_path = is_slow_path;
- }
-
- pkts_processed += next0 != NAT64_IN2OUT_NEXT_DROP;
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
- }
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
- vlib_node_increment_counter (vm, stats_node_index,
- NAT64_IN2OUT_ERROR_IN2OUT_PACKETS,
- pkts_processed);
- return frame->n_vectors;
-}
-
-static uword
-nat64_in2out_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return nat64_in2out_node_fn_inline (vm, node, frame, 0);
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (nat64_in2out_node) = {
- .function = nat64_in2out_node_fn,
- .name = "nat64-in2out",
- .vector_size = sizeof (u32),
- .format_trace = format_nat64_in2out_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (nat64_in2out_error_strings),
- .error_strings = nat64_in2out_error_strings,
- .n_next_nodes = NAT64_IN2OUT_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes = {
- [NAT64_IN2OUT_NEXT_DROP] = "error-drop",
- [NAT64_IN2OUT_NEXT_IP4_LOOKUP] = "ip4-lookup",
- [NAT64_IN2OUT_NEXT_IP6_LOOKUP] = "ip6-lookup",
- [NAT64_IN2OUT_NEXT_SLOWPATH] = "nat64-in2out-slowpath",
- },
-};
-/* *INDENT-ON* */
-
-VLIB_NODE_FUNCTION_MULTIARCH (nat64_in2out_node, nat64_in2out_node_fn);
-
-static uword
-nat64_in2out_slowpath_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- return nat64_in2out_node_fn_inline (vm, node, frame, 1);
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (nat64_in2out_slowpath_node) = {
- .function = nat64_in2out_slowpath_node_fn,
- .name = "nat64-in2out-slowpath",
- .vector_size = sizeof (u32),
- .format_trace = format_nat64_in2out_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (nat64_in2out_error_strings),
- .error_strings = nat64_in2out_error_strings,
- .n_next_nodes = NAT64_IN2OUT_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes = {
- [NAT64_IN2OUT_NEXT_DROP] = "error-drop",
- [NAT64_IN2OUT_NEXT_IP4_LOOKUP] = "ip4-lookup",
- [NAT64_IN2OUT_NEXT_IP6_LOOKUP] = "ip6-lookup",
- [NAT64_IN2OUT_NEXT_SLOWPATH] = "nat64-in2out-slowpath",
- },
-};
-/* *INDENT-ON* */
-
-VLIB_NODE_FUNCTION_MULTIARCH (nat64_in2out_slowpath_node,
- nat64_in2out_slowpath_node_fn);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/plugins/snat/nat64_out2in.c b/src/plugins/snat/nat64_out2in.c
deleted file mode 100644
index cd5b253ab5c..00000000000
--- a/src/plugins/snat/nat64_out2in.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright (c) 2017 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.
- */
-/**
- * @file
- * @brief NAT64 IPv4 to IPv6 translation (otside to inside network)
- */
-
-#include <snat/nat64.h>
-#include <vnet/ip/ip4_to_ip6.h>
-#include <vnet/fib/ip4_fib.h>
-
-typedef struct
-{
- u32 sw_if_index;
- u32 next_index;
-} nat64_out2in_trace_t;
-
-static u8 *
-format_nat64_out2in_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 *);
- nat64_out2in_trace_t *t = va_arg (*args, nat64_out2in_trace_t *);
-
- s =
- format (s, "NAT64-out2in: sw_if_index %d, next index %d", t->sw_if_index,
- t->next_index);
-
- return s;
-}
-
-vlib_node_registration_t nat64_out2in_node;
-
-#define foreach_nat64_out2in_error \
-_(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \
-_(OUT2IN_PACKETS, "Good out2in packets processed") \
-_(NO_TRANSLATION, "No translation") \
-_(UNKNOWN, "unknown")
-
-typedef enum
-{
-#define _(sym,str) NAT64_OUT2IN_ERROR_##sym,
- foreach_nat64_out2in_error
-#undef _
- NAT64_OUT2IN_N_ERROR,
-} nat64_out2in_error_t;
-
-static char *nat64_out2in_error_strings[] = {
-#define _(sym,string) string,
- foreach_nat64_out2in_error
-#undef _
-};
-
-typedef enum
-{
- NAT64_OUT2IN_NEXT_LOOKUP,
- NAT64_OUT2IN_NEXT_DROP,
- NAT64_OUT2IN_N_NEXT,
-} nat64_out2in_next_t;
-
-typedef struct nat64_out2in_set_ctx_t_
-{
- vlib_buffer_t *b;
- vlib_main_t *vm;
-} nat64_out2in_set_ctx_t;
-
-static int
-nat64_out2in_tcp_udp_set_cb (ip4_header_t * ip4, ip6_header_t * ip6,
- void *arg)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_out2in_set_ctx_t *ctx = arg;
- nat64_db_bib_entry_t *bibe;
- nat64_db_st_entry_t *ste;
- ip46_address_t saddr, daddr;
- ip6_address_t ip6_saddr;
- udp_header_t *udp = ip4_next_header (ip4);
- tcp_header_t *tcp = ip4_next_header (ip4);
- u8 proto = ip4->protocol;
- u16 dport = udp->dst_port;
- u16 sport = udp->src_port;
- u32 sw_if_index, fib_index;
- u16 *checksum;
- ip_csum_t csum;
-
- sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
- fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
-
- memset (&saddr, 0, sizeof (saddr));
- saddr.ip4.as_u32 = ip4->src_address.as_u32;
- memset (&daddr, 0, sizeof (daddr));
- daddr.ip4.as_u32 = ip4->dst_address.as_u32;
-
- ste =
- nat64_db_st_entry_find (&nm->db, &daddr, &saddr, dport, sport, proto,
- fib_index, 0);
- if (ste)
- {
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
- }
- else
- {
- bibe =
- nat64_db_bib_entry_find (&nm->db, &daddr, dport, proto, fib_index, 0);
-
- if (!bibe)
- return -1;
-
- nat64_compose_ip6 (&ip6_saddr, &ip4->src_address, bibe->fib_index);
- ste =
- nat64_db_st_entry_create (&nm->db, bibe, &ip6_saddr, &saddr.ip4,
- sport);
- }
-
- nat64_session_reset_timeout (ste, ctx->vm);
-
- ip6->src_address.as_u64[0] = ste->in_r_addr.as_u64[0];
- ip6->src_address.as_u64[1] = ste->in_r_addr.as_u64[1];
-
- ip6->dst_address.as_u64[0] = bibe->in_addr.as_u64[0];
- ip6->dst_address.as_u64[1] = bibe->in_addr.as_u64[1];
- udp->dst_port = bibe->in_port;
-
- if (proto == IP_PROTOCOL_UDP)
- checksum = &udp->checksum;
- else
- checksum = &tcp->checksum;
- csum = ip_csum_sub_even (*checksum, dport);
- csum = ip_csum_add_even (csum, udp->dst_port);
- *checksum = ip_csum_fold (csum);
-
- vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
-
- return 0;
-}
-
-static int
-nat64_out2in_icmp_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, void *arg)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_out2in_set_ctx_t *ctx = arg;
- nat64_db_bib_entry_t *bibe;
- nat64_db_st_entry_t *ste;
- ip46_address_t saddr, daddr;
- ip6_address_t ip6_saddr;
- u32 sw_if_index, fib_index;
- icmp46_header_t *icmp = ip4_next_header (ip4);
-
- sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
- fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
-
- memset (&saddr, 0, sizeof (saddr));
- saddr.ip4.as_u32 = ip4->src_address.as_u32;
- memset (&daddr, 0, sizeof (daddr));
- daddr.ip4.as_u32 = ip4->dst_address.as_u32;
-
- if (icmp->type == ICMP6_echo_request || icmp->type == ICMP6_echo_reply)
- {
- u16 out_id = ((u16 *) (icmp))[2];
- ste =
- nat64_db_st_entry_find (&nm->db, &daddr, &saddr, out_id, 0,
- IP_PROTOCOL_ICMP, fib_index, 0);
-
- if (ste)
- {
- bibe =
- nat64_db_bib_entry_by_index (&nm->db, IP_PROTOCOL_ICMP,
- ste->bibe_index);
- if (!bibe)
- return -1;
- }
- else
- {
- bibe =
- nat64_db_bib_entry_find (&nm->db, &daddr, out_id,
- IP_PROTOCOL_ICMP, fib_index, 0);
- if (!bibe)
- return -1;
-
- nat64_compose_ip6 (&ip6_saddr, &ip4->src_address, bibe->fib_index);
- ste =
- nat64_db_st_entry_create (&nm->db, bibe, &ip6_saddr, &saddr.ip4,
- 0);
- }
-
- nat64_session_reset_timeout (ste, ctx->vm);
-
- ip6->src_address.as_u64[0] = ste->in_r_addr.as_u64[0];
- ip6->src_address.as_u64[1] = ste->in_r_addr.as_u64[1];
-
- ip6->dst_address.as_u64[0] = bibe->in_addr.as_u64[0];
- ip6->dst_address.as_u64[1] = bibe->in_addr.as_u64[1];
- ((u16 *) (icmp))[2] = bibe->in_port;
-
- vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
- }
- else
- {
- ip6_header_t *inner_ip6 = (ip6_header_t *) u8_ptr_add (icmp, 8);
-
- nat64_compose_ip6 (&ip6->src_address, &ip4->src_address,
- vnet_buffer (ctx->b)->sw_if_index[VLIB_TX]);
- ip6->dst_address.as_u64[0] = inner_ip6->src_address.as_u64[0];
- ip6->dst_address.as_u64[1] = inner_ip6->src_address.as_u64[1];
- }
-
- return 0;
-}
-
-static int
-nat64_out2in_inner_icmp_set_cb (ip4_header_t * ip4, ip6_header_t * ip6,
- void *arg)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_out2in_set_ctx_t *ctx = arg;
- nat64_db_bib_entry_t *bibe;
- nat64_db_st_entry_t *ste;
- ip46_address_t saddr, daddr;
- u32 sw_if_index, fib_index;
- u8 proto = ip4->protocol;
-
- sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
- fib_index =
- fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
-
- memset (&saddr, 0, sizeof (saddr));
- saddr.ip4.as_u32 = ip4->src_address.as_u32;
- memset (&daddr, 0, sizeof (daddr));
- daddr.ip4.as_u32 = ip4->dst_address.as_u32;
-
- if (proto == IP_PROTOCOL_ICMP6)
- {
- icmp46_header_t *icmp = ip4_next_header (ip4);
- u16 out_id = ((u16 *) (icmp))[2];
- proto = IP_PROTOCOL_ICMP;
-
- if (!
- (icmp->type == ICMP6_echo_request
- || icmp->type == ICMP6_echo_reply))
- return -1;
-
- ste =
- nat64_db_st_entry_find (&nm->db, &saddr, &daddr, out_id, 0, proto,
- fib_index, 0);
- if (!ste)
- return -1;
-
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
-
- ip6->dst_address.as_u64[0] = ste->in_r_addr.as_u64[0];
- ip6->dst_address.as_u64[1] = ste->in_r_addr.as_u64[1];
- ip6->src_address.as_u64[0] = bibe->in_addr.as_u64[0];
- ip6->src_address.as_u64[1] = bibe->in_addr.as_u64[1];
- ((u16 *) (icmp))[2] = bibe->in_port;
-
- vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
- }
- else
- {
- udp_header_t *udp = ip4_next_header (ip4);
- tcp_header_t *tcp = ip4_next_header (ip4);
- u16 dport = udp->dst_port;
- u16 sport = udp->src_port;
- u16 *checksum;
- ip_csum_t csum;
-
- ste =
- nat64_db_st_entry_find (&nm->db, &saddr, &daddr, sport, dport, proto,
- fib_index, 0);
- if (!ste)
- return -1;
-
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
-
- nat64_compose_ip6 (&ip6->dst_address, &daddr.ip4, bibe->fib_index);
- ip6->src_address.as_u64[0] = bibe->in_addr.as_u64[0];
- ip6->src_address.as_u64[1] = bibe->in_addr.as_u64[1];
- udp->src_port = bibe->in_port;
-
- if (proto == IP_PROTOCOL_UDP)
- checksum = &udp->checksum;
- else
- checksum = &tcp->checksum;
- if (*checksum)
- {
- csum = ip_csum_sub_even (*checksum, sport);
- csum = ip_csum_add_even (csum, udp->src_port);
- *checksum = ip_csum_fold (csum);
- }
-
- vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
- }
-
- return 0;
-}
-
-static int
-nat64_out2in_unk_proto_set_cb (ip4_header_t * ip4, ip6_header_t * ip6,
- void *arg)
-{
- nat64_main_t *nm = &nat64_main;
- nat64_out2in_set_ctx_t *ctx = arg;
- nat64_db_bib_entry_t *bibe;
- nat64_db_st_entry_t *ste;
- ip46_address_t saddr, daddr;
- ip6_address_t ip6_saddr;
- u32 sw_if_index, fib_index;
- u8 proto = ip4->protocol;
-
- sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
- fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
-
- memset (&saddr, 0, sizeof (saddr));
- saddr.ip4.as_u32 = ip4->src_address.as_u32;
- memset (&daddr, 0, sizeof (daddr));
- daddr.ip4.as_u32 = ip4->dst_address.as_u32;
-
- ste =
- nat64_db_st_entry_find (&nm->db, &daddr, &saddr, 0, 0, proto, fib_index,
- 0);
- if (ste)
- {
- bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
- if (!bibe)
- return -1;
- }
- else
- {
- bibe =
- nat64_db_bib_entry_find (&nm->db, &daddr, 0, proto, fib_index, 0);
-
- if (!bibe)
- return -1;
-
- nat64_compose_ip6 (&ip6_saddr, &ip4->src_address, bibe->fib_index);
- ste =
- nat64_db_st_entry_create (&nm->db, bibe, &ip6_saddr, &saddr.ip4, 0);
- }
-
- nat64_session_reset_timeout (ste, ctx->vm);
-
- ip6->src_address.as_u64[0] = ste->in_r_addr.as_u64[0];
- ip6->src_address.as_u64[1] = ste->in_r_addr.as_u64[1];
-
- ip6->dst_address.as_u64[0] = bibe->in_addr.as_u64[0];
- ip6->dst_address.as_u64[1] = bibe->in_addr.as_u64[1];
-
- vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
-
- return 0;
-}
-
-static uword
-nat64_out2in_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- u32 n_left_from, *from, *to_next;
- nat64_out2in_next_t next_index;
- u32 pkts_processed = 0;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t *b0;
- u32 next0;
- ip4_header_t *ip40;
- u32 proto0;
- nat64_out2in_set_ctx_t ctx0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
- ip40 = vlib_buffer_get_current (b0);
-
- ctx0.b = b0;
- ctx0.vm = vm;
-
- next0 = NAT64_OUT2IN_NEXT_LOOKUP;
-
- proto0 = ip_proto_to_snat_proto (ip40->protocol);
-
- if (proto0 == SNAT_PROTOCOL_ICMP)
- {
- if (icmp_to_icmp6
- (b0, nat64_out2in_icmp_set_cb, &ctx0,
- nat64_out2in_inner_icmp_set_cb, &ctx0))
- {
- next0 = NAT64_OUT2IN_NEXT_DROP;
- b0->error = node->errors[NAT64_OUT2IN_ERROR_NO_TRANSLATION];
- goto trace0;
- }
- }
- else if (proto0 == SNAT_PROTOCOL_TCP || proto0 == SNAT_PROTOCOL_UDP)
- {
- if (ip4_to_ip6_tcp_udp (b0, nat64_out2in_tcp_udp_set_cb, &ctx0))
- {
- next0 = NAT64_OUT2IN_NEXT_DROP;
- b0->error = node->errors[NAT64_OUT2IN_ERROR_NO_TRANSLATION];
- goto trace0;
- }
- }
- else
- {
- if (ip4_to_ip6 (b0, nat64_out2in_unk_proto_set_cb, &ctx0))
- {
- next0 = NAT64_OUT2IN_NEXT_DROP;
- b0->error = node->errors[NAT64_OUT2IN_ERROR_NO_TRANSLATION];
- goto trace0;
- }
- }
-
- trace0:
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- nat64_out2in_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- t->next_index = next0;
- }
-
- pkts_processed += next0 != NAT64_OUT2IN_NEXT_DROP;
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
- }
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
- vlib_node_increment_counter (vm, nat64_out2in_node.index,
- NAT64_OUT2IN_ERROR_OUT2IN_PACKETS,
- pkts_processed);
- return frame->n_vectors;
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (nat64_out2in_node) = {
- .function = nat64_out2in_node_fn,
- .name = "nat64-out2in",
- .vector_size = sizeof (u32),
- .format_trace = format_nat64_out2in_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (nat64_out2in_error_strings),
- .error_strings = nat64_out2in_error_strings,.n_next_nodes = 2,
- /* edit / add dispositions here */
- .next_nodes = {
- [NAT64_OUT2IN_NEXT_DROP] = "error-drop",
- [NAT64_OUT2IN_NEXT_LOOKUP] = "ip6-lookup",
- },
-};
-/* *INDENT-ON* */
-
-VLIB_NODE_FUNCTION_MULTIARCH (nat64_out2in_node, nat64_out2in_node_fn);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/plugins/snat/out2in.c b/src/plugins/snat/out2in.c
deleted file mode 100644
index 329d67dc3bf..00000000000
--- a/src/plugins/snat/out2in.c
+++ /dev/null
@@ -1,2294 +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.
- */
-
-#include <vlib/vlib.h>
-#include <vnet/vnet.h>
-#include <vnet/pg/pg.h>
-#include <vnet/handoff.h>
-
-#include <vnet/ip/ip.h>
-#include <vnet/udp/udp.h>
-#include <vnet/ethernet/ethernet.h>
-#include <vnet/fib/ip4_fib.h>
-#include <snat/snat.h>
-#include <snat/snat_ipfix_logging.h>
-#include <snat/snat_det.h>
-
-#include <vppinfra/hash.h>
-#include <vppinfra/error.h>
-#include <vppinfra/elog.h>
-
-typedef struct {
- u32 sw_if_index;
- u32 next_index;
- u32 session_index;
-} snat_out2in_trace_t;
-
-typedef struct {
- u32 next_worker_index;
- u8 do_handoff;
-} snat_out2in_worker_handoff_trace_t;
-
-/* packet trace format function */
-static u8 * format_snat_out2in_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 *);
- snat_out2in_trace_t * t = va_arg (*args, snat_out2in_trace_t *);
-
- s = format (s, "SNAT_OUT2IN: sw_if_index %d, next index %d, session index %d",
- t->sw_if_index, t->next_index, t->session_index);
- return s;
-}
-
-static u8 * format_snat_out2in_fast_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 *);
- snat_out2in_trace_t * t = va_arg (*args, snat_out2in_trace_t *);
-
- s = format (s, "SNAT_OUT2IN_FAST: sw_if_index %d, next index %d",
- t->sw_if_index, t->next_index);
- return s;
-}
-
-static u8 * format_snat_out2in_worker_handoff_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 *);
- snat_out2in_worker_handoff_trace_t * t =
- va_arg (*args, snat_out2in_worker_handoff_trace_t *);
- char * m;
-
- m = t->do_handoff ? "next worker" : "same worker";
- s = format (s, "SNAT_OUT2IN_WORKER_HANDOFF: %s %d", m, t->next_worker_index);
-
- return s;
-}
-
-vlib_node_registration_t snat_out2in_node;
-vlib_node_registration_t snat_out2in_fast_node;
-vlib_node_registration_t snat_out2in_worker_handoff_node;
-vlib_node_registration_t snat_det_out2in_node;
-
-#define foreach_snat_out2in_error \
-_(UNSUPPORTED_PROTOCOL, "Unsupported protocol") \
-_(OUT2IN_PACKETS, "Good out2in packets processed") \
-_(BAD_ICMP_TYPE, "unsupported ICMP type") \
-_(NO_TRANSLATION, "No translation")
-
-typedef enum {
-#define _(sym,str) SNAT_OUT2IN_ERROR_##sym,
- foreach_snat_out2in_error
-#undef _
- SNAT_OUT2IN_N_ERROR,
-} snat_out2in_error_t;
-
-static char * snat_out2in_error_strings[] = {
-#define _(sym,string) string,
- foreach_snat_out2in_error
-#undef _
-};
-
-typedef enum {
- SNAT_OUT2IN_NEXT_DROP,
- SNAT_OUT2IN_NEXT_LOOKUP,
- SNAT_OUT2IN_NEXT_ICMP_ERROR,
- SNAT_OUT2IN_N_NEXT,
-} snat_out2in_next_t;
-
-/**
- * @brief Create session for static mapping.
- *
- * Create NAT session initiated by host from external network with static
- * mapping.
- *
- * @param sm SNAT main.
- * @param b0 Vlib buffer.
- * @param in2out In2out SNAT session key.
- * @param out2in Out2in SNAT session key.
- * @param node Vlib node.
- *
- * @returns SNAT session if successfully created otherwise 0.
- */
-static inline snat_session_t *
-create_session_for_static_mapping (snat_main_t *sm,
- vlib_buffer_t *b0,
- snat_session_key_t in2out,
- snat_session_key_t out2in,
- vlib_node_runtime_t * node,
- u32 thread_index)
-{
- snat_user_t *u;
- snat_user_key_t user_key;
- snat_session_t *s;
- clib_bihash_kv_8_8_t kv0, value0;
- dlist_elt_t * per_user_translation_list_elt;
- dlist_elt_t * per_user_list_head_elt;
- ip4_header_t *ip0;
-
- ip0 = vlib_buffer_get_current (b0);
-
- user_key.addr = in2out.addr;
- user_key.fib_index = in2out.fib_index;
- kv0.key = user_key.as_u64;
-
- /* Ever heard of the "user" = inside ip4 address before? */
- if (clib_bihash_search_8_8 (&sm->user_hash, &kv0, &value0))
- {
- /* no, make a new one */
- pool_get (sm->per_thread_data[thread_index].users, u);
- memset (u, 0, sizeof (*u));
- u->addr = in2out.addr;
- u->fib_index = in2out.fib_index;
-
- pool_get (sm->per_thread_data[thread_index].list_pool,
- per_user_list_head_elt);
-
- u->sessions_per_user_list_head_index = per_user_list_head_elt -
- sm->per_thread_data[thread_index].list_pool;
-
- clib_dlist_init (sm->per_thread_data[thread_index].list_pool,
- u->sessions_per_user_list_head_index);
-
- kv0.value = u - sm->per_thread_data[thread_index].users;
-
- /* add user */
- clib_bihash_add_del_8_8 (&sm->user_hash, &kv0, 1 /* is_add */);
-
- /* add non-traslated packets worker lookup */
- kv0.value = thread_index;
- clib_bihash_add_del_8_8 (&sm->worker_by_in, &kv0, 1);
- }
- else
- {
- u = pool_elt_at_index (sm->per_thread_data[thread_index].users,
- value0.value);
- }
-
- pool_get (sm->per_thread_data[thread_index].sessions, s);
- memset (s, 0, sizeof (*s));
-
- s->outside_address_index = ~0;
- s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
- s->ext_host_addr.as_u32 = ip0->dst_address.as_u32;
- u->nstaticsessions++;
-
- /* Create list elts */
- pool_get (sm->per_thread_data[thread_index].list_pool,
- per_user_translation_list_elt);
- clib_dlist_init (sm->per_thread_data[thread_index].list_pool,
- per_user_translation_list_elt -
- sm->per_thread_data[thread_index].list_pool);
-
- per_user_translation_list_elt->value =
- s - sm->per_thread_data[thread_index].sessions;
- s->per_user_index =
- per_user_translation_list_elt - sm->per_thread_data[thread_index].list_pool;
- s->per_user_list_head_index = u->sessions_per_user_list_head_index;
-
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s->per_user_list_head_index,
- per_user_translation_list_elt -
- sm->per_thread_data[thread_index].list_pool);
-
- s->in2out = in2out;
- s->out2in = out2in;
- s->in2out.protocol = out2in.protocol;
-
- /* Add to translation hashes */
- kv0.key = s->in2out.as_u64;
- kv0.value = s - sm->per_thread_data[thread_index].sessions;
- if (clib_bihash_add_del_8_8 (&sm->in2out, &kv0, 1 /* is_add */))
- clib_warning ("in2out key add failed");
-
- kv0.key = s->out2in.as_u64;
- kv0.value = s - sm->per_thread_data[thread_index].sessions;
-
- if (clib_bihash_add_del_8_8 (&sm->out2in, &kv0, 1 /* is_add */))
- clib_warning ("out2in key add failed");
-
- /* log NAT event */
- snat_ipfix_logging_nat44_ses_create(s->in2out.addr.as_u32,
- s->out2in.addr.as_u32,
- s->in2out.protocol,
- s->in2out.port,
- s->out2in.port,
- s->in2out.fib_index);
- return s;
-}
-
-static_always_inline
-snat_out2in_error_t icmp_get_key(ip4_header_t *ip0,
- snat_session_key_t *p_key0)
-{
- icmp46_header_t *icmp0;
- snat_session_key_t key0;
- icmp_echo_header_t *echo0, *inner_echo0 = 0;
- ip4_header_t *inner_ip0;
- void *l4_header = 0;
- icmp46_header_t *inner_icmp0;
-
- icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
- echo0 = (icmp_echo_header_t *)(icmp0+1);
-
- if (!icmp_is_error_message (icmp0))
- {
- key0.protocol = SNAT_PROTOCOL_ICMP;
- key0.addr = ip0->dst_address;
- key0.port = echo0->identifier;
- }
- else
- {
- inner_ip0 = (ip4_header_t *)(echo0+1);
- l4_header = ip4_next_header (inner_ip0);
- key0.protocol = ip_proto_to_snat_proto (inner_ip0->protocol);
- key0.addr = inner_ip0->src_address;
- switch (key0.protocol)
- {
- case SNAT_PROTOCOL_ICMP:
- inner_icmp0 = (icmp46_header_t*)l4_header;
- inner_echo0 = (icmp_echo_header_t *)(inner_icmp0+1);
- key0.port = inner_echo0->identifier;
- break;
- case SNAT_PROTOCOL_UDP:
- case SNAT_PROTOCOL_TCP:
- key0.port = ((tcp_udp_header_t*)l4_header)->src_port;
- break;
- default:
- return SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL;
- }
- }
- *p_key0 = key0;
- return -1; /* success */
-}
-
-/**
- * Get address and port values to be used for packet SNAT translation
- * and create session if needed
- *
- * @param[in,out] sm SNAT main
- * @param[in,out] node SNAT node runtime
- * @param[in] thread_index thread index
- * @param[in,out] b0 buffer containing packet to be translated
- * @param[out] p_proto protocol used for matching
- * @param[out] p_value address and port after NAT translation
- * @param[out] p_dont_translate if packet should not be translated
- * @param d optional parameter
- * @param e optional parameter
- */
-u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e)
-{
- ip4_header_t *ip0;
- icmp46_header_t *icmp0;
- u32 sw_if_index0;
- u32 rx_fib_index0;
- snat_session_key_t key0;
- snat_session_key_t sm0;
- snat_session_t *s0 = 0;
- u8 dont_translate = 0;
- clib_bihash_kv_8_8_t kv0, value0;
- u8 is_addr_only;
- u32 next0 = ~0;
- int err;
-
- ip0 = vlib_buffer_get_current (b0);
- icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
-
- key0.protocol = 0;
-
- err = icmp_get_key (ip0, &key0);
- if (err != -1)
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
- key0.fib_index = rx_fib_index0;
-
- kv0.key = key0.as_u64;
-
- if (clib_bihash_search_8_8 (&sm->out2in, &kv0, &value0))
- {
- /* Try to match static mapping by external address and port,
- destination address and port in packet */
- if (snat_static_mapping_match(sm, key0, &sm0, 1, &is_addr_only))
- {
- /* Don't NAT packet aimed at the intfc address */
- if (PREDICT_FALSE(is_interface_addr(sm, node, sw_if_index0,
- ip0->dst_address.as_u32)))
- {
- dont_translate = 1;
- goto out;
- }
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
-
- if (PREDICT_FALSE(icmp0->type != ICMP4_echo_reply &&
- (icmp0->type != ICMP4_echo_request || !is_addr_only)))
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
-
- /* Create session initiated by host from external network */
- s0 = create_session_for_static_mapping(sm, b0, sm0, key0,
- node, thread_index);
-
- if (!s0)
- {
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
- }
- else
- {
- if (PREDICT_FALSE(icmp0->type != ICMP4_echo_reply &&
- icmp0->type != ICMP4_echo_request &&
- !icmp_is_error_message (icmp0)))
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
-
- s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
- value0.value);
- }
-
-out:
- *p_proto = key0.protocol;
- if (s0)
- *p_value = s0->in2out;
- *p_dont_translate = dont_translate;
- if (d)
- *(snat_session_t**)d = s0;
- return next0;
-}
-
-/**
- * Get address and port values to be used for packet SNAT translation
- *
- * @param[in] sm SNAT main
- * @param[in,out] node SNAT node runtime
- * @param[in] thread_index thread index
- * @param[in,out] b0 buffer containing packet to be translated
- * @param[out] p_proto protocol used for matching
- * @param[out] p_value address and port after NAT translation
- * @param[out] p_dont_translate if packet should not be translated
- * @param d optional parameter
- * @param e optional parameter
- */
-u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e)
-{
- ip4_header_t *ip0;
- icmp46_header_t *icmp0;
- u32 sw_if_index0;
- u32 rx_fib_index0;
- snat_session_key_t key0;
- snat_session_key_t sm0;
- u8 dont_translate = 0;
- u8 is_addr_only;
- u32 next0 = ~0;
- int err;
-
- ip0 = vlib_buffer_get_current (b0);
- icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
-
- err = icmp_get_key (ip0, &key0);
- if (err != -1)
- {
- b0->error = node->errors[err];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out2;
- }
- key0.fib_index = rx_fib_index0;
-
- if (snat_static_mapping_match(sm, key0, &sm0, 1, &is_addr_only))
- {
- /* Don't NAT packet aimed at the intfc address */
- if (is_interface_addr(sm, node, sw_if_index0, ip0->dst_address.as_u32))
- {
- dont_translate = 1;
- goto out;
- }
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
-
- if (PREDICT_FALSE(icmp0->type != ICMP4_echo_reply &&
- (icmp0->type != ICMP4_echo_request || !is_addr_only) &&
- !icmp_is_error_message (icmp0)))
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
-
-out:
- *p_value = sm0;
-out2:
- *p_proto = key0.protocol;
- *p_dont_translate = dont_translate;
- return next0;
-}
-
-static inline u32 icmp_out2in (snat_main_t *sm,
- vlib_buffer_t * b0,
- ip4_header_t * ip0,
- icmp46_header_t * icmp0,
- u32 sw_if_index0,
- u32 rx_fib_index0,
- vlib_node_runtime_t * node,
- u32 next0,
- u32 thread_index,
- void *d,
- void *e)
-{
- snat_session_key_t sm0;
- u8 protocol;
- icmp_echo_header_t *echo0, *inner_echo0 = 0;
- ip4_header_t *inner_ip0 = 0;
- void *l4_header = 0;
- icmp46_header_t *inner_icmp0;
- u8 dont_translate;
- u32 new_addr0, old_addr0;
- u16 old_id0, new_id0;
- ip_csum_t sum0;
- u16 checksum0;
- u32 next0_tmp;
-
- echo0 = (icmp_echo_header_t *)(icmp0+1);
-
- next0_tmp = sm->icmp_match_out2in_cb(sm, node, thread_index, b0,
- &protocol, &sm0, &dont_translate, d, e);
- if (next0_tmp != ~0)
- next0 = next0_tmp;
- if (next0 == SNAT_OUT2IN_NEXT_DROP || dont_translate)
- goto out;
-
- sum0 = ip_incremental_checksum (0, icmp0,
- ntohs(ip0->length) - ip4_header_bytes (ip0));
- checksum0 = ~ip_csum_fold (sum0);
- if (checksum0 != 0 && checksum0 != 0xffff)
- {
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
-
- old_addr0 = ip0->dst_address.as_u32;
- new_addr0 = ip0->dst_address.as_u32 = sm0.addr.as_u32;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm0.fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
- dst_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (!icmp_is_error_message (icmp0))
- {
- new_id0 = sm0.port;
- if (PREDICT_FALSE(new_id0 != echo0->identifier))
- {
- old_id0 = echo0->identifier;
- new_id0 = sm0.port;
- echo0->identifier = new_id0;
-
- sum0 = icmp0->checksum;
- sum0 = ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
- identifier /* changed member */);
- icmp0->checksum = ip_csum_fold (sum0);
- }
- }
- else
- {
- inner_ip0 = (ip4_header_t *)(echo0+1);
- l4_header = ip4_next_header (inner_ip0);
-
- if (!ip4_header_checksum_is_valid (inner_ip0))
- {
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
-
- old_addr0 = inner_ip0->src_address.as_u32;
- inner_ip0->src_address = sm0.addr;
- new_addr0 = inner_ip0->src_address.as_u32;
-
- sum0 = icmp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
- src_address /* changed member */);
- icmp0->checksum = ip_csum_fold (sum0);
-
- switch (protocol)
- {
- case SNAT_PROTOCOL_ICMP:
- inner_icmp0 = (icmp46_header_t*)l4_header;
- inner_echo0 = (icmp_echo_header_t *)(inner_icmp0+1);
-
- old_id0 = inner_echo0->identifier;
- new_id0 = sm0.port;
- inner_echo0->identifier = new_id0;
-
- sum0 = icmp0->checksum;
- sum0 = ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
- identifier);
- icmp0->checksum = ip_csum_fold (sum0);
- break;
- case SNAT_PROTOCOL_UDP:
- case SNAT_PROTOCOL_TCP:
- old_id0 = ((tcp_udp_header_t*)l4_header)->src_port;
- new_id0 = sm0.port;
- ((tcp_udp_header_t*)l4_header)->src_port = new_id0;
-
- sum0 = icmp0->checksum;
- sum0 = ip_csum_update (sum0, old_id0, new_id0, tcp_udp_header_t,
- src_port);
- icmp0->checksum = ip_csum_fold (sum0);
- break;
- default:
- ASSERT(0);
- }
- }
-
-out:
- return next0;
-}
-
-
-static inline u32 icmp_out2in_slow_path (snat_main_t *sm,
- vlib_buffer_t * b0,
- ip4_header_t * ip0,
- icmp46_header_t * icmp0,
- u32 sw_if_index0,
- u32 rx_fib_index0,
- vlib_node_runtime_t * node,
- u32 next0, f64 now,
- u32 thread_index,
- snat_session_t ** p_s0)
-{
- next0 = icmp_out2in(sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
- next0, thread_index, p_s0, 0);
- snat_session_t * s0 = *p_s0;
- if (PREDICT_TRUE(next0 != SNAT_OUT2IN_NEXT_DROP && s0))
- {
- /* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (sm->vlib_main, b0);
- /* Per-user LRU list maintenance for dynamic translation */
- if (!snat_is_session_static (s0))
- {
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
- }
- }
- return next0;
-}
-
-static void
-snat_out2in_unknown_proto (snat_main_t *sm,
- vlib_buffer_t * b,
- ip4_header_t * ip,
- u32 rx_fib_index,
- u32 thread_index,
- f64 now,
- vlib_main_t * vm)
-{
- clib_bihash_kv_8_8_t kv, value;
- clib_bihash_kv_16_8_t s_kv, s_value;
- snat_static_mapping_t *m;
- snat_session_key_t m_key;
- u32 old_addr, new_addr;
- ip_csum_t sum;
- snat_unk_proto_ses_key_t key;
- snat_session_t * s;
- snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
- snat_user_key_t u_key;
- snat_user_t *u;
- dlist_elt_t *head, *elt;
-
- old_addr = ip->dst_address.as_u32;
-
- key.l_addr = ip->dst_address;
- key.r_addr = ip->src_address;
- key.fib_index = rx_fib_index;
- key.proto = ip->protocol;
- key.rsvd[0] = key.rsvd[1] = key.rsvd[2] = 0;
- s_kv.key[0] = key.as_u64[0];
- s_kv.key[1] = key.as_u64[1];
-
- if (!clib_bihash_search_16_8 (&sm->out2in_unk_proto, &s_kv, &s_value))
- {
- s = pool_elt_at_index (tsm->sessions, s_value.value);
- new_addr = ip->dst_address.as_u32 = s->in2out.addr.as_u32;
- }
- else
- {
- m_key.addr = ip->dst_address;
- m_key.port = 0;
- m_key.protocol = 0;
- m_key.fib_index = rx_fib_index;
- kv.key = m_key.as_u64;
- if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
- return;
-
- m = pool_elt_at_index (sm->static_mappings, value.value);
-
- new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32;
-
- u_key.addr = ip->src_address;
- u_key.fib_index = m->fib_index;
- kv.key = u_key.as_u64;
-
- /* Ever heard of the "user" = src ip4 address before? */
- if (clib_bihash_search_8_8 (&sm->user_hash, &kv, &value))
- {
- /* no, make a new one */
- pool_get (tsm->users, u);
- memset (u, 0, sizeof (*u));
- u->addr = ip->src_address;
- u->fib_index = rx_fib_index;
-
- pool_get (tsm->list_pool, head);
- u->sessions_per_user_list_head_index = head - tsm->list_pool;
-
- clib_dlist_init (tsm->list_pool,
- u->sessions_per_user_list_head_index);
-
- kv.value = u - tsm->users;
-
- /* add user */
- clib_bihash_add_del_8_8 (&sm->user_hash, &kv, 1);
- }
- else
- {
- u = pool_elt_at_index (tsm->users, value.value);
- }
-
- /* Create a new session */
- pool_get (tsm->sessions, s);
- memset (s, 0, sizeof (*s));
-
- s->ext_host_addr.as_u32 = ip->src_address.as_u32;
- s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO;
- s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
- s->outside_address_index = ~0;
- s->out2in.addr.as_u32 = old_addr;
- s->out2in.fib_index = rx_fib_index;
- s->in2out.addr.as_u32 = new_addr;
- s->in2out.fib_index = m->fib_index;
- s->in2out.port = s->out2in.port = ip->protocol;
- u->nstaticsessions++;
-
- /* Create list elts */
- pool_get (tsm->list_pool, elt);
- clib_dlist_init (tsm->list_pool, elt - tsm->list_pool);
- elt->value = s - tsm->sessions;
- s->per_user_index = elt - tsm->list_pool;
- s->per_user_list_head_index = u->sessions_per_user_list_head_index;
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
-
- /* Add to lookup tables */
- s_kv.value = s - tsm->sessions;
- if (clib_bihash_add_del_16_8 (&sm->out2in_unk_proto, &s_kv, 1))
- clib_warning ("out2in key add failed");
-
- key.l_addr = ip->dst_address;
- key.fib_index = m->fib_index;
- s_kv.key[0] = key.as_u64[0];
- s_kv.key[1] = key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->in2out_unk_proto, &s_kv, 1))
- clib_warning ("in2out key add failed");
- }
-
- /* Update IP checksum */
- sum = ip->checksum;
- sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, dst_address);
- ip->checksum = ip_csum_fold (sum);
-
- vnet_buffer(b)->sw_if_index[VLIB_TX] = s->in2out.fib_index;
-
- /* Accounting */
- s->last_heard = now;
- s->total_pkts++;
- s->total_bytes += vlib_buffer_length_in_chain (vm, b);
- /* Per-user LRU list maintenance */
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
-}
-
-static uword
-snat_out2in_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- u32 n_left_from, * from, * to_next;
- snat_out2in_next_t next_index;
- u32 pkts_processed = 0;
- snat_main_t * sm = &snat_main;
- f64 now = vlib_time_now (vm);
- u32 thread_index = vlib_get_thread_index ();
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 bi0, bi1;
- vlib_buffer_t * b0, * b1;
- u32 next0 = SNAT_OUT2IN_NEXT_LOOKUP;
- u32 next1 = SNAT_OUT2IN_NEXT_LOOKUP;
- u32 sw_if_index0, sw_if_index1;
- ip4_header_t * ip0, *ip1;
- ip_csum_t sum0, sum1;
- u32 new_addr0, old_addr0;
- u16 new_port0, old_port0;
- u32 new_addr1, old_addr1;
- u16 new_port1, old_port1;
- udp_header_t * udp0, * udp1;
- tcp_header_t * tcp0, * tcp1;
- icmp46_header_t * icmp0, * icmp1;
- snat_session_key_t key0, key1, sm0, sm1;
- u32 rx_fib_index0, rx_fib_index1;
- u32 proto0, proto1;
- snat_session_t * s0 = 0, * s1 = 0;
- clib_bihash_kv_8_8_t kv0, kv1, value0, value1;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t * p2, * p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
- }
-
- /* speculatively enqueue b0 and b1 to the current next frame */
- to_next[0] = bi0 = from[0];
- to_next[1] = bi1 = from[1];
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- vnet_buffer (b0)->snat.flags = 0;
- vnet_buffer (b1)->snat.flags = 0;
-
- ip0 = vlib_buffer_get_current (b0);
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
- icmp0 = (icmp46_header_t *) udp0;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
- sw_if_index0);
-
- if (PREDICT_FALSE(ip0->ttl == 1))
- {
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = SNAT_OUT2IN_NEXT_ICMP_ERROR;
- goto trace0;
- }
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- if (PREDICT_FALSE (proto0 == ~0))
- {
- snat_out2in_unknown_proto(sm, b0, ip0, rx_fib_index0,
- thread_index, now, vm);
- goto trace0;
- }
-
- if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
- {
- next0 = icmp_out2in_slow_path
- (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
- next0, now, thread_index, &s0);
- goto trace0;
- }
-
- key0.addr = ip0->dst_address;
- key0.port = udp0->dst_port;
- key0.protocol = proto0;
- key0.fib_index = rx_fib_index0;
-
- kv0.key = key0.as_u64;
-
- if (clib_bihash_search_8_8 (&sm->out2in, &kv0, &value0))
- {
- /* Try to match static mapping by external address and port,
- destination address and port in packet */
- if (snat_static_mapping_match(sm, key0, &sm0, 1, 0))
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- /*
- * Send DHCP packets to the ipv4 stack, or we won't
- * be able to use dhcp client on the outside interface
- */
- if (proto0 != SNAT_PROTOCOL_UDP
- || (udp0->dst_port
- != clib_host_to_net_u16(UDP_DST_PORT_dhcp_to_client)))
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto trace0;
- }
-
- /* Create session initiated by host from external network */
- s0 = create_session_for_static_mapping(sm, b0, sm0, key0, node,
- thread_index);
- if (!s0)
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto trace0;
- }
- }
- else
- s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
- value0.value);
-
- old_addr0 = ip0->dst_address.as_u32;
- ip0->dst_address = s0->in2out.addr;
- new_addr0 = ip0->dst_address.as_u32;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- old_port0 = tcp0->dst_port;
- tcp0->dst_port = s0->in2out.port;
- new_port0 = tcp0->dst_port;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
-
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- old_port0 = udp0->dst_port;
- udp0->dst_port = s0->in2out.port;
- udp0->checksum = 0;
- }
-
- /* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (vm, b0);
- /* Per-user LRU list maintenance for dynamic translation */
- if (!snat_is_session_static (s0))
- {
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
- }
- trace0:
-
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_out2in_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- t->session_index = ~0;
- if (s0)
- t->session_index = s0 - sm->per_thread_data[thread_index].sessions;
- }
-
- pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
-
-
- ip1 = vlib_buffer_get_current (b1);
- udp1 = ip4_next_header (ip1);
- tcp1 = (tcp_header_t *) udp1;
- icmp1 = (icmp46_header_t *) udp1;
-
- sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
- rx_fib_index1 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
- sw_if_index1);
-
- if (PREDICT_FALSE(ip1->ttl == 1))
- {
- vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next1 = SNAT_OUT2IN_NEXT_ICMP_ERROR;
- goto trace1;
- }
-
- proto1 = ip_proto_to_snat_proto (ip1->protocol);
-
- if (PREDICT_FALSE (proto1 == ~0))
- {
- snat_out2in_unknown_proto(sm, b1, ip1, rx_fib_index1,
- thread_index, now, vm);
- goto trace1;
- }
-
- if (PREDICT_FALSE (proto1 == SNAT_PROTOCOL_ICMP))
- {
- next1 = icmp_out2in_slow_path
- (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
- next1, now, thread_index, &s1);
- goto trace1;
- }
-
- key1.addr = ip1->dst_address;
- key1.port = udp1->dst_port;
- key1.protocol = proto1;
- key1.fib_index = rx_fib_index1;
-
- kv1.key = key1.as_u64;
-
- if (clib_bihash_search_8_8 (&sm->out2in, &kv1, &value1))
- {
- /* Try to match static mapping by external address and port,
- destination address and port in packet */
- if (snat_static_mapping_match(sm, key1, &sm1, 1, 0))
- {
- b1->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- /*
- * Send DHCP packets to the ipv4 stack, or we won't
- * be able to use dhcp client on the outside interface
- */
- if (proto1 != SNAT_PROTOCOL_UDP
- || (udp1->dst_port
- != clib_host_to_net_u16(UDP_DST_PORT_dhcp_to_client)))
- next1 = SNAT_OUT2IN_NEXT_DROP;
- goto trace1;
- }
-
- /* Create session initiated by host from external network */
- s1 = create_session_for_static_mapping(sm, b1, sm1, key1, node,
- thread_index);
- if (!s1)
- {
- b1->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- next1 = SNAT_OUT2IN_NEXT_DROP;
- goto trace1;
- }
- }
- else
- s1 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
- value1.value);
-
- old_addr1 = ip1->dst_address.as_u32;
- ip1->dst_address = s1->in2out.addr;
- new_addr1 = ip1->dst_address.as_u32;
- vnet_buffer(b1)->sw_if_index[VLIB_TX] = s1->in2out.fib_index;
-
- sum1 = ip1->checksum;
- sum1 = ip_csum_update (sum1, old_addr1, new_addr1,
- ip4_header_t,
- dst_address /* changed member */);
- ip1->checksum = ip_csum_fold (sum1);
-
- if (PREDICT_TRUE(proto1 == SNAT_PROTOCOL_TCP))
- {
- old_port1 = tcp1->dst_port;
- tcp1->dst_port = s1->in2out.port;
- new_port1 = tcp1->dst_port;
-
- sum1 = tcp1->checksum;
- sum1 = ip_csum_update (sum1, old_addr1, new_addr1,
- ip4_header_t,
- dst_address /* changed member */);
-
- sum1 = ip_csum_update (sum1, old_port1, new_port1,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp1->checksum = ip_csum_fold(sum1);
- }
- else
- {
- old_port1 = udp1->dst_port;
- udp1->dst_port = s1->in2out.port;
- udp1->checksum = 0;
- }
-
- /* Accounting */
- s1->last_heard = now;
- s1->total_pkts++;
- s1->total_bytes += vlib_buffer_length_in_chain (vm, b1);
- /* Per-user LRU list maintenance for dynamic translation */
- if (!snat_is_session_static (s1))
- {
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s1->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s1->per_user_list_head_index,
- s1->per_user_index);
- }
- trace1:
-
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b1->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_out2in_trace_t *t =
- vlib_add_trace (vm, node, b1, sizeof (*t));
- t->sw_if_index = sw_if_index1;
- t->next_index = next1;
- t->session_index = ~0;
- if (s1)
- t->session_index = s1 - sm->per_thread_data[thread_index].sessions;
- }
-
- pkts_processed += next1 != SNAT_OUT2IN_NEXT_DROP;
-
- /* verify speculative enqueues, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, bi1, next0, next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t * b0;
- u32 next0 = SNAT_OUT2IN_NEXT_LOOKUP;
- u32 sw_if_index0;
- ip4_header_t * ip0;
- ip_csum_t sum0;
- u32 new_addr0, old_addr0;
- u16 new_port0, old_port0;
- udp_header_t * udp0;
- tcp_header_t * tcp0;
- icmp46_header_t * icmp0;
- snat_session_key_t key0, sm0;
- u32 rx_fib_index0;
- u32 proto0;
- snat_session_t * s0 = 0;
- clib_bihash_kv_8_8_t kv0, value0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- vnet_buffer (b0)->snat.flags = 0;
-
- ip0 = vlib_buffer_get_current (b0);
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
- icmp0 = (icmp46_header_t *) udp0;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
- sw_if_index0);
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- if (PREDICT_FALSE (proto0 == ~0))
- {
- snat_out2in_unknown_proto(sm, b0, ip0, rx_fib_index0,
- thread_index, now, vm);
- goto trace00;
- }
-
- if (PREDICT_FALSE(ip0->ttl == 1))
- {
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = SNAT_OUT2IN_NEXT_ICMP_ERROR;
- goto trace00;
- }
-
- if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
- {
- next0 = icmp_out2in_slow_path
- (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
- next0, now, thread_index, &s0);
- goto trace00;
- }
-
- key0.addr = ip0->dst_address;
- key0.port = udp0->dst_port;
- key0.protocol = proto0;
- key0.fib_index = rx_fib_index0;
-
- kv0.key = key0.as_u64;
-
- if (clib_bihash_search_8_8 (&sm->out2in, &kv0, &value0))
- {
- /* Try to match static mapping by external address and port,
- destination address and port in packet */
- if (snat_static_mapping_match(sm, key0, &sm0, 1, 0))
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- /*
- * Send DHCP packets to the ipv4 stack, or we won't
- * be able to use dhcp client on the outside interface
- */
- if (proto0 != SNAT_PROTOCOL_UDP
- || (udp0->dst_port
- != clib_host_to_net_u16(UDP_DST_PORT_dhcp_to_client)))
-
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto trace00;
- }
-
- /* Create session initiated by host from external network */
- s0 = create_session_for_static_mapping(sm, b0, sm0, key0, node,
- thread_index);
- if (!s0)
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto trace00;
- }
- }
- else
- s0 = pool_elt_at_index (sm->per_thread_data[thread_index].sessions,
- value0.value);
-
- old_addr0 = ip0->dst_address.as_u32;
- ip0->dst_address = s0->in2out.addr;
- new_addr0 = ip0->dst_address.as_u32;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- old_port0 = tcp0->dst_port;
- tcp0->dst_port = s0->in2out.port;
- new_port0 = tcp0->dst_port;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
-
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- old_port0 = udp0->dst_port;
- udp0->dst_port = s0->in2out.port;
- udp0->checksum = 0;
- }
-
- /* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (vm, b0);
- /* Per-user LRU list maintenance for dynamic translation */
- if (!snat_is_session_static (s0))
- {
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
- }
- trace00:
-
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_out2in_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- t->session_index = ~0;
- if (s0)
- t->session_index = s0 - sm->per_thread_data[thread_index].sessions;
- }
-
- pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vlib_node_increment_counter (vm, snat_out2in_node.index,
- SNAT_OUT2IN_ERROR_OUT2IN_PACKETS,
- pkts_processed);
- return frame->n_vectors;
-}
-
-VLIB_REGISTER_NODE (snat_out2in_node) = {
- .function = snat_out2in_node_fn,
- .name = "snat-out2in",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_out2in_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_errors = ARRAY_LEN(snat_out2in_error_strings),
- .error_strings = snat_out2in_error_strings,
-
- .runtime_data_bytes = sizeof (snat_runtime_t),
-
- .n_next_nodes = SNAT_OUT2IN_N_NEXT,
-
- /* edit / add dispositions here */
- .next_nodes = {
- [SNAT_OUT2IN_NEXT_DROP] = "error-drop",
- [SNAT_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
- [SNAT_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- },
-};
-VLIB_NODE_FUNCTION_MULTIARCH (snat_out2in_node, snat_out2in_node_fn);
-
-/**************************/
-/*** deterministic mode ***/
-/**************************/
-static uword
-snat_det_out2in_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- u32 n_left_from, * from, * to_next;
- snat_out2in_next_t next_index;
- u32 pkts_processed = 0;
- snat_main_t * sm = &snat_main;
- u32 thread_index = vlib_get_thread_index ();
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 bi0, bi1;
- vlib_buffer_t * b0, * b1;
- u32 next0 = SNAT_OUT2IN_NEXT_LOOKUP;
- u32 next1 = SNAT_OUT2IN_NEXT_LOOKUP;
- u32 sw_if_index0, sw_if_index1;
- ip4_header_t * ip0, * ip1;
- ip_csum_t sum0, sum1;
- ip4_address_t new_addr0, old_addr0, new_addr1, old_addr1;
- u16 new_port0, old_port0, old_port1, new_port1;
- udp_header_t * udp0, * udp1;
- tcp_header_t * tcp0, * tcp1;
- u32 proto0, proto1;
- snat_det_out_key_t key0, key1;
- snat_det_map_t * dm0, * dm1;
- snat_det_session_t * ses0 = 0, * ses1 = 0;
- u32 rx_fib_index0, rx_fib_index1;
- icmp46_header_t * icmp0, * icmp1;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t * p2, * p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
- }
-
- /* speculatively enqueue b0 and b1 to the current next frame */
- to_next[0] = bi0 = from[0];
- to_next[1] = bi1 = from[1];
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- ip0 = vlib_buffer_get_current (b0);
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
-
- if (PREDICT_FALSE(ip0->ttl == 1))
- {
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = SNAT_OUT2IN_NEXT_ICMP_ERROR;
- goto trace0;
- }
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- if (PREDICT_FALSE(proto0 == SNAT_PROTOCOL_ICMP))
- {
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0);
- icmp0 = (icmp46_header_t *) udp0;
-
- next0 = icmp_out2in(sm, b0, ip0, icmp0, sw_if_index0,
- rx_fib_index0, node, next0, thread_index,
- &ses0, &dm0);
- goto trace0;
- }
-
- key0.ext_host_addr = ip0->src_address;
- key0.ext_host_port = tcp0->src;
- key0.out_port = tcp0->dst;
-
- dm0 = snat_det_map_by_out(sm, &ip0->dst_address);
- if (PREDICT_FALSE(!dm0))
- {
- clib_warning("unknown dst address: %U",
- format_ip4_address, &ip0->dst_address);
- next0 = SNAT_OUT2IN_NEXT_DROP;
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- goto trace0;
- }
-
- snat_det_reverse(dm0, &ip0->dst_address,
- clib_net_to_host_u16(tcp0->dst), &new_addr0);
-
- ses0 = snat_det_get_ses_by_out (dm0, &new_addr0, key0.as_u64);
- if (PREDICT_FALSE(!ses0))
- {
- clib_warning("no match src %U:%d dst %U:%d for user %U",
- format_ip4_address, &ip0->src_address,
- clib_net_to_host_u16 (tcp0->src),
- format_ip4_address, &ip0->dst_address,
- clib_net_to_host_u16 (tcp0->dst),
- format_ip4_address, &new_addr0);
- next0 = SNAT_OUT2IN_NEXT_DROP;
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- goto trace0;
- }
- new_port0 = ses0->in_port;
-
- old_addr0 = ip0->dst_address;
- ip0->dst_address = new_addr0;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm->inside_fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
- ip4_header_t,
- dst_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- if (tcp0->flags & TCP_FLAG_FIN && ses0->state == SNAT_SESSION_TCP_ESTABLISHED)
- ses0->state = SNAT_SESSION_TCP_CLOSE_WAIT;
- else if (tcp0->flags & TCP_FLAG_ACK && ses0->state == SNAT_SESSION_TCP_LAST_ACK)
- snat_det_ses_close(dm0, ses0);
-
- old_port0 = tcp0->dst;
- tcp0->dst = new_port0;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
- ip4_header_t,
- dst_address /* changed member */);
-
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- old_port0 = udp0->dst_port;
- udp0->dst_port = new_port0;
- udp0->checksum = 0;
- }
-
- trace0:
-
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_out2in_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- t->session_index = ~0;
- if (ses0)
- t->session_index = ses0 - dm0->sessions;
- }
-
- pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
-
- b1 = vlib_get_buffer (vm, bi1);
-
- ip1 = vlib_buffer_get_current (b1);
- udp1 = ip4_next_header (ip1);
- tcp1 = (tcp_header_t *) udp1;
-
- sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
-
- if (PREDICT_FALSE(ip1->ttl == 1))
- {
- vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next1 = SNAT_OUT2IN_NEXT_ICMP_ERROR;
- goto trace1;
- }
-
- proto1 = ip_proto_to_snat_proto (ip1->protocol);
-
- if (PREDICT_FALSE(proto1 == SNAT_PROTOCOL_ICMP))
- {
- rx_fib_index1 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index1);
- icmp1 = (icmp46_header_t *) udp1;
-
- next1 = icmp_out2in(sm, b1, ip1, icmp1, sw_if_index1,
- rx_fib_index1, node, next1, thread_index,
- &ses1, &dm1);
- goto trace1;
- }
-
- key1.ext_host_addr = ip1->src_address;
- key1.ext_host_port = tcp1->src;
- key1.out_port = tcp1->dst;
-
- dm1 = snat_det_map_by_out(sm, &ip1->dst_address);
- if (PREDICT_FALSE(!dm1))
- {
- clib_warning("unknown dst address: %U",
- format_ip4_address, &ip1->dst_address);
- next1 = SNAT_OUT2IN_NEXT_DROP;
- b1->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- goto trace1;
- }
-
- snat_det_reverse(dm1, &ip1->dst_address,
- clib_net_to_host_u16(tcp1->dst), &new_addr1);
-
- ses1 = snat_det_get_ses_by_out (dm1, &new_addr1, key1.as_u64);
- if (PREDICT_FALSE(!ses1))
- {
- clib_warning("no match src %U:%d dst %U:%d for user %U",
- format_ip4_address, &ip1->src_address,
- clib_net_to_host_u16 (tcp1->src),
- format_ip4_address, &ip1->dst_address,
- clib_net_to_host_u16 (tcp1->dst),
- format_ip4_address, &new_addr1);
- next1 = SNAT_OUT2IN_NEXT_DROP;
- b1->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- goto trace1;
- }
- new_port1 = ses1->in_port;
-
- old_addr1 = ip1->dst_address;
- ip1->dst_address = new_addr1;
- vnet_buffer(b1)->sw_if_index[VLIB_TX] = sm->inside_fib_index;
-
- sum1 = ip1->checksum;
- sum1 = ip_csum_update (sum1, old_addr1.as_u32, new_addr1.as_u32,
- ip4_header_t,
- dst_address /* changed member */);
- ip1->checksum = ip_csum_fold (sum1);
-
- if (PREDICT_TRUE(proto1 == SNAT_PROTOCOL_TCP))
- {
- if (tcp1->flags & TCP_FLAG_FIN && ses1->state == SNAT_SESSION_TCP_ESTABLISHED)
- ses1->state = SNAT_SESSION_TCP_CLOSE_WAIT;
- else if (tcp1->flags & TCP_FLAG_ACK && ses1->state == SNAT_SESSION_TCP_LAST_ACK)
- snat_det_ses_close(dm1, ses1);
-
- old_port1 = tcp1->dst;
- tcp1->dst = new_port1;
-
- sum1 = tcp1->checksum;
- sum1 = ip_csum_update (sum1, old_addr1.as_u32, new_addr1.as_u32,
- ip4_header_t,
- dst_address /* changed member */);
-
- sum1 = ip_csum_update (sum1, old_port1, new_port1,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp1->checksum = ip_csum_fold(sum1);
- }
- else
- {
- old_port1 = udp1->dst_port;
- udp1->dst_port = new_port1;
- udp1->checksum = 0;
- }
-
- trace1:
-
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b1->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_out2in_trace_t *t =
- vlib_add_trace (vm, node, b1, sizeof (*t));
- t->sw_if_index = sw_if_index1;
- t->next_index = next1;
- t->session_index = ~0;
- if (ses1)
- t->session_index = ses1 - dm1->sessions;
- }
-
- pkts_processed += next1 != SNAT_OUT2IN_NEXT_DROP;
-
- /* verify speculative enqueues, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, bi1, next0, next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t * b0;
- u32 next0 = SNAT_OUT2IN_NEXT_LOOKUP;
- u32 sw_if_index0;
- ip4_header_t * ip0;
- ip_csum_t sum0;
- ip4_address_t new_addr0, old_addr0;
- u16 new_port0, old_port0;
- udp_header_t * udp0;
- tcp_header_t * tcp0;
- u32 proto0;
- snat_det_out_key_t key0;
- snat_det_map_t * dm0;
- snat_det_session_t * ses0 = 0;
- u32 rx_fib_index0;
- icmp46_header_t * icmp0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- ip0 = vlib_buffer_get_current (b0);
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
-
- if (PREDICT_FALSE(ip0->ttl == 1))
- {
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = SNAT_OUT2IN_NEXT_ICMP_ERROR;
- goto trace00;
- }
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- if (PREDICT_FALSE(proto0 == SNAT_PROTOCOL_ICMP))
- {
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0);
- icmp0 = (icmp46_header_t *) udp0;
-
- next0 = icmp_out2in(sm, b0, ip0, icmp0, sw_if_index0,
- rx_fib_index0, node, next0, thread_index,
- &ses0, &dm0);
- goto trace00;
- }
-
- key0.ext_host_addr = ip0->src_address;
- key0.ext_host_port = tcp0->src;
- key0.out_port = tcp0->dst;
-
- dm0 = snat_det_map_by_out(sm, &ip0->dst_address);
- if (PREDICT_FALSE(!dm0))
- {
- clib_warning("unknown dst address: %U",
- format_ip4_address, &ip0->dst_address);
- next0 = SNAT_OUT2IN_NEXT_DROP;
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- goto trace00;
- }
-
- snat_det_reverse(dm0, &ip0->dst_address,
- clib_net_to_host_u16(tcp0->dst), &new_addr0);
-
- ses0 = snat_det_get_ses_by_out (dm0, &new_addr0, key0.as_u64);
- if (PREDICT_FALSE(!ses0))
- {
- clib_warning("no match src %U:%d dst %U:%d for user %U",
- format_ip4_address, &ip0->src_address,
- clib_net_to_host_u16 (tcp0->src),
- format_ip4_address, &ip0->dst_address,
- clib_net_to_host_u16 (tcp0->dst),
- format_ip4_address, &new_addr0);
- next0 = SNAT_OUT2IN_NEXT_DROP;
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- goto trace00;
- }
- new_port0 = ses0->in_port;
-
- old_addr0 = ip0->dst_address;
- ip0->dst_address = new_addr0;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm->inside_fib_index;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
- ip4_header_t,
- dst_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- if (tcp0->flags & TCP_FLAG_FIN && ses0->state == SNAT_SESSION_TCP_ESTABLISHED)
- ses0->state = SNAT_SESSION_TCP_CLOSE_WAIT;
- else if (tcp0->flags & TCP_FLAG_ACK && ses0->state == SNAT_SESSION_TCP_LAST_ACK)
- snat_det_ses_close(dm0, ses0);
-
- old_port0 = tcp0->dst;
- tcp0->dst = new_port0;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0.as_u32, new_addr0.as_u32,
- ip4_header_t,
- dst_address /* changed member */);
-
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- old_port0 = udp0->dst_port;
- udp0->dst_port = new_port0;
- udp0->checksum = 0;
- }
-
- trace00:
-
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_out2in_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- t->session_index = ~0;
- if (ses0)
- t->session_index = ses0 - dm0->sessions;
- }
-
- pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vlib_node_increment_counter (vm, snat_det_out2in_node.index,
- SNAT_OUT2IN_ERROR_OUT2IN_PACKETS,
- pkts_processed);
- return frame->n_vectors;
-}
-
-VLIB_REGISTER_NODE (snat_det_out2in_node) = {
- .function = snat_det_out2in_node_fn,
- .name = "snat-det-out2in",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_out2in_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_errors = ARRAY_LEN(snat_out2in_error_strings),
- .error_strings = snat_out2in_error_strings,
-
- .runtime_data_bytes = sizeof (snat_runtime_t),
-
- .n_next_nodes = SNAT_OUT2IN_N_NEXT,
-
- /* edit / add dispositions here */
- .next_nodes = {
- [SNAT_OUT2IN_NEXT_DROP] = "error-drop",
- [SNAT_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
- [SNAT_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- },
-};
-VLIB_NODE_FUNCTION_MULTIARCH (snat_det_out2in_node, snat_det_out2in_node_fn);
-
-/**
- * Get address and port values to be used for packet SNAT translation
- * and create session if needed
- *
- * @param[in,out] sm SNAT main
- * @param[in,out] node SNAT node runtime
- * @param[in] thread_index thread index
- * @param[in,out] b0 buffer containing packet to be translated
- * @param[out] p_proto protocol used for matching
- * @param[out] p_value address and port after NAT translation
- * @param[out] p_dont_translate if packet should not be translated
- * @param d optional parameter
- * @param e optional parameter
- */
-u32 icmp_match_out2in_det(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e)
-{
- ip4_header_t *ip0;
- icmp46_header_t *icmp0;
- u32 sw_if_index0;
- u8 protocol;
- snat_det_out_key_t key0;
- u8 dont_translate = 0;
- u32 next0 = ~0;
- icmp_echo_header_t *echo0, *inner_echo0 = 0;
- ip4_header_t *inner_ip0;
- void *l4_header = 0;
- icmp46_header_t *inner_icmp0;
- snat_det_map_t * dm0 = 0;
- ip4_address_t new_addr0 = {{0}};
- snat_det_session_t * ses0 = 0;
- ip4_address_t out_addr;
-
- ip0 = vlib_buffer_get_current (b0);
- icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
- echo0 = (icmp_echo_header_t *)(icmp0+1);
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
-
- if (!icmp_is_error_message (icmp0))
- {
- protocol = SNAT_PROTOCOL_ICMP;
- key0.ext_host_addr = ip0->src_address;
- key0.ext_host_port = 0;
- key0.out_port = echo0->identifier;
- out_addr = ip0->dst_address;
- }
- else
- {
- inner_ip0 = (ip4_header_t *)(echo0+1);
- l4_header = ip4_next_header (inner_ip0);
- protocol = ip_proto_to_snat_proto (inner_ip0->protocol);
- key0.ext_host_addr = inner_ip0->dst_address;
- out_addr = inner_ip0->src_address;
- switch (protocol)
- {
- case SNAT_PROTOCOL_ICMP:
- inner_icmp0 = (icmp46_header_t*)l4_header;
- inner_echo0 = (icmp_echo_header_t *)(inner_icmp0+1);
- key0.ext_host_port = 0;
- key0.out_port = inner_echo0->identifier;
- break;
- case SNAT_PROTOCOL_UDP:
- case SNAT_PROTOCOL_TCP:
- key0.ext_host_port = ((tcp_udp_header_t*)l4_header)->dst_port;
- key0.out_port = ((tcp_udp_header_t*)l4_header)->src_port;
- break;
- default:
- b0->error = node->errors[SNAT_OUT2IN_ERROR_UNSUPPORTED_PROTOCOL];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
- }
-
- dm0 = snat_det_map_by_out(sm, &out_addr);
- if (PREDICT_FALSE(!dm0))
- {
- /* Don't NAT packet aimed at the intfc address */
- if (PREDICT_FALSE(is_interface_addr(sm, node, sw_if_index0,
- ip0->dst_address.as_u32)))
- {
- dont_translate = 1;
- goto out;
- }
- clib_warning("unknown dst address: %U",
- format_ip4_address, &ip0->dst_address);
- goto out;
- }
-
- snat_det_reverse(dm0, &ip0->dst_address,
- clib_net_to_host_u16(key0.out_port), &new_addr0);
-
- ses0 = snat_det_get_ses_by_out (dm0, &new_addr0, key0.as_u64);
- if (PREDICT_FALSE(!ses0))
- {
- /* Don't NAT packet aimed at the intfc address */
- if (PREDICT_FALSE(is_interface_addr(sm, node, sw_if_index0,
- ip0->dst_address.as_u32)))
- {
- dont_translate = 1;
- goto out;
- }
- clib_warning("no match src %U:%d dst %U:%d for user %U",
- format_ip4_address, &key0.ext_host_addr,
- clib_net_to_host_u16 (key0.ext_host_port),
- format_ip4_address, &out_addr,
- clib_net_to_host_u16 (key0.out_port),
- format_ip4_address, &new_addr0);
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
-
- if (PREDICT_FALSE(icmp0->type != ICMP4_echo_reply &&
- !icmp_is_error_message (icmp0)))
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_BAD_ICMP_TYPE];
- next0 = SNAT_OUT2IN_NEXT_DROP;
- goto out;
- }
-
- goto out;
-
-out:
- *p_proto = protocol;
- if (ses0)
- {
- p_value->addr = new_addr0;
- p_value->fib_index = sm->inside_fib_index;
- p_value->port = ses0->in_port;
- }
- *p_dont_translate = dont_translate;
- if (d)
- *(snat_det_session_t**)d = ses0;
- if (e)
- *(snat_det_map_t**)e = dm0;
- return next0;
-}
-
-/**********************/
-/*** worker handoff ***/
-/**********************/
-static uword
-snat_out2in_worker_handoff_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- snat_main_t *sm = &snat_main;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- u32 n_left_from, *from, *to_next = 0;
- static __thread vlib_frame_queue_elt_t **handoff_queue_elt_by_worker_index;
- static __thread vlib_frame_queue_t **congested_handoff_queue_by_worker_index
- = 0;
- vlib_frame_queue_elt_t *hf = 0;
- vlib_frame_t *f = 0;
- int i;
- u32 n_left_to_next_worker = 0, *to_next_worker = 0;
- u32 next_worker_index = 0;
- u32 current_worker_index = ~0;
- u32 thread_index = vlib_get_thread_index ();
-
- ASSERT (vec_len (sm->workers));
-
- if (PREDICT_FALSE (handoff_queue_elt_by_worker_index == 0))
- {
- vec_validate (handoff_queue_elt_by_worker_index, tm->n_vlib_mains - 1);
-
- vec_validate_init_empty (congested_handoff_queue_by_worker_index,
- sm->first_worker_index + sm->num_workers - 1,
- (vlib_frame_queue_t *) (~0));
- }
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
-
- while (n_left_from > 0)
- {
- u32 bi0;
- vlib_buffer_t *b0;
- u32 sw_if_index0;
- u32 rx_fib_index0;
- ip4_header_t * ip0;
- u8 do_handoff;
-
- bi0 = from[0];
- from += 1;
- n_left_from -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0);
-
- ip0 = vlib_buffer_get_current (b0);
-
- next_worker_index = sm->worker_out2in_cb(ip0, rx_fib_index0);
-
- if (PREDICT_FALSE (next_worker_index != thread_index))
- {
- do_handoff = 1;
-
- if (next_worker_index != current_worker_index)
- {
- if (hf)
- hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker;
-
- hf = vlib_get_worker_handoff_queue_elt (sm->fq_out2in_index,
- next_worker_index,
- handoff_queue_elt_by_worker_index);
-
- n_left_to_next_worker = VLIB_FRAME_SIZE - hf->n_vectors;
- to_next_worker = &hf->buffer_index[hf->n_vectors];
- current_worker_index = next_worker_index;
- }
-
- /* enqueue to correct worker thread */
- to_next_worker[0] = bi0;
- to_next_worker++;
- n_left_to_next_worker--;
-
- if (n_left_to_next_worker == 0)
- {
- hf->n_vectors = VLIB_FRAME_SIZE;
- vlib_put_frame_queue_elt (hf);
- current_worker_index = ~0;
- handoff_queue_elt_by_worker_index[next_worker_index] = 0;
- hf = 0;
- }
- }
- else
- {
- do_handoff = 0;
- /* if this is 1st frame */
- if (!f)
- {
- f = vlib_get_frame_to_node (vm, sm->out2in_node_index);
- to_next = vlib_frame_vector_args (f);
- }
-
- to_next[0] = bi0;
- to_next += 1;
- f->n_vectors++;
- }
-
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_out2in_worker_handoff_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->next_worker_index = next_worker_index;
- t->do_handoff = do_handoff;
- }
- }
-
- if (f)
- vlib_put_frame_to_node (vm, sm->out2in_node_index, f);
-
- if (hf)
- hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker;
-
- /* Ship frames to the worker nodes */
- for (i = 0; i < vec_len (handoff_queue_elt_by_worker_index); i++)
- {
- if (handoff_queue_elt_by_worker_index[i])
- {
- hf = handoff_queue_elt_by_worker_index[i];
- /*
- * It works better to let the handoff node
- * rate-adapt, always ship the handoff queue element.
- */
- if (1 || hf->n_vectors == hf->last_n_vectors)
- {
- vlib_put_frame_queue_elt (hf);
- handoff_queue_elt_by_worker_index[i] = 0;
- }
- else
- hf->last_n_vectors = hf->n_vectors;
- }
- congested_handoff_queue_by_worker_index[i] =
- (vlib_frame_queue_t *) (~0);
- }
- hf = 0;
- current_worker_index = ~0;
- return frame->n_vectors;
-}
-
-VLIB_REGISTER_NODE (snat_out2in_worker_handoff_node) = {
- .function = snat_out2in_worker_handoff_fn,
- .name = "snat-out2in-worker-handoff",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_out2in_worker_handoff_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_next_nodes = 1,
-
- .next_nodes = {
- [0] = "error-drop",
- },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (snat_out2in_worker_handoff_node, snat_out2in_worker_handoff_fn);
-
-static uword
-snat_out2in_fast_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
-{
- u32 n_left_from, * from, * to_next;
- snat_out2in_next_t next_index;
- u32 pkts_processed = 0;
- snat_main_t * sm = &snat_main;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0;
- vlib_buffer_t * b0;
- u32 next0 = SNAT_OUT2IN_NEXT_DROP;
- u32 sw_if_index0;
- ip4_header_t * ip0;
- ip_csum_t sum0;
- u32 new_addr0, old_addr0;
- u16 new_port0, old_port0;
- udp_header_t * udp0;
- tcp_header_t * tcp0;
- icmp46_header_t * icmp0;
- snat_session_key_t key0, sm0;
- u32 proto0;
- u32 rx_fib_index0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- ip0 = vlib_buffer_get_current (b0);
- udp0 = ip4_next_header (ip0);
- tcp0 = (tcp_header_t *) udp0;
- icmp0 = (icmp46_header_t *) udp0;
-
- sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0);
-
- vnet_feature_next (sw_if_index0, &next0, b0);
-
- if (PREDICT_FALSE(ip0->ttl == 1))
- {
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
- ICMP4_time_exceeded_ttl_exceeded_in_transit,
- 0);
- next0 = SNAT_OUT2IN_NEXT_ICMP_ERROR;
- goto trace00;
- }
-
- proto0 = ip_proto_to_snat_proto (ip0->protocol);
-
- if (PREDICT_FALSE (proto0 == ~0))
- goto trace00;
-
- if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
- {
- next0 = icmp_out2in(sm, b0, ip0, icmp0, sw_if_index0,
- rx_fib_index0, node, next0, ~0, 0, 0);
- goto trace00;
- }
-
- key0.addr = ip0->dst_address;
- key0.port = udp0->dst_port;
- key0.fib_index = rx_fib_index0;
-
- if (snat_static_mapping_match(sm, key0, &sm0, 1, 0))
- {
- b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
- goto trace00;
- }
-
- new_addr0 = sm0.addr.as_u32;
- new_port0 = sm0.port;
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm0.fib_index;
- old_addr0 = ip0->dst_address.as_u32;
- ip0->dst_address.as_u32 = new_addr0;
-
- sum0 = ip0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
- ip0->checksum = ip_csum_fold (sum0);
-
- if (PREDICT_FALSE(new_port0 != udp0->dst_port))
- {
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- old_port0 = tcp0->dst_port;
- tcp0->dst_port = new_port0;
-
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
-
- sum0 = ip_csum_update (sum0, old_port0, new_port0,
- ip4_header_t /* cheat */,
- length /* changed member */);
- tcp0->checksum = ip_csum_fold(sum0);
- }
- else
- {
- old_port0 = udp0->dst_port;
- udp0->dst_port = new_port0;
- udp0->checksum = 0;
- }
- }
- else
- {
- if (PREDICT_TRUE(proto0 == SNAT_PROTOCOL_TCP))
- {
- sum0 = tcp0->checksum;
- sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
- ip4_header_t,
- dst_address /* changed member */);
-
- tcp0->checksum = ip_csum_fold(sum0);
- }
- }
-
- trace00:
-
- if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- snat_out2in_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- }
-
- pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
-
- /* verify speculative enqueue, maybe switch current next frame */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vlib_node_increment_counter (vm, snat_out2in_fast_node.index,
- SNAT_OUT2IN_ERROR_OUT2IN_PACKETS,
- pkts_processed);
- return frame->n_vectors;
-}
-
-VLIB_REGISTER_NODE (snat_out2in_fast_node) = {
- .function = snat_out2in_fast_node_fn,
- .name = "snat-out2in-fast",
- .vector_size = sizeof (u32),
- .format_trace = format_snat_out2in_fast_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
-
- .n_errors = ARRAY_LEN(snat_out2in_error_strings),
- .error_strings = snat_out2in_error_strings,
-
- .runtime_data_bytes = sizeof (snat_runtime_t),
-
- .n_next_nodes = SNAT_OUT2IN_N_NEXT,
-
- /* edit / add dispositions here */
- .next_nodes = {
- [SNAT_OUT2IN_NEXT_LOOKUP] = "ip4-lookup",
- [SNAT_OUT2IN_NEXT_DROP] = "error-drop",
- [SNAT_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- },
-};
-VLIB_NODE_FUNCTION_MULTIARCH (snat_out2in_fast_node, snat_out2in_fast_node_fn);
diff --git a/src/plugins/snat/snat.api b/src/plugins/snat/snat.api
deleted file mode 100644
index 3c493ddae5b..00000000000
--- a/src/plugins/snat/snat.api
+++ /dev/null
@@ -1,897 +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.
- */
-/**
- * @file snat.api
- * @brief VPP control-plane API messages.
- *
- * This file defines VPP control-plane API messages which are generally
- * called through a shared memory interface.
- */
-
-/** \brief Add/del S-NAT address range
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param first_ip_address - first IP address
- @param last_ip_address - last IP address
- @param vrf_id - VRF id of tenant, ~0 means independent of VRF
- @param is_add - 1 if add, 0 if delete
-*/
-autoreply define snat_add_address_range {
- u32 client_index;
- u32 context;
- u8 is_ip4;
- u8 first_ip_address[16];
- u8 last_ip_address[16];
- u32 vrf_id;
- u8 is_add;
-};
-
-/** \brief Dump S-NAT addresses
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_address_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief S-NAT address details response
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param ip_address - IP address
- @param vrf_id - VRF id of tenant, ~0 means independent of VRF
-*/
-define snat_address_details {
- u32 context;
- u8 is_ip4;
- u8 ip_address[16];
- u32 vrf_id;
-};
-
-/** \brief Enable/disable S-NAT feature on the interface
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_add - 1 if add, 0 if delete
- @param is_inside - 1 if inside, 0 if outside
- @param sw_if_index - software index of the interface
-*/
-autoreply define snat_interface_add_del_feature {
- u32 client_index;
- u32 context;
- u8 is_add;
- u8 is_inside;
- u32 sw_if_index;
-};
-
-/** \brief Dump interfaces with S-NAT feature
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_interface_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief S-NAT interface details response
- @param context - sender context, to match reply w/ request
- @param is_inside - 1 if inside, 0 if outside
- @param sw_if_index - software index of the interface
-*/
-define snat_interface_details {
- u32 context;
- u8 is_inside;
- u32 sw_if_index;
-};
-
-/** \brief Enable/disbale S-NAT as an interface output feature (postrouting
- in2out translation)
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_add - 1 if add, 0 if delete
- @param is_inside - 1 if inside, 0 if outside
- @param sw_if_index - software index of the interface
-*/
-autoreply define snat_interface_add_del_output_feature {
- u32 client_index;
- u32 context;
- u8 is_add;
- u8 is_inside;
- u32 sw_if_index;
-};
-
-/** \brief Dump interfaces with S-NAT output feature
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_interface_output_feature_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief S-NAT interface with output feature details response
- @param context - sender context, to match reply w/ request
- @param is_inside - 1 if inside, 0 if outside
- @param sw_if_index - software index of the interface
-*/
-define snat_interface_output_feature_details {
- u32 context;
- u8 is_inside;
- u32 sw_if_index;
-};
-
-/** \brief Add/delete S-NAT static mapping
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_add - 1 if add, 0 if delete
- @param is_ip4 - 1 if address type is IPv4
- @param addr_only - 1 if address only mapping
- @param local_ip_address - local IP address
- @param external_ip_address - external IP address
- @param protocol - IP protocol
- @param local_port - local port number
- @param external_port - external port number
- @param external_sw_if_index - external interface (if set
- external_ip_address is ignored, ~0 means not
- used)
- @param vfr_id - VRF ID
-*/
-autoreply define snat_add_static_mapping {
- u32 client_index;
- u32 context;
- u8 is_add;
- u8 is_ip4;
- u8 addr_only;
- u8 local_ip_address[16];
- u8 external_ip_address[16];
- u8 protocol;
- u16 local_port;
- u16 external_port;
- u32 external_sw_if_index;
- u32 vrf_id;
-};
-
-/** \brief Dump S-NAT static mappings
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_static_mapping_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief S-NAT static mapping details response
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param addr_only - 1 if address only mapping
- @param local_ip_address - local IP address
- @param external_ip_address - external IP address
- @param protocol - IP protocol
- @param local_port - local port number
- @param external_port - external port number
- @param external_sw_if_index - external interface
- @param vfr_id - VRF ID
-*/
-define snat_static_mapping_details {
- u32 context;
- u8 is_ip4;
- u8 addr_only;
- u8 local_ip_address[16];
- u8 external_ip_address[16];
- u8 protocol;
- u16 local_port;
- u16 external_port;
- u32 external_sw_if_index;
- u32 vrf_id;
-};
-
-/** \brief Control ping from client to api server request
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_control_ping
-{
- u32 client_index;
- u32 context;
-};
-
-/** \brief Control ping from the client to the server response
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param retval - return code for the request
- @param vpe_pid - the pid of the vpe, returned by the server
-*/
-define snat_control_ping_reply
-{
- u32 context;
- i32 retval;
- u32 client_index;
- u32 vpe_pid;
-};
-
-/** \brief Show S-NAT plugin startup config
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_show_config
-{
- u32 client_index;
- u32 context;
-};
-
-/** \brief Show S-NAT plugin startup config reply
- @param context - sender context, to match reply w/ request
- @param retval - return code for the request
- @param static_mapping_only - if 1 dynamic translations disabled
- @param static_mapping_connection_tracking - if 1 create session data
- @param deterministic - if 1 deterministic mapping
- @param translation_buckets - number of translation hash buckets
- @param translation_memory_size - translation hash memory size
- @param user_buckets - number of user hash buckets
- @param user_memory_size - user hash memory size
- @param max_translations_per_user - maximum number of translations per user
- @param outside_vrf_id - outside VRF id
- @param inside_vrf_id - default inside VRF id
-*/
-define snat_show_config_reply
-{
- u32 context;
- i32 retval;
- u8 static_mapping_only;
- u8 static_mapping_connection_tracking;
- u8 deterministic;
- u32 translation_buckets;
- u32 translation_memory_size;
- u32 user_buckets;
- u32 user_memory_size;
- u32 max_translations_per_user;
- u32 outside_vrf_id;
- u32 inside_vrf_id;
-};
-
-/** \brief Set S-NAT workers
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param worker_mask - S-NAT workers mask
-*/
-autoreply define snat_set_workers {
- u32 client_index;
- u32 context;
- u64 worker_mask;
-};
-
-/** \brief Dump S-NAT workers
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_worker_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief S-NAT workers details response
- @param context - sender context, to match reply w/ request
- @param worker_index - worker index
- @param lcore_id - lcore ID
- @param name - worker name
-*/
-define snat_worker_details {
- u32 context;
- u32 worker_index;
- u32 lcore_id;
- u8 name[64];
-};
-
-/** \brief Add/delete S-NAT pool address from specific interfce
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_add - 1 if add, 0 if delete
- @param sw_if_index - software index of the interface
-*/
-autoreply define snat_add_del_interface_addr {
- u32 client_index;
- u32 context;
- u8 is_add;
- u8 is_inside;
- u32 sw_if_index;
-};
-
-/** \brief Dump S-NAT pool addresses interfaces
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_interface_addr_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief S-NAT pool addresses interfaces details response
- @param context - sender context, to match reply w/ request
- @param sw_if_index - software index of the interface
-*/
-define snat_interface_addr_details {
- u32 context;
- u32 sw_if_index;
-};
-
-/** \brief Enable/disable S-NAT IPFIX logging
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param domain_id - observation domain ID
- @param src_port - source port number
- @param enable - 1 if enable, 0 if disable
-*/
-autoreply define snat_ipfix_enable_disable {
- u32 client_index;
- u32 context;
- u32 domain_id;
- u16 src_port;
- u8 enable;
-};
-
-/** \brief Dump S-NAT users
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_user_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief S-NAT users response
- @param context - sender context, to match reply w/ request
- @vrf_id - VRF ID
- @param is_ip4 - 1 if address type is IPv4
- @param ip_adress - IP address
- @param nsessions - number of dynamic sessions
- @param nstaticsessions - number of static sessions
-*/
-define snat_user_details {
- u32 context;
- u32 vrf_id;
- u8 is_ip4;
- u8 ip_address[16];
- u32 nsessions;
- u32 nstaticsessions;
-};
-
-/** \brief S-NAT user's sessions
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param user_ip - IP address of the user to dump
- @param vrf_id - VRF_ID
-*/
-define snat_user_session_dump {
- u32 client_index;
- u32 context;
- u8 is_ip4;
- u8 ip_address[16];
- u32 vrf_id;
-};
-
-/** \brief S-NAT user's sessions response
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param outside_ip_address - outside IP address
- @param outside_port - outside port
- @param inside_ip_address - inside IP address
- @param inside_port - inside port
- @param protocol - protocol
- @param is_static - 1 if session is static
- @param last_heard - last heard timer
- @param total_bytes - count of bytes sent through session
- @param total_pkts - count of pakets sent through session
-*/
-define snat_user_session_details {
- u32 context;
- u8 is_ip4;
- u8 outside_ip_address[16];
- u16 outside_port;
- u8 inside_ip_address[16];
- u16 inside_port;
- u16 protocol;
- u8 is_static;
- u64 last_heard;
- u64 total_bytes;
- u32 total_pkts;
-};
-
-/** \brief Add/delete S-NAT deterministic mapping
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_add - 1 if add, 0 if delete
- @param is_ip4 - 1 if address type is IPv4
- @param in_addr - inside IP address
- @param in_plen - inside IP address prefix length
- @param out_addr - outside IP address
- @param out_addr - outside IP address prefix length
-*/
-autoreply define snat_add_det_map {
- u32 client_index;
- u32 context;
- u8 is_add;
- u8 is_ip4;
- u8 addr_only;
- u8 in_addr[16];
- u8 in_plen;
- u8 out_addr[16];
- u8 out_plen;
-};
-
-/** \brief Get outside address and port range from inside address
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param in_addr - inside IP address
-*/
-define snat_det_forward {
- u32 client_index;
- u32 context;
- u8 is_ip4;
- u8 in_addr[16];
-};
-
-/** \brief Get outside address and port range from inside address
- @param context - sender context, to match reply w/ request
- @param retval - return code
- @param out_port_lo - outside port range start
- @param out_port_hi - outside port range end
- @param is_ip4 - 1 if address type is IPv4
- @param out_addr - outside IP address
-*/
-define snat_det_forward_reply {
- u32 context;
- i32 retval;
- u16 out_port_lo;
- u16 out_port_hi;
- u8 is_ip4;
- u8 out_addr[16];
-};
-
-/** \brief Get inside address from outside address and port
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param out_port - outside port
- @param is_ip4 - 1 if address type is IPv4
- @param out_addr - outside IP address
-*/
-define snat_det_reverse {
- u32 client_index;
- u32 context;
- u16 out_port;
- u8 is_ip4;
- u8 out_addr[16];
-};
-
-/** \brief Get inside address from outside address and port reply
- @param context - sender context, to match reply w/ request
- @param retval - return code
- @param is_ip4 - 1 if address type is IPv4
- @param in_addr - inside IP address
-*/
-define snat_det_reverse_reply {
- u32 context;
- i32 retval;
- u8 is_ip4;
- u8 in_addr[16];
-};
-
-/** \brief Dump S-NAT deterministic mappings
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_det_map_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief S-NAT users response
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param in_addr - inside IP address
- @param in_plen - inside IP address prefix length
- @param out_addr - outside IP address
- @param out_plen - outside IP address prefix length
- @param sharing_ratio - outside to inside address sharing ratio
- @param ports_per_host - number of ports available to a host
- @param ses_num - number of sessions belonging to this mapping
-*/
-define snat_det_map_details {
- u32 context;
- u8 is_ip4;
- u8 in_addr[16];
- u8 in_plen;
- u8 out_addr[16];
- u8 out_plen;
- u32 sharing_ratio;
- u16 ports_per_host;
- u32 ses_num;
-};
-
-/** \brief Set values of timeouts for deterministic NAT (seconds, 0 = default)
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param udp - UDP timeout (default 300sec)
- @param tcp_established - TCP established timeout (default 7440sec)
- @param tcp_transitory - TCP transitory timeout (default 240sec)
- @param icmp - ICMP timeout (default 60sec)
-*/
-autoreply define snat_det_set_timeouts {
- u32 client_index;
- u32 context;
- u32 udp;
- u32 tcp_established;
- u32 tcp_transitory;
- u32 icmp;
-};
-
-/** \brief Get values of timeouts for deterministic NAT (seconds)
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define snat_det_get_timeouts {
- u32 client_index;
- u32 context;
-};
-
-/** \brief Get values of timeouts for deterministic NAT reply
- @param context - sender context, to match reply w/ request
- @param retval - return code
- @param udp - UDP timeout (default 300sec)
- @param tcp_established - TCP established timeout (default 7440sec)
- @param tcp_transitory - TCP transitory timeout (default 240sec)
- @param icmp - ICMP timeout (default 60sec)
-*/
-define snat_det_get_timeouts_reply {
- u32 context;
- i32 retval;
- u32 udp;
- u32 tcp_established;
- u32 tcp_transitory;
- u32 icmp;
-};
-
-/** \brief Close CGNAT session by outside address and port
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param out_addr - outside IP address
- @param out_port - outside port
- @param ext_addr - external host address
- @param ext_port - external host port
-*/
-autoreply define snat_det_close_session_out {
- u32 client_index;
- u32 context;
- u8 is_ip4;
- u8 out_addr[16];
- u16 out_port;
- u8 ext_addr[16];
- u16 ext_port;
-};
-
-/** \brief Close CGNAT session by inside address and port
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param in_addr - inside IP address
- @param in_port - inside port
- @param ext_addr - external host address
- @param ext_port - external host port
-*/
-autoreply define snat_det_close_session_in {
- u32 client_index;
- u32 context;
- u8 is_ip4;
- u8 in_addr[16];
- u16 in_port;
- u8 ext_addr[16];
- u16 ext_port;
-};
-
-/** \brief Dump S-NAT deterministic sessions
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param user_addr - address of an inside user whose sessions to dump
-*/
-define snat_det_session_dump {
- u32 client_index;
- u32 context;
- u8 is_ip4;
- u8 user_addr[16];
-};
-
-/** \brief S-NAT deterministic sessions reply
- @param context - sender context, to match reply w/ request
- @param is_ip4 - 1 if address type is IPv4
- @param in_port - inside port
- @param ext_addr - external host address
- @param ext_port - external host port
- @param out_port - outside NAT port
- @param state - session state
- @param expire - session expiration timestamp
-*/
-define snat_det_session_details {
- u32 client_index;
- u32 context;
- u8 is_ip4;
- u16 in_port;
- u8 ext_addr[16];
- u16 ext_port;
- u16 out_port;
- u8 state;
- u32 expire;
-};
-
-/** \brief Add/delete address range to NAT64 pool
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param start_addr - start address of the range
- @param end_addr - end address of the range
- @param vrf_id - VRF id of tenant, ~0 means independent of VRF
- @param is_add - 1 if add, 0 if delete
-*/
-autoreply define nat64_add_del_pool_addr_range {
- u32 client_index;
- u32 context;
- u8 start_addr[4];
- u8 end_addr[4];
- u32 vrf_id;
- u8 is_add;
-};
-
-/** \brief Dump NAT64 pool addresses
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define nat64_pool_addr_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief NAT64 pool address details response
- @param context - sender context, to match reply w/ request
- @param address - IPv4 address
- @param vfr_id - VRF id of tenant, ~0 means independent of VRF
-*/
-define nat64_pool_addr_details {
- u32 context;
- u8 address[4];
- u32 vrf_id;
-};
-
-/** \brief Enable/disable NAT64 feature on the interface
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param sw_if_index - index of the interface
- @param is_inside - 1 if inside, 0 if outside
- @param is_add - 1 if add, 0 if delete
-*/
-autoreply define nat64_add_del_interface {
- u32 client_index;
- u32 context;
- u32 sw_if_index;
- u8 is_inside;
- u8 is_add;
-};
-
-/** \brief Dump interfaces with NAT64 feature
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define nat64_interface_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief NAT64 interface details response
- @param context - sender context, to match reply w/ request
- @param is_inside - 1 if inside, 0 if outside
- @param sw_if_index - index of the interface
-*/
-define nat64_interface_details {
- u32 context;
- u8 is_inside;
- u32 sw_if_index;
-};
-
-/** \brief Add/delete NAT64 static BIB entry
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param i_addr - inside IPv6 address
- @param o_addr - outside IPv4 address
- @param i_port - inside port number
- @param o_port - outside port number
- @param vrf_id - VRF id of tenant
- @param proto - protocol number
- @param is_add - 1 if add, 0 if delete
-*/
- autoreply define nat64_add_del_static_bib {
- u32 client_index;
- u32 context;
- u8 i_addr[16];
- u8 o_addr[4];
- u16 i_port;
- u16 o_port;
- u32 vrf_id;
- u8 proto;
- u8 is_add;
-};
-
-/** \brief Dump NAT64 BIB
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param proto - protocol of the BIB: 255 - all BIBs
- 6 - TCP BIB
- 17 - UDP BIB
- 1/58 - ICMP BIB
- otherwise - "unknown" protocol BIB
-*/
-define nat64_bib_dump {
- u32 client_index;
- u32 context;
- u8 proto;
-};
-
-/** \brief NAT64 BIB details response
- @param context - sender context, to match reply w/ request
- @param i_addr - inside IPv6 address
- @param o_addr - outside IPv4 address
- @param i_port - inside port number
- @param o_port - outside port number
- @param vrf_id - VRF id of tenant
- @param proto - protocol number
- @param is_static - 1 if static BIB entry, 0 if dynamic
- @param ses_num - number of sessions associated with the BIB entry
-*/
-define nat64_bib_details {
- u32 context;
- u8 i_addr[16];
- u8 o_addr[4];
- u16 i_port;
- u16 o_port;
- u32 vrf_id;
- u8 proto;
- u8 is_static;
- u32 ses_num;
-};
-
-/** \brief Set values of timeouts for NAT64 (seconds, 0 = default)
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param udp - UDP timeout (default 300sec)
- @param icmp - ICMP timeout (default 60sec)
- @param tcp_trans - TCP transitory timeout (default 240sec)
- @param tcp_est - TCP established timeout (default 7440sec)
- @param tcp_incoming_syn - TCP incoming SYN timeout (default 6sec)
-*/
-autoreply define nat64_set_timeouts {
- u32 client_index;
- u32 context;
- u32 udp;
- u32 icmp;
- u32 tcp_trans;
- u32 tcp_est;
- u32 tcp_incoming_syn;
-};
-
-/** \brief Get values of timeouts for NAT64 (seconds)
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define nat64_get_timeouts {
- u32 client_index;
- u32 context;
-};
-
-/** \brief Get values of timeouts for NAT64 reply
- @param context - sender context, to match reply w/ request
- @param retval - return code
- @param udp - UDP timeout
- @param icmp - ICMP timeout
- @param tcp_trans - TCP transitory timeout
- @param tcp_est - TCP established timeout
- @param tcp_incoming_syn - TCP incoming SYN timeout
-*/
-define nat64_get_timeouts_reply {
- u32 context;
- i32 retval;
- u32 udp;
- u32 icmp;
- u32 tcp_trans;
- u32 tcp_est;
- u32 tcp_incoming_syn;
-};
-
-/** \brief Dump NAT64 session table
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param proto - protocol of the session table: 255 - all STs
- 6 - TCP ST
- 17 - UDP ST
- 1/58 - ICMP ST
- otherwise - "unknown" proto ST
-*/
-define nat64_st_dump {
- u32 client_index;
- u32 context;
- u8 proto;
-};
-
-/** \brief NAT64 session table details response
- @param context - sender context, to match reply w/ request
- @param il_addr - inside IPv6 address of the local host
- @param ol_addr - outside IPv4 address of the local host
- @param il_port - inside port number id of the local host/inside ICMP id
- @param ol_port - outside port number of the local host/outside ICMP id
- @param il_addr - inside IPv6 address of the remote host
- @param ol_addr - outside IPv4 address of the remote host
- @param l_port - port number of the remote host (not used for ICMP)
- @param vrf_id - VRF id of tenant
- @param proto - protocol number
-*/
-define nat64_st_details {
- u32 context;
- u8 il_addr[16];
- u8 ol_addr[4];
- u16 il_port;
- u16 ol_port;
- u8 ir_addr[16];
- u8 or_addr[4];
- u16 r_port;
- u32 vrf_id;
- u8 proto;
-};
-
-/** \brief Add/del NAT64 prefix
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
- @param prefix - NAT64 prefix
- @param prefix - NAT64 prefix length
- @param vrf_id - VRF id of tenant
- @param is_add - 1 if add, 0 if delete
-*/
-autoreply define nat64_add_del_prefix {
- u32 client_index;
- u32 context;
- u8 prefix[16];
- u8 prefix_len;
- u32 vrf_id;
- u8 is_add;
-};
-
-/** \brief Dump NAT64 prefix
- @param client_index - opaque cookie to identify the sender
- @param context - sender context, to match reply w/ request
-*/
-define nat64_prefix_dump {
- u32 client_index;
- u32 context;
-};
-
-/** \brief Dump NAT64 prefix details response
- @param context - sender context, to match reply w/ request
- @param prefix - NAT64 prefix
- @param prefix - NAT64 prefix length
- @param vrf_id - VRF id of tenant
-*/
-define nat64_prefix_details {
- u32 context;
- u8 prefix[16];
- u8 prefix_len;
- u32 vrf_id;
-};
diff --git a/src/plugins/snat/snat.c b/src/plugins/snat/snat.c
deleted file mode 100644
index 315cec8a65b..00000000000
--- a/src/plugins/snat/snat.c
+++ /dev/null
@@ -1,2842 +0,0 @@
-/*
- * snat.c - simple nat plugin
- *
- * 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.
- */
-
-#include <vnet/vnet.h>
-#include <vnet/ip/ip.h>
-#include <vnet/ip/ip4.h>
-#include <vnet/plugin/plugin.h>
-#include <snat/snat.h>
-#include <snat/snat_ipfix_logging.h>
-#include <snat/snat_det.h>
-#include <snat/nat64.h>
-#include <vnet/fib/fib_table.h>
-#include <vnet/fib/ip4_fib.h>
-
-#include <vpp/app/version.h>
-
-snat_main_t snat_main;
-
-
-/* Hook up input features */
-VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "snat-in2out",
- .runs_before = VNET_FEATURES ("snat-out2in"),
-};
-VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "snat-out2in",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
-};
-VNET_FEATURE_INIT (ip4_snat_det_in2out, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "snat-det-in2out",
- .runs_before = VNET_FEATURES ("snat-det-out2in"),
-};
-VNET_FEATURE_INIT (ip4_snat_det_out2in, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "snat-det-out2in",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
-};
-VNET_FEATURE_INIT (ip4_snat_in2out_worker_handoff, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "snat-in2out-worker-handoff",
- .runs_before = VNET_FEATURES ("snat-out2in-worker-handoff"),
-};
-VNET_FEATURE_INIT (ip4_snat_out2in_worker_handoff, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "snat-out2in-worker-handoff",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
-};
-VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "snat-in2out-fast",
- .runs_before = VNET_FEATURES ("snat-out2in-fast"),
-};
-VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "snat-out2in-fast",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
-};
-VNET_FEATURE_INIT (ip4_snat_hairpin_dst, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "snat-hairpin-dst",
- .runs_before = VNET_FEATURES ("ip4-lookup"),
-};
-
-/* Hook up output features */
-VNET_FEATURE_INIT (ip4_snat_in2out_output, static) = {
- .arc_name = "ip4-output",
- .node_name = "snat-in2out-output",
- .runs_before = VNET_FEATURES ("interface-output"),
-};
-VNET_FEATURE_INIT (ip4_snat_in2out_output_worker_handoff, static) = {
- .arc_name = "ip4-output",
- .node_name = "snat-in2out-output-worker-handoff",
- .runs_before = VNET_FEATURES ("interface-output"),
-};
-VNET_FEATURE_INIT (ip4_snat_hairpin_src, static) = {
- .arc_name = "ip4-output",
- .node_name = "snat-hairpin-src",
- .runs_before = VNET_FEATURES ("interface-output"),
-};
-
-
-/* *INDENT-OFF* */
-VLIB_PLUGIN_REGISTER () = {
- .version = VPP_BUILD_VER,
- .description = "Network Address Translation",
-};
-/* *INDENT-ON* */
-
-/**
- * @brief Add/del NAT address to FIB.
- *
- * Add the external NAT address to the FIB as receive entries. This ensures
- * that VPP will reply to ARP for this address and we don't need to enable
- * proxy ARP on the outside interface.
- *
- * @param addr IPv4 address.
- * @param plen address prefix length
- * @param sw_if_index Interface.
- * @param is_add If 0 delete, otherwise add.
- */
-void
-snat_add_del_addr_to_fib (ip4_address_t * addr, u8 p_len, u32 sw_if_index,
- int is_add)
-{
- fib_prefix_t prefix = {
- .fp_len = p_len,
- .fp_proto = FIB_PROTOCOL_IP4,
- .fp_addr = {
- .ip4.as_u32 = addr->as_u32,
- },
- };
- u32 fib_index = ip4_fib_table_get_index_for_sw_if_index(sw_if_index);
-
- if (is_add)
- fib_table_entry_update_one_path(fib_index,
- &prefix,
- FIB_SOURCE_PLUGIN_HI,
- (FIB_ENTRY_FLAG_CONNECTED |
- FIB_ENTRY_FLAG_LOCAL |
- FIB_ENTRY_FLAG_EXCLUSIVE),
- DPO_PROTO_IP4,
- NULL,
- sw_if_index,
- ~0,
- 1,
- NULL,
- FIB_ROUTE_PATH_FLAG_NONE);
- else
- fib_table_entry_delete(fib_index,
- &prefix,
- FIB_SOURCE_PLUGIN_HI);
-}
-
-void snat_add_address (snat_main_t *sm, ip4_address_t *addr, u32 vrf_id)
-{
- snat_address_t * ap;
- snat_interface_t *i;
-
- if (vrf_id != ~0)
- sm->vrf_mode = 1;
-
- /* Check if address already exists */
- vec_foreach (ap, sm->addresses)
- {
- if (ap->addr.as_u32 == addr->as_u32)
- return;
- }
-
- vec_add2 (sm->addresses, ap, 1);
- ap->addr = *addr;
- if (vrf_id != ~0)
- ap->fib_index =
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id);
- else
- ap->fib_index = ~0;
-#define _(N, i, n, s) \
- clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535);
- foreach_snat_protocol
-#undef _
-
- /* Add external address to FIB */
- pool_foreach (i, sm->interfaces,
- ({
- if (i->is_inside)
- continue;
-
- snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
- break;
- }));
- pool_foreach (i, sm->output_feature_interfaces,
- ({
- if (i->is_inside)
- continue;
-
- snat_add_del_addr_to_fib(addr, 32, i->sw_if_index, 1);
- break;
- }));
-}
-
-static int is_snat_address_used_in_static_mapping (snat_main_t *sm,
- ip4_address_t addr)
-{
- snat_static_mapping_t *m;
- pool_foreach (m, sm->static_mappings,
- ({
- if (m->external_addr.as_u32 == addr.as_u32)
- return 1;
- }));
-
- return 0;
-}
-
-void increment_v4_address (ip4_address_t * a)
-{
- u32 v;
-
- v = clib_net_to_host_u32(a->as_u32) + 1;
- a->as_u32 = clib_host_to_net_u32(v);
-}
-
-static void
-snat_add_static_mapping_when_resolved (snat_main_t * sm,
- ip4_address_t l_addr,
- u16 l_port,
- u32 sw_if_index,
- u16 e_port,
- u32 vrf_id,
- snat_protocol_t proto,
- int addr_only,
- int is_add)
-{
- snat_static_map_resolve_t *rp;
-
- vec_add2 (sm->to_resolve, rp, 1);
- rp->l_addr.as_u32 = l_addr.as_u32;
- rp->l_port = l_port;
- rp->sw_if_index = sw_if_index;
- rp->e_port = e_port;
- rp->vrf_id = vrf_id;
- rp->proto = proto;
- rp->addr_only = addr_only;
- rp->is_add = is_add;
-}
-
-/**
- * @brief Add static mapping.
- *
- * Create static mapping between local addr+port and external addr+port.
- *
- * @param l_addr Local IPv4 address.
- * @param e_addr External IPv4 address.
- * @param l_port Local port number.
- * @param e_port External port number.
- * @param vrf_id VRF ID.
- * @param addr_only If 0 address port and pair mapping, otherwise address only.
- * @param sw_if_index External port instead of specific IP address.
- * @param is_add If 0 delete static mapping, otherwise add.
- *
- * @returns
- */
-int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
- u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
- u32 sw_if_index, snat_protocol_t proto, int is_add)
-{
- snat_main_t * sm = &snat_main;
- snat_static_mapping_t *m;
- snat_session_key_t m_key;
- clib_bihash_kv_8_8_t kv, value;
- snat_address_t *a = 0;
- u32 fib_index = ~0;
- uword * p;
- snat_interface_t *interface;
- int i;
-
- /* If the external address is a specific interface address */
- if (sw_if_index != ~0)
- {
- ip4_address_t * first_int_addr;
-
- /* Might be already set... */
- first_int_addr = ip4_interface_first_address
- (sm->ip4_main, sw_if_index, 0 /* just want the address*/);
-
- /* DHCP resolution required? */
- if (first_int_addr == 0)
- {
- snat_add_static_mapping_when_resolved
- (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
- addr_only, is_add);
- return 0;
- }
- else
- e_addr.as_u32 = first_int_addr->as_u32;
- }
-
- m_key.addr = e_addr;
- m_key.port = addr_only ? 0 : e_port;
- m_key.protocol = addr_only ? 0 : proto;
- m_key.fib_index = sm->outside_fib_index;
- kv.key = m_key.as_u64;
- if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
- m = 0;
- else
- m = pool_elt_at_index (sm->static_mappings, value.value);
-
- if (is_add)
- {
- if (m)
- return VNET_API_ERROR_VALUE_EXIST;
-
- /* Convert VRF id to FIB index */
- if (vrf_id != ~0)
- {
- p = hash_get (sm->ip4_main->fib_index_by_table_id, vrf_id);
- if (!p)
- return VNET_API_ERROR_NO_SUCH_FIB;
- fib_index = p[0];
- }
- /* If not specified use inside VRF id from SNAT plugin startup config */
- else
- {
- fib_index = sm->inside_fib_index;
- vrf_id = sm->inside_vrf_id;
- }
-
- /* Find external address in allocated addresses and reserve port for
- address and port pair mapping when dynamic translations enabled */
- if (!addr_only && !(sm->static_mapping_only))
- {
- for (i = 0; i < vec_len (sm->addresses); i++)
- {
- if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
- {
- a = sm->addresses + i;
- /* External port must be unused */
- switch (proto)
- {
-#define _(N, j, n, s) \
- case SNAT_PROTOCOL_##N: \
- if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
- return VNET_API_ERROR_INVALID_VALUE; \
- clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
- if (e_port > 1024) \
- a->busy_##n##_ports++; \
- break;
- foreach_snat_protocol
-#undef _
- default:
- clib_warning("unknown_protocol");
- return VNET_API_ERROR_INVALID_VALUE_2;
- }
- break;
- }
- }
- /* External address must be allocated */
- if (!a)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
- }
-
- pool_get (sm->static_mappings, m);
- memset (m, 0, sizeof (*m));
- m->local_addr = l_addr;
- m->external_addr = e_addr;
- m->addr_only = addr_only;
- m->vrf_id = vrf_id;
- m->fib_index = fib_index;
- if (!addr_only)
- {
- m->local_port = l_port;
- m->external_port = e_port;
- m->proto = proto;
- }
-
- m_key.addr = m->local_addr;
- m_key.port = m->local_port;
- m_key.protocol = m->proto;
- m_key.fib_index = m->fib_index;
- kv.key = m_key.as_u64;
- kv.value = m - sm->static_mappings;
- clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 1);
-
- m_key.addr = m->external_addr;
- m_key.port = m->external_port;
- m_key.fib_index = sm->outside_fib_index;
- kv.key = m_key.as_u64;
- kv.value = m - sm->static_mappings;
- clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 1);
-
- /* Assign worker */
- if (sm->workers)
- {
- snat_user_key_t w_key0;
- snat_worker_key_t w_key1;
-
- w_key0.addr = m->local_addr;
- w_key0.fib_index = m->fib_index;
- kv.key = w_key0.as_u64;
-
- if (clib_bihash_search_8_8 (&sm->worker_by_in, &kv, &value))
- {
- kv.value = sm->first_worker_index +
- sm->workers[sm->next_worker++ % vec_len (sm->workers)];
-
- clib_bihash_add_del_8_8 (&sm->worker_by_in, &kv, 1);
- }
- else
- {
- kv.value = value.value;
- }
-
- w_key1.addr = m->external_addr;
- w_key1.port = clib_host_to_net_u16 (m->external_port);
- w_key1.fib_index = sm->outside_fib_index;
- kv.key = w_key1.as_u64;
- clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv, 1);
- }
- }
- else
- {
- if (!m)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- /* Free external address port */
- if (!addr_only && !(sm->static_mapping_only))
- {
- for (i = 0; i < vec_len (sm->addresses); i++)
- {
- if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
- {
- a = sm->addresses + i;
- switch (proto)
- {
-#define _(N, j, n, s) \
- case SNAT_PROTOCOL_##N: \
- clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
- if (e_port > 1024) \
- a->busy_##n##_ports--; \
- break;
- foreach_snat_protocol
-#undef _
- default:
- clib_warning("unknown_protocol");
- return VNET_API_ERROR_INVALID_VALUE_2;
- }
- break;
- }
- }
- }
-
- m_key.addr = m->local_addr;
- m_key.port = m->local_port;
- m_key.protocol = m->proto;
- m_key.fib_index = m->fib_index;
- kv.key = m_key.as_u64;
- clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0);
-
- m_key.addr = m->external_addr;
- m_key.port = m->external_port;
- m_key.fib_index = sm->outside_fib_index;
- kv.key = m_key.as_u64;
- clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 0);
-
- /* Delete session(s) for static mapping if exist */
- if (!(sm->static_mapping_only) ||
- (sm->static_mapping_only && sm->static_mapping_connection_tracking))
- {
- snat_user_key_t u_key;
- snat_user_t *u;
- dlist_elt_t * head, * elt;
- u32 elt_index, head_index, del_elt_index;
- u32 ses_index;
- u64 user_index;
- snat_session_t * s;
- snat_main_per_thread_data_t *tsm;
-
- u_key.addr = m->local_addr;
- u_key.fib_index = m->fib_index;
- kv.key = u_key.as_u64;
- if (!clib_bihash_search_8_8 (&sm->user_hash, &kv, &value))
- {
- user_index = value.value;
- if (!clib_bihash_search_8_8 (&sm->worker_by_in, &kv, &value))
- tsm = vec_elt_at_index (sm->per_thread_data, value.value);
- else
- tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
- u = pool_elt_at_index (tsm->users, user_index);
- if (u->nstaticsessions)
- {
- head_index = u->sessions_per_user_list_head_index;
- head = pool_elt_at_index (tsm->list_pool, head_index);
- elt_index = head->next;
- elt = pool_elt_at_index (tsm->list_pool, elt_index);
- ses_index = elt->value;
- while (ses_index != ~0)
- {
- s = pool_elt_at_index (tsm->sessions, ses_index);
- del_elt_index = elt_index;
- elt_index = elt->next;
- elt = pool_elt_at_index (tsm->list_pool, elt_index);
- ses_index = elt->value;
-
- if (!addr_only)
- {
- if ((s->out2in.addr.as_u32 != e_addr.as_u32) &&
- (clib_net_to_host_u16 (s->out2in.port) != e_port))
- continue;
- }
-
- if (snat_is_unk_proto_session (s))
- {
- clib_bihash_kv_16_8_t up_kv;
- snat_unk_proto_ses_key_t up_key;
- up_key.l_addr = s->in2out.addr;
- up_key.r_addr = s->ext_host_addr;
- up_key.fib_index = s->in2out.fib_index;
- up_key.proto = s->in2out.port;
- up_key.rsvd[0] = up_key.rsvd[1] = up_key.rsvd[2] = 0;
- up_kv.key[0] = up_key.as_u64[0];
- up_kv.key[1] = up_key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->in2out_unk_proto,
- &up_kv, 0))
- clib_warning ("in2out key del failed");
-
- up_key.l_addr = s->out2in.addr;
- up_key.fib_index = s->out2in.fib_index;
- up_kv.key[0] = up_key.as_u64[0];
- up_kv.key[1] = up_key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->out2in_unk_proto,
- &up_kv, 0))
- clib_warning ("out2in key del failed");
-
- goto delete;
- }
- /* log NAT event */
- snat_ipfix_logging_nat44_ses_delete(s->in2out.addr.as_u32,
- s->out2in.addr.as_u32,
- s->in2out.protocol,
- s->in2out.port,
- s->out2in.port,
- s->in2out.fib_index);
-
- value.key = s->in2out.as_u64;
- if (clib_bihash_add_del_8_8 (&sm->in2out, &value, 0))
- clib_warning ("in2out key del failed");
- value.key = s->out2in.as_u64;
- if (clib_bihash_add_del_8_8 (&sm->out2in, &value, 0))
- clib_warning ("out2in key del failed");
-delete:
- pool_put (tsm->sessions, s);
-
- clib_dlist_remove (tsm->list_pool, del_elt_index);
- pool_put_index (tsm->list_pool, del_elt_index);
- u->nstaticsessions--;
-
- if (!addr_only)
- break;
- }
- if (addr_only)
- {
- pool_put (tsm->users, u);
- clib_bihash_add_del_8_8 (&sm->user_hash, &kv, 0);
- }
- }
- }
- }
-
- /* Delete static mapping from pool */
- pool_put (sm->static_mappings, m);
- }
-
- if (!addr_only)
- return 0;
-
- /* Add/delete external address to FIB */
- pool_foreach (interface, sm->interfaces,
- ({
- if (interface->is_inside)
- continue;
-
- snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
- break;
- }));
- pool_foreach (interface, sm->output_feature_interfaces,
- ({
- if (interface->is_inside)
- continue;
-
- snat_add_del_addr_to_fib(&e_addr, 32, interface->sw_if_index, is_add);
- break;
- }));
-
- return 0;
-}
-
-int snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm)
-{
- snat_address_t *a = 0;
- snat_session_t *ses;
- u32 *ses_to_be_removed = 0, *ses_index;
- clib_bihash_kv_8_8_t kv, value;
- snat_user_key_t user_key;
- snat_user_t *u;
- snat_main_per_thread_data_t *tsm;
- snat_static_mapping_t *m;
- snat_interface_t *interface;
- int i;
-
- /* Find SNAT address */
- for (i=0; i < vec_len (sm->addresses); i++)
- {
- if (sm->addresses[i].addr.as_u32 == addr.as_u32)
- {
- a = sm->addresses + i;
- break;
- }
- }
- if (!a)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- if (delete_sm)
- {
- pool_foreach (m, sm->static_mappings,
- ({
- if (m->external_addr.as_u32 == addr.as_u32)
- (void) snat_add_static_mapping (m->local_addr, m->external_addr,
- m->local_port, m->external_port,
- m->vrf_id, m->addr_only, ~0,
- m->proto, 0);
- }));
- }
- else
- {
- /* Check if address is used in some static mapping */
- if (is_snat_address_used_in_static_mapping(sm, addr))
- {
- clib_warning ("address used in static mapping");
- return VNET_API_ERROR_UNSPECIFIED;
- }
- }
-
- if (a->fib_index != ~0)
- fib_table_unlock(a->fib_index, FIB_PROTOCOL_IP4);
-
- /* Delete sessions using address */
- if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
- {
- vec_foreach (tsm, sm->per_thread_data)
- {
- pool_foreach (ses, tsm->sessions, ({
- if (ses->out2in.addr.as_u32 == addr.as_u32)
- {
- if (snat_is_unk_proto_session (ses))
- {
- clib_bihash_kv_16_8_t up_kv;
- snat_unk_proto_ses_key_t up_key;
- up_key.l_addr = ses->in2out.addr;
- up_key.r_addr = ses->ext_host_addr;
- up_key.fib_index = ses->in2out.fib_index;
- up_key.proto = ses->in2out.port;
- up_key.rsvd[0] = up_key.rsvd[1] = up_key.rsvd[2] = 0;
- up_kv.key[0] = up_key.as_u64[0];
- up_kv.key[1] = up_key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->in2out_unk_proto,
- &up_kv, 0))
- clib_warning ("in2out key del failed");
-
- up_key.l_addr = ses->out2in.addr;
- up_key.fib_index = ses->out2in.fib_index;
- up_kv.key[0] = up_key.as_u64[0];
- up_kv.key[1] = up_key.as_u64[1];
- if (clib_bihash_add_del_16_8 (&sm->out2in_unk_proto,
- &up_kv, 0))
- clib_warning ("out2in key del failed");
- }
- else
- {
- /* log NAT event */
- snat_ipfix_logging_nat44_ses_delete(ses->in2out.addr.as_u32,
- ses->out2in.addr.as_u32,
- ses->in2out.protocol,
- ses->in2out.port,
- ses->out2in.port,
- ses->in2out.fib_index);
- kv.key = ses->in2out.as_u64;
- clib_bihash_add_del_8_8 (&sm->in2out, &kv, 0);
- kv.key = ses->out2in.as_u64;
- clib_bihash_add_del_8_8 (&sm->out2in, &kv, 0);
- }
- vec_add1 (ses_to_be_removed, ses - tsm->sessions);
- clib_dlist_remove (tsm->list_pool, ses->per_user_index);
- user_key.addr = ses->in2out.addr;
- user_key.fib_index = ses->in2out.fib_index;
- kv.key = user_key.as_u64;
- if (!clib_bihash_search_8_8 (&sm->user_hash, &kv, &value))
- {
- u = pool_elt_at_index (tsm->users, value.value);
- u->nsessions--;
- }
- }
- }));
-
- vec_foreach (ses_index, ses_to_be_removed)
- pool_put_index (tsm->sessions, ses_index[0]);
-
- vec_free (ses_to_be_removed);
- }
- }
-
- vec_del1 (sm->addresses, i);
-
- /* Delete external address from FIB */
- pool_foreach (interface, sm->interfaces,
- ({
- if (interface->is_inside)
- continue;
-
- snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
- break;
- }));
- pool_foreach (interface, sm->output_feature_interfaces,
- ({
- if (interface->is_inside)
- continue;
-
- snat_add_del_addr_to_fib(&addr, 32, interface->sw_if_index, 0);
- break;
- }));
-
- return 0;
-}
-
-int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
-{
- snat_main_t *sm = &snat_main;
- snat_interface_t *i;
- const char * feature_name;
- snat_address_t * ap;
- snat_static_mapping_t * m;
- snat_det_map_t * dm;
-
- if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
- feature_name = is_inside ? "snat-in2out-fast" : "snat-out2in-fast";
- else
- {
- if (sm->num_workers > 1 && !sm->deterministic)
- feature_name = is_inside ? "snat-in2out-worker-handoff" : "snat-out2in-worker-handoff";
- else if (sm->deterministic)
- feature_name = is_inside ? "snat-det-in2out" : "snat-det-out2in";
- else
- feature_name = is_inside ? "snat-in2out" : "snat-out2in";
- }
-
- vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index,
- !is_del, 0, 0);
-
- if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
- sm->fq_in2out_index = vlib_frame_queue_main_init (sm->in2out_node_index, 0);
-
- if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
- sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index, 0);
-
- pool_foreach (i, sm->interfaces,
- ({
- if (i->sw_if_index == sw_if_index)
- {
- if (is_del)
- pool_put (sm->interfaces, i);
- else
- return VNET_API_ERROR_VALUE_EXIST;
-
- goto fib;
- }
- }));
-
- if (is_del)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- pool_get (sm->interfaces, i);
- i->sw_if_index = sw_if_index;
- i->is_inside = is_inside;
-
- /* Add/delete external addresses to FIB */
-fib:
- if (is_inside)
- return 0;
-
- vec_foreach (ap, sm->addresses)
- snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
-
- pool_foreach (m, sm->static_mappings,
- ({
- if (!(m->addr_only))
- continue;
-
- snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
- }));
-
- pool_foreach (dm, sm->det_maps,
- ({
- snat_add_del_addr_to_fib(&dm->out_addr, dm->out_plen, sw_if_index, !is_del);
- }));
-
- return 0;
-}
-
-int snat_interface_add_del_output_feature (u32 sw_if_index,
- u8 is_inside,
- int is_del)
-{
- snat_main_t *sm = &snat_main;
- snat_interface_t *i;
- snat_address_t * ap;
- snat_static_mapping_t * m;
-
- if (sm->deterministic ||
- (sm->static_mapping_only && !(sm->static_mapping_connection_tracking)))
- return VNET_API_ERROR_UNSUPPORTED;
-
- if (is_inside)
- {
- vnet_feature_enable_disable ("ip4-unicast", "snat-hairpin-dst",
- sw_if_index, !is_del, 0, 0);
- vnet_feature_enable_disable ("ip4-output", "snat-hairpin-src",
- sw_if_index, !is_del, 0, 0);
- goto fq;
- }
-
- if (sm->num_workers > 1)
- {
- vnet_feature_enable_disable ("ip4-unicast", "snat-out2in-worker-handoff",
- sw_if_index, !is_del, 0, 0);
- vnet_feature_enable_disable ("ip4-output",
- "snat-in2out-output-worker-handoff",
- sw_if_index, !is_del, 0, 0);
- }
- else
- {
- vnet_feature_enable_disable ("ip4-unicast", "snat-out2in", sw_if_index,
- !is_del, 0, 0);
- vnet_feature_enable_disable ("ip4-output", "snat-in2out-output",
- sw_if_index, !is_del, 0, 0);
- }
-
-fq:
- if (sm->fq_in2out_output_index == ~0 && sm->num_workers > 1)
- sm->fq_in2out_output_index =
- vlib_frame_queue_main_init (sm->in2out_output_node_index, 0);
-
- if (sm->fq_out2in_index == ~0 && sm->num_workers > 1)
- sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index, 0);
-
- pool_foreach (i, sm->output_feature_interfaces,
- ({
- if (i->sw_if_index == sw_if_index)
- {
- if (is_del)
- pool_put (sm->output_feature_interfaces, i);
- else
- return VNET_API_ERROR_VALUE_EXIST;
-
- goto fib;
- }
- }));
-
- if (is_del)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- pool_get (sm->output_feature_interfaces, i);
- i->sw_if_index = sw_if_index;
- i->is_inside = is_inside;
-
- /* Add/delete external addresses to FIB */
-fib:
- if (is_inside)
- return 0;
-
- vec_foreach (ap, sm->addresses)
- snat_add_del_addr_to_fib(&ap->addr, 32, sw_if_index, !is_del);
-
- pool_foreach (m, sm->static_mappings,
- ({
- if (!(m->addr_only))
- continue;
-
- snat_add_del_addr_to_fib(&m->external_addr, 32, sw_if_index, !is_del);
- }));
-
- return 0;
-}
-
-int snat_set_workers (uword * bitmap)
-{
- snat_main_t *sm = &snat_main;
- int i, j = 0;
-
- if (sm->num_workers < 2)
- return VNET_API_ERROR_FEATURE_DISABLED;
-
- if (clib_bitmap_last_set (bitmap) >= sm->num_workers)
- return VNET_API_ERROR_INVALID_WORKER;
-
- vec_free (sm->workers);
- clib_bitmap_foreach (i, bitmap,
- ({
- vec_add1(sm->workers, i);
- sm->per_thread_data[i].snat_thread_index = j;
- j++;
- }));
-
- sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers);
- sm->num_snat_thread = _vec_len (sm->workers);
-
- return 0;
-}
-
-
-static void
-snat_ip4_add_del_interface_address_cb (ip4_main_t * im,
- uword opaque,
- u32 sw_if_index,
- ip4_address_t * address,
- u32 address_length,
- u32 if_address_index,
- u32 is_delete);
-
-static clib_error_t * snat_init (vlib_main_t * vm)
-{
- snat_main_t * sm = &snat_main;
- clib_error_t * error = 0;
- ip4_main_t * im = &ip4_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- uword *p;
- vlib_thread_registration_t *tr;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- uword *bitmap = 0;
- u32 i;
- ip4_add_del_interface_address_callback_t cb4;
-
- sm->vlib_main = vm;
- sm->vnet_main = vnet_get_main();
- sm->ip4_main = im;
- sm->ip4_lookup_main = lm;
- sm->api_main = &api_main;
- sm->first_worker_index = 0;
- sm->next_worker = 0;
- sm->num_workers = 0;
- sm->num_snat_thread = 1;
- sm->workers = 0;
- sm->port_per_thread = 0xffff - 1024;
- sm->fq_in2out_index = ~0;
- sm->fq_out2in_index = ~0;
- sm->udp_timeout = SNAT_UDP_TIMEOUT;
- sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
- sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
- sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
-
- p = hash_get_mem (tm->thread_registrations_by_name, "workers");
- if (p)
- {
- tr = (vlib_thread_registration_t *) p[0];
- if (tr)
- {
- sm->num_workers = tr->count;
- sm->first_worker_index = tr->first_index;
- }
- }
-
- vec_validate (sm->per_thread_data, tm->n_vlib_mains - 1);
-
- /* Use all available workers by default */
- if (sm->num_workers > 1)
- {
- for (i=0; i < sm->num_workers; i++)
- bitmap = clib_bitmap_set (bitmap, i, 1);
- snat_set_workers(bitmap);
- clib_bitmap_free (bitmap);
- }
- else
- {
- sm->per_thread_data[0].snat_thread_index = 0;
- }
-
- error = snat_api_init(vm, sm);
- if (error)
- return error;
-
- /* Set up the interface address add/del callback */
- cb4.function = snat_ip4_add_del_interface_address_cb;
- cb4.function_opaque = 0;
-
- vec_add1 (im->add_del_interface_address_callbacks, cb4);
-
- /* Init IPFIX logging */
- snat_ipfix_logging_init(vm);
-
- error = nat64_init(vm);
-
- return error;
-}
-
-VLIB_INIT_FUNCTION (snat_init);
-
-void snat_free_outside_address_and_port (snat_main_t * sm,
- snat_session_key_t * k,
- u32 address_index)
-{
- snat_address_t *a;
- u16 port_host_byte_order = clib_net_to_host_u16 (k->port);
-
- ASSERT (address_index < vec_len (sm->addresses));
-
- a = sm->addresses + address_index;
-
- switch (k->protocol)
- {
-#define _(N, i, n, s) \
- case SNAT_PROTOCOL_##N: \
- ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
- port_host_byte_order) == 1); \
- clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
- port_host_byte_order, 0); \
- a->busy_##n##_ports--; \
- break;
- foreach_snat_protocol
-#undef _
- default:
- clib_warning("unknown_protocol");
- return;
- }
-}
-
-/**
- * @brief Match SNAT static mapping.
- *
- * @param sm SNAT main.
- * @param match Address and port to match.
- * @param mapping External or local address and port of the matched mapping.
- * @param by_external If 0 match by local address otherwise match by external
- * address.
- * @param is_addr_only If matched mapping is address only
- *
- * @returns 0 if match found otherwise 1.
- */
-int snat_static_mapping_match (snat_main_t * sm,
- snat_session_key_t match,
- snat_session_key_t * mapping,
- u8 by_external,
- u8 *is_addr_only)
-{
- clib_bihash_kv_8_8_t kv, value;
- snat_static_mapping_t *m;
- snat_session_key_t m_key;
- clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
-
- if (by_external)
- mapping_hash = &sm->static_mapping_by_external;
-
- m_key.addr = match.addr;
- m_key.port = clib_net_to_host_u16 (match.port);
- m_key.protocol = match.protocol;
- m_key.fib_index = match.fib_index;
-
- kv.key = m_key.as_u64;
-
- if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
- {
- /* Try address only mapping */
- m_key.port = 0;
- m_key.protocol = 0;
- kv.key = m_key.as_u64;
- if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
- return 1;
- }
-
- m = pool_elt_at_index (sm->static_mappings, value.value);
-
- if (by_external)
- {
- mapping->addr = m->local_addr;
- /* Address only mapping doesn't change port */
- mapping->port = m->addr_only ? match.port
- : clib_host_to_net_u16 (m->local_port);
- mapping->fib_index = m->fib_index;
- }
- else
- {
- mapping->addr = m->external_addr;
- /* Address only mapping doesn't change port */
- mapping->port = m->addr_only ? match.port
- : clib_host_to_net_u16 (m->external_port);
- mapping->fib_index = sm->outside_fib_index;
- }
-
- if (PREDICT_FALSE(is_addr_only != 0))
- *is_addr_only = m->addr_only;
-
- return 0;
-}
-
-static_always_inline u16
-snat_random_port (snat_main_t * sm, u16 min, u16 max)
-{
- return min + random_u32 (&sm->random_seed) /
- (random_u32_max() / (max - min + 1) + 1);
-}
-
-int snat_alloc_outside_address_and_port (snat_main_t * sm,
- u32 fib_index,
- u32 thread_index,
- snat_session_key_t * k,
- u32 * address_indexp)
-{
- int i;
- snat_address_t *a;
- u32 portnum;
-
- for (i = 0; i < vec_len (sm->addresses); i++)
- {
- a = sm->addresses + i;
- if (sm->vrf_mode && a->fib_index != ~0 && a->fib_index != fib_index)
- continue;
- switch (k->protocol)
- {
-#define _(N, j, n, s) \
- case SNAT_PROTOCOL_##N: \
- if (a->busy_##n##_ports < (sm->port_per_thread * sm->num_snat_thread)) \
- { \
- while (1) \
- { \
- portnum = (sm->port_per_thread * \
- sm->per_thread_data[thread_index].snat_thread_index) + \
- snat_random_port(sm, 0, sm->port_per_thread) + 1024; \
- if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
- continue; \
- clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
- a->busy_##n##_ports++; \
- k->addr = a->addr; \
- k->port = clib_host_to_net_u16(portnum); \
- *address_indexp = i; \
- return 0; \
- } \
- } \
- break;
- foreach_snat_protocol
-#undef _
- default:
- clib_warning("unknown protocol");
- return 1;
- }
-
- }
- /* Totally out of translations to use... */
- snat_ipfix_logging_addresses_exhausted(0);
- return 1;
-}
-
-
-static clib_error_t *
-add_address_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, *line_input = &_line_input;
- snat_main_t * sm = &snat_main;
- ip4_address_t start_addr, end_addr, this_addr;
- u32 start_host_order, end_host_order;
- u32 vrf_id = ~0;
- int i, count;
- int is_add = 1;
- int rv = 0;
- clib_error_t *error = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "%U - %U",
- unformat_ip4_address, &start_addr,
- unformat_ip4_address, &end_addr))
- ;
- else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
- ;
- else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
- end_addr = start_addr;
- else if (unformat (line_input, "del"))
- is_add = 0;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- if (sm->static_mapping_only)
- {
- error = clib_error_return (0, "static mapping only mode");
- goto done;
- }
-
- start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
- end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
-
- if (end_host_order < start_host_order)
- {
- error = clib_error_return (0, "end address less than start address");
- goto done;
- }
-
- count = (end_host_order - start_host_order) + 1;
-
- if (count > 1024)
- clib_warning ("%U - %U, %d addresses...",
- format_ip4_address, &start_addr,
- format_ip4_address, &end_addr,
- count);
-
- this_addr = start_addr;
-
- for (i = 0; i < count; i++)
- {
- if (is_add)
- snat_add_address (sm, &this_addr, vrf_id);
- else
- rv = snat_del_address (sm, this_addr, 0);
-
- switch (rv)
- {
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- error = clib_error_return (0, "S-NAT address not exist.");
- goto done;
- case VNET_API_ERROR_UNSPECIFIED:
- error = clib_error_return (0, "S-NAT address used in static mapping.");
- goto done;
- default:
- break;
- }
-
- increment_v4_address (&this_addr);
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-VLIB_CLI_COMMAND (add_address_command, static) = {
- .path = "snat add address",
- .short_help = "snat add addresses <ip4-range-start> [- <ip4-range-end>] "
- "[tenant-vrf <vrf-id>] [del]",
- .function = add_address_command_fn,
-};
-
-static clib_error_t *
-snat_feature_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, *line_input = &_line_input;
- vnet_main_t * vnm = vnet_get_main();
- clib_error_t * error = 0;
- u32 sw_if_index;
- u32 * inside_sw_if_indices = 0;
- u32 * outside_sw_if_indices = 0;
- u8 is_output_feature = 0;
- int is_del = 0;
- int i;
-
- sw_if_index = ~0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
- vnm, &sw_if_index))
- vec_add1 (inside_sw_if_indices, sw_if_index);
- else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
- vnm, &sw_if_index))
- vec_add1 (outside_sw_if_indices, sw_if_index);
- else if (unformat (line_input, "output-feature"))
- is_output_feature = 1;
- else if (unformat (line_input, "del"))
- is_del = 1;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- if (vec_len (inside_sw_if_indices))
- {
- for (i = 0; i < vec_len(inside_sw_if_indices); i++)
- {
- sw_if_index = inside_sw_if_indices[i];
- if (is_output_feature)
- {
- if (snat_interface_add_del_output_feature (sw_if_index, 1, is_del))
- {
- error = clib_error_return (0, "%s %U failed",
- is_del ? "del" : "add",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm,
- sw_if_index));
- goto done;
- }
- }
- else
- {
- if (snat_interface_add_del (sw_if_index, 1, is_del))
- {
- error = clib_error_return (0, "%s %U failed",
- is_del ? "del" : "add",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm,
- sw_if_index));
- goto done;
- }
- }
- }
- }
-
- if (vec_len (outside_sw_if_indices))
- {
- for (i = 0; i < vec_len(outside_sw_if_indices); i++)
- {
- sw_if_index = outside_sw_if_indices[i];
- if (is_output_feature)
- {
- if (snat_interface_add_del_output_feature (sw_if_index, 0, is_del))
- {
- error = clib_error_return (0, "%s %U failed",
- is_del ? "del" : "add",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm,
- sw_if_index));
- goto done;
- }
- }
- else
- {
- if (snat_interface_add_del (sw_if_index, 0, is_del))
- {
- error = clib_error_return (0, "%s %U failed",
- is_del ? "del" : "add",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm,
- sw_if_index));
- goto done;
- }
- }
- }
- }
-
-done:
- unformat_free (line_input);
- vec_free (inside_sw_if_indices);
- vec_free (outside_sw_if_indices);
-
- return error;
-}
-
-VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
- .path = "set interface snat",
- .function = snat_feature_command_fn,
- .short_help = "set interface snat in <intfc> out <intfc> [output-feature] "
- "[del]",
-};
-
-uword
-unformat_snat_protocol (unformat_input_t * input, va_list * args)
-{
- u32 *r = va_arg (*args, u32 *);
-
- if (0);
-#define _(N, i, n, s) else if (unformat (input, s)) *r = SNAT_PROTOCOL_##N;
- foreach_snat_protocol
-#undef _
- else
- return 0;
- return 1;
-}
-
-u8 *
-format_snat_protocol (u8 * s, va_list * args)
-{
- u32 i = va_arg (*args, u32);
- u8 *t = 0;
-
- switch (i)
- {
-#define _(N, j, n, str) case SNAT_PROTOCOL_##N: t = (u8 *) str; break;
- foreach_snat_protocol
-#undef _
- default:
- s = format (s, "unknown");
- return s;
- }
- s = format (s, "%s", t);
- return s;
-}
-
-static clib_error_t *
-add_static_mapping_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, *line_input = &_line_input;
- clib_error_t * error = 0;
- ip4_address_t l_addr, e_addr;
- u32 l_port = 0, e_port = 0, vrf_id = ~0;
- int is_add = 1;
- int addr_only = 1;
- u32 sw_if_index = ~0;
- vnet_main_t * vnm = vnet_get_main();
- int rv;
- snat_protocol_t proto;
- u8 proto_set = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr,
- &l_port))
- addr_only = 0;
- else if (unformat (line_input, "local %U", unformat_ip4_address, &l_addr))
- ;
- else if (unformat (line_input, "external %U %u", unformat_ip4_address,
- &e_addr, &e_port))
- addr_only = 0;
- else if (unformat (line_input, "external %U", unformat_ip4_address,
- &e_addr))
- ;
- else if (unformat (line_input, "external %U %u",
- unformat_vnet_sw_interface, vnm, &sw_if_index,
- &e_port))
- addr_only = 0;
-
- else if (unformat (line_input, "external %U",
- unformat_vnet_sw_interface, vnm, &sw_if_index))
- ;
- else if (unformat (line_input, "vrf %u", &vrf_id))
- ;
- else if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
- proto_set = 1;
- else if (unformat (line_input, "del"))
- is_add = 0;
- else
- {
- error = clib_error_return (0, "unknown input: '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- if (!addr_only && !proto_set)
- {
- error = clib_error_return (0, "missing protocol");
- goto done;
- }
-
- rv = snat_add_static_mapping(l_addr, e_addr, (u16) l_port, (u16) e_port,
- vrf_id, addr_only, sw_if_index, proto, is_add);
-
- switch (rv)
- {
- case VNET_API_ERROR_INVALID_VALUE:
- error = clib_error_return (0, "External port already in use.");
- goto done;
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- if (is_add)
- error = clib_error_return (0, "External addres must be allocated.");
- else
- error = clib_error_return (0, "Mapping not exist.");
- goto done;
- case VNET_API_ERROR_NO_SUCH_FIB:
- error = clib_error_return (0, "No such VRF id.");
- goto done;
- case VNET_API_ERROR_VALUE_EXIST:
- error = clib_error_return (0, "Mapping already exist.");
- goto done;
- default:
- break;
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-/*?
- * @cliexpar
- * @cliexstart{snat add static mapping}
- * Static mapping allows hosts on the external network to initiate connection
- * to to the local network host.
- * To create static mapping between local host address 10.0.0.3 port 6303 and
- * external address 4.4.4.4 port 3606 for TCP protocol use:
- * vpp# snat add static mapping local tcp 10.0.0.3 6303 external 4.4.4.4 3606
- * If not runnig "static mapping only" S-NAT plugin mode use before:
- * vpp# snat add address 4.4.4.4
- * To create static mapping between local and external address use:
- * vpp# snat add static mapping local 10.0.0.3 external 4.4.4.4
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
- .path = "snat add static mapping",
- .function = add_static_mapping_command_fn,
- .short_help =
- "snat add static mapping local tcp|udp|icmp <addr> [<port>] external <addr> [<port>] [vrf <table-id>] [del]",
-};
-
-static clib_error_t *
-set_workers_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, *line_input = &_line_input;
- uword *bitmap = 0;
- int rv = 0;
- clib_error_t *error = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "%U", unformat_bitmap_list, &bitmap))
- ;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- if (bitmap == 0)
- {
- error = clib_error_return (0, "List of workers must be specified.");
- goto done;
- }
-
- rv = snat_set_workers(bitmap);
-
- clib_bitmap_free (bitmap);
-
- switch (rv)
- {
- case VNET_API_ERROR_INVALID_WORKER:
- error = clib_error_return (0, "Invalid worker(s).");
- goto done;
- case VNET_API_ERROR_FEATURE_DISABLED:
- error = clib_error_return (0,
- "Supported only if 2 or more workes available.");
- goto done;
- default:
- break;
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-/*?
- * @cliexpar
- * @cliexstart{set snat workers}
- * Set SNAT workers if 2 or more workers available, use:
- * vpp# set snat workers 0-2,5
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (set_workers_command, static) = {
- .path = "set snat workers",
- .function = set_workers_command_fn,
- .short_help =
- "set snat workers <workers-list>",
-};
-
-static clib_error_t *
-snat_ipfix_logging_enable_disable_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, *line_input = &_line_input;
- u32 domain_id = 0;
- u32 src_port = 0;
- u8 enable = 1;
- int rv = 0;
- clib_error_t *error = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "domain %d", &domain_id))
- ;
- else if (unformat (line_input, "src-port %d", &src_port))
- ;
- else if (unformat (line_input, "disable"))
- enable = 0;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- rv = snat_ipfix_logging_enable_disable (enable, domain_id, (u16) src_port);
-
- if (rv)
- {
- error = clib_error_return (0, "ipfix logging enable failed");
- goto done;
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-/*?
- * @cliexpar
- * @cliexstart{snat ipfix logging}
- * To enable SNAT IPFIX logging use:
- * vpp# snat ipfix logging
- * To set IPFIX exporter use:
- * vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
- .path = "snat ipfix logging",
- .function = snat_ipfix_logging_enable_disable_command_fn,
- .short_help = "snat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
-};
-
-static u32
-snat_get_worker_in2out_cb (ip4_header_t * ip0, u32 rx_fib_index0)
-{
- snat_main_t *sm = &snat_main;
- snat_user_key_t key0;
- clib_bihash_kv_8_8_t kv0, value0;
- u32 next_worker_index = 0;
-
- key0.addr = ip0->src_address;
- key0.fib_index = rx_fib_index0;
-
- kv0.key = key0.as_u64;
-
- /* Ever heard of of the "user" before? */
- if (clib_bihash_search_8_8 (&sm->worker_by_in, &kv0, &value0))
- {
- /* No, assign next available worker (RR) */
- next_worker_index = sm->first_worker_index;
- if (vec_len (sm->workers))
- {
- next_worker_index +=
- sm->workers[sm->next_worker++ % _vec_len (sm->workers)];
- }
-
- /* add non-traslated packets worker lookup */
- kv0.value = next_worker_index;
- clib_bihash_add_del_8_8 (&sm->worker_by_in, &kv0, 1);
- }
- else
- next_worker_index = value0.value;
-
- return next_worker_index;
-}
-
-static u32
-snat_get_worker_out2in_cb (ip4_header_t * ip0, u32 rx_fib_index0)
-{
- snat_main_t *sm = &snat_main;
- snat_worker_key_t key0;
- clib_bihash_kv_8_8_t kv0, value0;
- udp_header_t * udp0;
- u32 next_worker_index = 0;
-
- udp0 = ip4_next_header (ip0);
-
- key0.addr = ip0->dst_address;
- key0.port = udp0->dst_port;
- key0.fib_index = rx_fib_index0;
-
- if (PREDICT_FALSE(ip0->protocol == IP_PROTOCOL_ICMP))
- {
- icmp46_header_t * icmp0 = (icmp46_header_t *) udp0;
- icmp_echo_header_t *echo0 = (icmp_echo_header_t *)(icmp0+1);
- key0.port = echo0->identifier;
- }
-
- kv0.key = key0.as_u64;
-
- /* Ever heard of of the "user" before? */
- if (clib_bihash_search_8_8 (&sm->worker_by_out, &kv0, &value0))
- {
- key0.port = 0;
- kv0.key = key0.as_u64;
-
- if (clib_bihash_search_8_8 (&sm->worker_by_out, &kv0, &value0))
- {
- /* No, assign next available worker (RR) */
- next_worker_index = sm->first_worker_index;
- if (vec_len (sm->workers))
- {
- next_worker_index +=
- sm->workers[sm->next_worker++ % _vec_len (sm->workers)];
- }
- }
- else
- {
- /* Static mapping without port */
- next_worker_index = value0.value;
- }
-
- /* Add to translated packets worker lookup */
- kv0.value = next_worker_index;
- clib_bihash_add_del_8_8 (&sm->worker_by_out, &kv0, 1);
- }
- else
- next_worker_index = value0.value;
-
- return next_worker_index;
-}
-
-static clib_error_t *
-snat_config (vlib_main_t * vm, unformat_input_t * input)
-{
- snat_main_t * sm = &snat_main;
- u32 translation_buckets = 1024;
- u32 translation_memory_size = 128<<20;
- u32 user_buckets = 128;
- u32 user_memory_size = 64<<20;
- u32 max_translations_per_user = 100;
- u32 outside_vrf_id = 0;
- u32 inside_vrf_id = 0;
- u32 static_mapping_buckets = 1024;
- u32 static_mapping_memory_size = 64<<20;
- u8 static_mapping_only = 0;
- u8 static_mapping_connection_tracking = 0;
-
- sm->deterministic = 0;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "translation hash buckets %d", &translation_buckets))
- ;
- else if (unformat (input, "translation hash memory %d",
- &translation_memory_size));
- else if (unformat (input, "user hash buckets %d", &user_buckets))
- ;
- else if (unformat (input, "user hash memory %d",
- &user_memory_size))
- ;
- else if (unformat (input, "max translations per user %d",
- &max_translations_per_user))
- ;
- else if (unformat (input, "outside VRF id %d",
- &outside_vrf_id))
- ;
- else if (unformat (input, "inside VRF id %d",
- &inside_vrf_id))
- ;
- else if (unformat (input, "static mapping only"))
- {
- static_mapping_only = 1;
- if (unformat (input, "connection tracking"))
- static_mapping_connection_tracking = 1;
- }
- else if (unformat (input, "deterministic"))
- sm->deterministic = 1;
- else
- return clib_error_return (0, "unknown input '%U'",
- format_unformat_error, input);
- }
-
- /* for show commands, etc. */
- sm->translation_buckets = translation_buckets;
- sm->translation_memory_size = translation_memory_size;
- sm->user_buckets = user_buckets;
- sm->user_memory_size = user_memory_size;
- sm->max_translations_per_user = max_translations_per_user;
- sm->outside_vrf_id = outside_vrf_id;
- sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
- outside_vrf_id);
- sm->inside_vrf_id = inside_vrf_id;
- sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
- inside_vrf_id);
- sm->static_mapping_only = static_mapping_only;
- sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
-
- if (sm->deterministic)
- {
- sm->in2out_node_index = snat_det_in2out_node.index;
- sm->in2out_output_node_index = ~0;
- sm->out2in_node_index = snat_det_out2in_node.index;
- sm->icmp_match_in2out_cb = icmp_match_in2out_det;
- sm->icmp_match_out2in_cb = icmp_match_out2in_det;
- }
- else
- {
- sm->worker_in2out_cb = snat_get_worker_in2out_cb;
- sm->worker_out2in_cb = snat_get_worker_out2in_cb;
- sm->in2out_node_index = snat_in2out_node.index;
- sm->in2out_output_node_index = snat_in2out_output_node.index;
- sm->out2in_node_index = snat_out2in_node.index;
- if (!static_mapping_only ||
- (static_mapping_only && static_mapping_connection_tracking))
- {
- sm->icmp_match_in2out_cb = icmp_match_in2out_slow;
- sm->icmp_match_out2in_cb = icmp_match_out2in_slow;
-
- clib_bihash_init_8_8 (&sm->worker_by_in, "worker-by-in", user_buckets,
- user_memory_size);
-
- clib_bihash_init_8_8 (&sm->worker_by_out, "worker-by-out", user_buckets,
- user_memory_size);
-
- clib_bihash_init_8_8 (&sm->in2out, "in2out", translation_buckets,
- translation_memory_size);
-
- clib_bihash_init_8_8 (&sm->out2in, "out2in", translation_buckets,
- translation_memory_size);
-
- clib_bihash_init_8_8 (&sm->user_hash, "users", user_buckets,
- user_memory_size);
-
- clib_bihash_init_16_8 (&sm->in2out_unk_proto, "in2out-unk-proto",
- translation_buckets, translation_memory_size);
-
- clib_bihash_init_16_8 (&sm->out2in_unk_proto, "out2in-unk-proto",
- translation_buckets, translation_memory_size);
- }
- else
- {
- sm->icmp_match_in2out_cb = icmp_match_in2out_fast;
- sm->icmp_match_out2in_cb = icmp_match_out2in_fast;
- }
- clib_bihash_init_8_8 (&sm->static_mapping_by_local,
- "static_mapping_by_local", static_mapping_buckets,
- static_mapping_memory_size);
-
- clib_bihash_init_8_8 (&sm->static_mapping_by_external,
- "static_mapping_by_external", static_mapping_buckets,
- static_mapping_memory_size);
- }
-
- return 0;
-}
-
-VLIB_CONFIG_FUNCTION (snat_config, "snat");
-
-u8 * format_snat_session_state (u8 * s, va_list * args)
-{
- u32 i = va_arg (*args, u32);
- u8 *t = 0;
-
- switch (i)
- {
-#define _(v, N, str) case SNAT_SESSION_##N: t = (u8 *) str; break;
- foreach_snat_session_state
-#undef _
- default:
- t = format (t, "unknown");
- }
- s = format (s, "%s", t);
- return s;
-}
-
-u8 * format_snat_key (u8 * s, va_list * args)
-{
- snat_session_key_t * key = va_arg (*args, snat_session_key_t *);
- char * protocol_string = "unknown";
- static char *protocol_strings[] = {
- "UDP",
- "TCP",
- "ICMP",
- };
-
- if (key->protocol < ARRAY_LEN(protocol_strings))
- protocol_string = protocol_strings[key->protocol];
-
- s = format (s, "%U proto %s port %d fib %d",
- format_ip4_address, &key->addr, protocol_string,
- clib_net_to_host_u16 (key->port), key->fib_index);
- return s;
-}
-
-u8 * format_snat_session (u8 * s, va_list * args)
-{
- snat_main_t * sm __attribute__((unused)) = va_arg (*args, snat_main_t *);
- snat_session_t * sess = va_arg (*args, snat_session_t *);
-
- if (snat_is_unk_proto_session (sess))
- {
- s = format (s, " i2o %U proto %u fib %u\n",
- format_ip4_address, &sess->in2out.addr, sess->in2out.port,
- sess->in2out.fib_index);
- s = format (s, " o2i %U proto %u fib %u\n",
- format_ip4_address, &sess->out2in.addr, sess->out2in.port,
- sess->out2in.fib_index);
- }
- else
- {
- s = format (s, " i2o %U\n", format_snat_key, &sess->in2out);
- s = format (s, " o2i %U\n", format_snat_key, &sess->out2in);
- }
- s = format (s, " last heard %.2f\n", sess->last_heard);
- s = format (s, " total pkts %d, total bytes %lld\n",
- sess->total_pkts, sess->total_bytes);
- if (snat_is_session_static (sess))
- s = format (s, " static translation\n");
- else
- s = format (s, " dynamic translation\n");
-
- return s;
-}
-
-u8 * format_snat_user (u8 * s, va_list * args)
-{
- snat_main_per_thread_data_t * sm = va_arg (*args, snat_main_per_thread_data_t *);
- snat_user_t * u = va_arg (*args, snat_user_t *);
- int verbose = va_arg (*args, int);
- dlist_elt_t * head, * elt;
- u32 elt_index, head_index;
- u32 session_index;
- snat_session_t * sess;
-
- s = format (s, "%U: %d dynamic translations, %d static translations\n",
- format_ip4_address, &u->addr, u->nsessions, u->nstaticsessions);
-
- if (verbose == 0)
- return s;
-
- if (u->nsessions || u->nstaticsessions)
- {
- head_index = u->sessions_per_user_list_head_index;
- head = pool_elt_at_index (sm->list_pool, head_index);
-
- elt_index = head->next;
- elt = pool_elt_at_index (sm->list_pool, elt_index);
- session_index = elt->value;
-
- while (session_index != ~0)
- {
- sess = pool_elt_at_index (sm->sessions, session_index);
-
- s = format (s, " %U\n", format_snat_session, sm, sess);
-
- elt_index = elt->next;
- elt = pool_elt_at_index (sm->list_pool, elt_index);
- session_index = elt->value;
- }
- }
-
- return s;
-}
-
-u8 * format_snat_static_mapping (u8 * s, va_list * args)
-{
- snat_static_mapping_t *m = va_arg (*args, snat_static_mapping_t *);
-
- if (m->addr_only)
- s = format (s, "local %U external %U vrf %d",
- format_ip4_address, &m->local_addr,
- format_ip4_address, &m->external_addr,
- m->vrf_id);
- else
- s = format (s, "%U local %U:%d external %U:%d vrf %d",
- format_snat_protocol, m->proto,
- format_ip4_address, &m->local_addr, m->local_port,
- format_ip4_address, &m->external_addr, m->external_port,
- m->vrf_id);
-
- return s;
-}
-
-u8 * format_snat_static_map_to_resolve (u8 * s, va_list * args)
-{
- snat_static_map_resolve_t *m = va_arg (*args, snat_static_map_resolve_t *);
- vnet_main_t *vnm = vnet_get_main();
-
- if (m->addr_only)
- s = format (s, "local %U external %U vrf %d",
- format_ip4_address, &m->l_addr,
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, m->sw_if_index),
- m->vrf_id);
- else
- s = format (s, "%U local %U:%d external %U:%d vrf %d",
- format_snat_protocol, m->proto,
- format_ip4_address, &m->l_addr, m->l_port,
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, m->sw_if_index), m->e_port,
- m->vrf_id);
-
- return s;
-}
-
-u8 * format_det_map_ses (u8 * s, va_list * args)
-{
- snat_det_map_t * det_map = va_arg (*args, snat_det_map_t *);
- ip4_address_t in_addr, out_addr;
- u32 in_offset, out_offset;
- snat_det_session_t * ses = va_arg (*args, snat_det_session_t *);
- u32 * i = va_arg (*args, u32 *);
-
- u32 user_index = *i / SNAT_DET_SES_PER_USER;
- in_addr.as_u32 = clib_host_to_net_u32 (
- clib_net_to_host_u32(det_map->in_addr.as_u32) + user_index);
- in_offset = clib_net_to_host_u32(in_addr.as_u32) -
- clib_net_to_host_u32(det_map->in_addr.as_u32);
- out_offset = in_offset / det_map->sharing_ratio;
- out_addr.as_u32 = clib_host_to_net_u32(
- clib_net_to_host_u32(det_map->out_addr.as_u32) + out_offset);
- s = format (s, "in %U:%d out %U:%d external host %U:%d state: %U expire: %d\n",
- format_ip4_address, &in_addr,
- clib_net_to_host_u16 (ses->in_port),
- format_ip4_address, &out_addr,
- clib_net_to_host_u16 (ses->out.out_port),
- format_ip4_address, &ses->out.ext_host_addr,
- clib_net_to_host_u16 (ses->out.ext_host_port),
- format_snat_session_state, ses->state,
- ses->expire);
-
- return s;
-}
-
-static clib_error_t *
-show_snat_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- int verbose = 0;
- snat_main_t * sm = &snat_main;
- snat_user_t * u;
- snat_static_mapping_t *m;
- snat_interface_t *i;
- snat_address_t * ap;
- vnet_main_t *vnm = vnet_get_main();
- snat_main_per_thread_data_t *tsm;
- u32 users_num = 0, sessions_num = 0, *worker, *sw_if_index;
- uword j = 0;
- snat_static_map_resolve_t *rp;
- snat_det_map_t * dm;
- snat_det_session_t * ses;
-
- if (unformat (input, "detail"))
- verbose = 1;
- else if (unformat (input, "verbose"))
- verbose = 2;
-
- if (sm->static_mapping_only)
- {
- if (sm->static_mapping_connection_tracking)
- vlib_cli_output (vm, "SNAT mode: static mapping only connection "
- "tracking");
- else
- vlib_cli_output (vm, "SNAT mode: static mapping only");
- }
- else if (sm->deterministic)
- {
- vlib_cli_output (vm, "SNAT mode: deterministic mapping");
- }
- else
- {
- vlib_cli_output (vm, "SNAT mode: dynamic translations enabled");
- }
-
- if (verbose > 0)
- {
- pool_foreach (i, sm->interfaces,
- ({
- vlib_cli_output (vm, "%U %s", format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, i->sw_if_index),
- i->is_inside ? "in" : "out");
- }));
-
- pool_foreach (i, sm->output_feature_interfaces,
- ({
- vlib_cli_output (vm, "%U output-feature %s",
- format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, i->sw_if_index),
- i->is_inside ? "in" : "out");
- }));
-
- if (vec_len (sm->auto_add_sw_if_indices))
- {
- vlib_cli_output (vm, "SNAT pool addresses interfaces:");
- vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
- {
- vlib_cli_output (vm, "%U", format_vnet_sw_interface_name, vnm,
- vnet_get_sw_interface (vnm, *sw_if_index));
- }
- }
-
- vec_foreach (ap, sm->addresses)
- {
- vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
- if (ap->fib_index != ~0)
- vlib_cli_output (vm, " tenant VRF: %u",
- ip4_fib_get(ap->fib_index)->table_id);
- else
- vlib_cli_output (vm, " tenant VRF independent");
-#define _(N, i, n, s) \
- vlib_cli_output (vm, " %d busy %s ports", ap->busy_##n##_ports, s);
- foreach_snat_protocol
-#undef _
- }
- }
-
- if (sm->num_workers > 1)
- {
- vlib_cli_output (vm, "%d workers", vec_len (sm->workers));
- if (verbose > 0)
- {
- vec_foreach (worker, sm->workers)
- {
- vlib_worker_thread_t *w =
- vlib_worker_threads + *worker + sm->first_worker_index;
- vlib_cli_output (vm, " %s", w->name);
- }
- }
- }
-
- if (sm->deterministic)
- {
- vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
- vlib_cli_output (vm, "tcp-established timeout: %dsec",
- sm->tcp_established_timeout);
- vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
- sm->tcp_transitory_timeout);
- vlib_cli_output (vm, "icmp timeout: %dsec", sm->icmp_timeout);
- vlib_cli_output (vm, "%d deterministic mappings",
- pool_elts (sm->det_maps));
- if (verbose > 0)
- {
- pool_foreach (dm, sm->det_maps,
- ({
- vlib_cli_output (vm, "in %U/%d out %U/%d\n",
- format_ip4_address, &dm->in_addr, dm->in_plen,
- format_ip4_address, &dm->out_addr, dm->out_plen);
- vlib_cli_output (vm, " outside address sharing ratio: %d\n",
- dm->sharing_ratio);
- vlib_cli_output (vm, " number of ports per inside host: %d\n",
- dm->ports_per_host);
- vlib_cli_output (vm, " sessions number: %d\n", dm->ses_num);
- if (verbose > 1)
- {
- vec_foreach_index (j, dm->sessions)
- {
- ses = vec_elt_at_index (dm->sessions, j);
- if (ses->in_port)
- vlib_cli_output (vm, " %U", format_det_map_ses, dm, ses,
- &j);
- }
- }
- }));
- }
- }
- else
- {
- if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
- {
- vlib_cli_output (vm, "%d static mappings",
- pool_elts (sm->static_mappings));
-
- if (verbose > 0)
- {
- pool_foreach (m, sm->static_mappings,
- ({
- vlib_cli_output (vm, "%U", format_snat_static_mapping, m);
- }));
- }
- }
- else
- {
- vec_foreach (tsm, sm->per_thread_data)
- {
- users_num += pool_elts (tsm->users);
- sessions_num += pool_elts (tsm->sessions);
- }
-
- vlib_cli_output (vm, "%d users, %d outside addresses, %d active sessions,"
- " %d static mappings",
- users_num,
- vec_len (sm->addresses),
- sessions_num,
- pool_elts (sm->static_mappings));
-
- if (verbose > 0)
- {
- vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->in2out,
- verbose - 1);
- vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->out2in,
- verbose - 1);
- vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->worker_by_in,
- verbose - 1);
- vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->worker_by_out,
- verbose - 1);
- vec_foreach_index (j, sm->per_thread_data)
- {
- tsm = vec_elt_at_index (sm->per_thread_data, j);
-
- if (pool_elts (tsm->users) == 0)
- continue;
-
- vlib_worker_thread_t *w = vlib_worker_threads + j;
- vlib_cli_output (vm, "Thread %d (%s at lcore %u):", j, w->name,
- w->lcore_id);
- vlib_cli_output (vm, " %d list pool elements",
- pool_elts (tsm->list_pool));
-
- pool_foreach (u, tsm->users,
- ({
- vlib_cli_output (vm, " %U", format_snat_user, tsm, u,
- verbose - 1);
- }));
- }
-
- if (pool_elts (sm->static_mappings))
- {
- vlib_cli_output (vm, "static mappings:");
- pool_foreach (m, sm->static_mappings,
- ({
- vlib_cli_output (vm, "%U", format_snat_static_mapping, m);
- }));
- for (j = 0; j < vec_len (sm->to_resolve); j++)
- {
- rp = sm->to_resolve + j;
- vlib_cli_output (vm, "%U",
- format_snat_static_map_to_resolve, rp);
- }
- }
- }
- }
- }
- return 0;
-}
-
-VLIB_CLI_COMMAND (show_snat_command, static) = {
- .path = "show snat",
- .short_help = "show snat",
- .function = show_snat_command_fn,
-};
-
-
-static void
-snat_ip4_add_del_interface_address_cb (ip4_main_t * im,
- uword opaque,
- u32 sw_if_index,
- ip4_address_t * address,
- u32 address_length,
- u32 if_address_index,
- u32 is_delete)
-{
- snat_main_t *sm = &snat_main;
- snat_static_map_resolve_t *rp;
- u32 *indices_to_delete = 0;
- int i, j;
- int rv;
-
- for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
- {
- if (sw_if_index == sm->auto_add_sw_if_indices[i])
- {
- if (!is_delete)
- {
- /* Don't trip over lease renewal, static config */
- for (j = 0; j < vec_len(sm->addresses); j++)
- if (sm->addresses[j].addr.as_u32 == address->as_u32)
- return;
-
- snat_add_address (sm, address, ~0);
- /* Scan static map resolution vector */
- for (j = 0; j < vec_len (sm->to_resolve); j++)
- {
- rp = sm->to_resolve + j;
- /* On this interface? */
- if (rp->sw_if_index == sw_if_index)
- {
- /* Add the static mapping */
- rv = snat_add_static_mapping (rp->l_addr,
- address[0],
- rp->l_port,
- rp->e_port,
- rp->vrf_id,
- rp->addr_only,
- ~0 /* sw_if_index */,
- rp->proto,
- rp->is_add);
- if (rv)
- clib_warning ("snat_add_static_mapping returned %d",
- rv);
- vec_add1 (indices_to_delete, j);
- }
- }
- /* If we resolved any of the outstanding static mappings */
- if (vec_len(indices_to_delete))
- {
- /* Delete them */
- for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
- vec_delete(sm->to_resolve, 1, j);
- vec_free(indices_to_delete);
- }
- return;
- }
- else
- {
- (void) snat_del_address(sm, address[0], 1);
- return;
- }
- }
- }
-}
-
-
-int snat_add_interface_address (snat_main_t *sm, u32 sw_if_index, int is_del)
-{
- ip4_main_t * ip4_main = sm->ip4_main;
- ip4_address_t * first_int_addr;
- snat_static_map_resolve_t *rp;
- u32 *indices_to_delete = 0;
- int i, j;
-
- first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index,
- 0 /* just want the address*/);
-
- for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
- {
- if (sm->auto_add_sw_if_indices[i] == sw_if_index)
- {
- if (is_del)
- {
- /* if have address remove it */
- if (first_int_addr)
- (void) snat_del_address (sm, first_int_addr[0], 1);
- else
- {
- for (j = 0; j < vec_len (sm->to_resolve); j++)
- {
- rp = sm->to_resolve + j;
- if (rp->sw_if_index == sw_if_index)
- vec_add1 (indices_to_delete, j);
- }
- if (vec_len(indices_to_delete))
- {
- for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
- vec_del1(sm->to_resolve, j);
- vec_free(indices_to_delete);
- }
- }
- vec_del1(sm->auto_add_sw_if_indices, i);
- }
- else
- return VNET_API_ERROR_VALUE_EXIST;
-
- return 0;
- }
- }
-
- if (is_del)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- /* add to the auto-address list */
- vec_add1(sm->auto_add_sw_if_indices, sw_if_index);
-
- /* If the address is already bound - or static - add it now */
- if (first_int_addr)
- snat_add_address (sm, first_int_addr, ~0);
-
- return 0;
-}
-
-static clib_error_t *
-snat_add_interface_address_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- snat_main_t *sm = &snat_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- u32 sw_if_index;
- int rv;
- int is_del = 0;
- clib_error_t *error = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "%U", unformat_vnet_sw_interface,
- sm->vnet_main, &sw_if_index))
- ;
- else if (unformat (line_input, "del"))
- is_del = 1;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- rv = snat_add_interface_address (sm, sw_if_index, is_del);
-
- switch (rv)
- {
- case 0:
- break;
-
- default:
- error = clib_error_return (0, "snat_add_interface_address returned %d",
- rv);
- goto done;
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
- .path = "snat add interface address",
- .short_help = "snat add interface address <interface> [del]",
- .function = snat_add_interface_address_command_fn,
-};
-
-static clib_error_t *
-snat_det_map_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- snat_main_t *sm = &snat_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- ip4_address_t in_addr, out_addr;
- u32 in_plen, out_plen;
- int is_add = 1, rv;
- clib_error_t *error = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "in %U/%u", unformat_ip4_address, &in_addr, &in_plen))
- ;
- else if (unformat (line_input, "out %U/%u", unformat_ip4_address, &out_addr, &out_plen))
- ;
- else if (unformat (line_input, "del"))
- is_add = 0;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- unformat_free (line_input);
-
- rv = snat_det_add_map(sm, &in_addr, (u8) in_plen, &out_addr, (u8)out_plen,
- is_add);
-
- if (rv)
- {
- error = clib_error_return (0, "snat_det_add_map return %d", rv);
- goto done;
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-/*?
- * @cliexpar
- * @cliexstart{snat deterministic add}
- * Create bijective mapping of inside address to outside address and port range
- * pairs, with the purpose of enabling deterministic NAT to reduce logging in
- * CGN deployments.
- * To create deterministic mapping between inside network 10.0.0.0/18 and
- * outside network 1.1.1.0/30 use:
- * # vpp# snat deterministic add in 10.0.0.0/18 out 1.1.1.0/30
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (snat_det_map_command, static) = {
- .path = "snat deterministic add",
- .short_help = "snat deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
- .function = snat_det_map_command_fn,
-};
-
-static clib_error_t *
-snat_det_forward_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- snat_main_t *sm = &snat_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- ip4_address_t in_addr, out_addr;
- u16 lo_port;
- snat_det_map_t * dm;
- clib_error_t *error = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "%U", unformat_ip4_address, &in_addr))
- ;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- unformat_free (line_input);
-
- dm = snat_det_map_by_user(sm, &in_addr);
- if (!dm)
- vlib_cli_output (vm, "no match");
- else
- {
- snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
- vlib_cli_output (vm, "%U:<%d-%d>", format_ip4_address, &out_addr,
- lo_port, lo_port + dm->ports_per_host - 1);
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-/*?
- * @cliexpar
- * @cliexstart{snat deterministic forward}
- * Return outside address and port range from inside address for deterministic
- * NAT.
- * To obtain outside address and port of inside host use:
- * vpp# snat deterministic forward 10.0.0.2
- * 1.1.1.0:<1054-1068>
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (snat_det_forward_command, static) = {
- .path = "snat deterministic forward",
- .short_help = "snat deterministic forward <addr>",
- .function = snat_det_forward_command_fn,
-};
-
-static clib_error_t *
-snat_det_reverse_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- snat_main_t *sm = &snat_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- ip4_address_t in_addr, out_addr;
- u32 out_port;
- snat_det_map_t * dm;
- clib_error_t *error = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "%U:%d", unformat_ip4_address, &out_addr, &out_port))
- ;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- }
- }
-
- unformat_free (line_input);
-
- if (out_port < 1024 || out_port > 65535)
- {
- error = clib_error_return (0, "wrong port, must be <1024-65535>");
- goto done;
- }
-
- dm = snat_det_map_by_out(sm, &out_addr);
- if (!dm)
- vlib_cli_output (vm, "no match");
- else
- {
- snat_det_reverse (dm, &out_addr, (u16) out_port, &in_addr);
- vlib_cli_output (vm, "%U", format_ip4_address, &in_addr);
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-/*?
- * @cliexpar
- * @cliexstart{snat deterministic reverse}
- * Return inside address from outside address and port for deterministic NAT.
- * To obtain inside host address from outside address and port use:
- * #vpp snat deterministic reverse 1.1.1.1:1276
- * 10.0.16.16
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (snat_det_reverse_command, static) = {
- .path = "snat deterministic reverse",
- .short_help = "snat deterministic reverse <addr>:<port>",
- .function = snat_det_reverse_command_fn,
-};
-
-static clib_error_t *
-set_timeout_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- snat_main_t *sm = &snat_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- clib_error_t *error = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "udp %u", &sm->udp_timeout))
- ;
- else if (unformat (line_input, "tcp-established %u",
- &sm->tcp_established_timeout))
- ;
- else if (unformat (line_input, "tcp-transitory %u",
- &sm->tcp_transitory_timeout))
- ;
- else if (unformat (line_input, "icmp %u", &sm->icmp_timeout))
- ;
- else if (unformat (line_input, "reset"))
- {
- sm->udp_timeout = SNAT_UDP_TIMEOUT;
- sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
- sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
- sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
- }
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- unformat_free (line_input);
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-/*?
- * @cliexpar
- * @cliexstart{set snat deterministic timeout}
- * Set values of timeouts for deterministic NAT (in seconds), use:
- * vpp# set snat deterministic timeout udp 120 tcp-established 7500
- * tcp-transitory 250 icmp 90
- * To reset default values use:
- * vpp# set snat deterministic timeout reset
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (set_timeout_command, static) = {
- .path = "set snat deterministic timeout",
- .function = set_timeout_command_fn,
- .short_help =
- "set snat deterministic timeout [udp <sec> | tcp-established <sec> "
- "tcp-transitory <sec> | icmp <sec> | reset]",
-};
-
-static clib_error_t *
-snat_det_close_session_out_fn (vlib_main_t *vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- snat_main_t *sm = &snat_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- ip4_address_t out_addr, ext_addr, in_addr;
- u16 out_port, ext_port;
- snat_det_map_t * dm;
- snat_det_session_t * ses;
- snat_det_out_key_t key;
- clib_error_t *error = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "%U:%d %U:%d",
- unformat_ip4_address, &out_addr, &out_port,
- unformat_ip4_address, &ext_addr, &ext_port))
- ;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- unformat_free (line_input);
-
- dm = snat_det_map_by_out(sm, &out_addr);
- if (!dm)
- vlib_cli_output (vm, "no match");
- else
- {
- snat_det_reverse(dm, &ext_addr, out_port, &in_addr);
- key.ext_host_addr = out_addr;
- key.ext_host_port = ntohs(ext_port);
- key.out_port = ntohs(out_port);
- ses = snat_det_get_ses_by_out(dm, &out_addr, key.as_u64);
- if (!ses)
- vlib_cli_output (vm, "no match");
- else
- snat_det_ses_close(dm, ses);
- }
-
-done:
- unformat_free (line_input);
-
- return error;
-}
-
-/*?
- * @cliexpar
- * @cliexstart{snat deterministic close session out}
- * Close session using outside ip address and port
- * and external ip address and port, use:
- * vpp# snat deterministic close session out 1.1.1.1:1276 2.2.2.2:2387
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (snat_det_close_sesion_out_command, static) = {
- .path = "snat deterministic close session out",
- .short_help = "snat deterministic close session out "
- "<out_addr>:<out_port> <ext_addr>:<ext_port>",
- .function = snat_det_close_session_out_fn,
-};
-
-static clib_error_t *
-snat_det_close_session_in_fn (vlib_main_t *vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- snat_main_t *sm = &snat_main;
- unformat_input_t _line_input, *line_input = &_line_input;
- ip4_address_t in_addr, ext_addr;
- u16 in_port, ext_port;
- snat_det_map_t * dm;
- snat_det_session_t * ses;
- snat_det_out_key_t key;
- clib_error_t *error = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "%U:%d %U:%d",
- unformat_ip4_address, &in_addr, &in_port,
- unformat_ip4_address, &ext_addr, &ext_port))
- ;
- else
- {
- error = clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- goto done;
- }
- }
-
- unformat_free (line_input);
-
- dm = snat_det_map_by_user (sm, &in_addr);
- if (!dm)
- vlib_cli_output (vm, "no match");
- else
- {
- key.ext_host_addr = ext_addr;
- key.ext_host_port = ntohs (ext_port);
- ses = snat_det_find_ses_by_in (dm, &in_addr, ntohs(in_port), key);
- if (!ses)
- vlib_cli_output (vm, "no match");
- else
- snat_det_ses_close(dm, ses);
- }
-
-done:
- unformat_free(line_input);
-
- return error;
-}
-
-/*?
- * @cliexpar
- * @cliexstart{snat deterministic close_session_in}
- * Close session using inside ip address and port
- * and external ip address and port, use:
- * vpp# snat deterministic close session in 3.3.3.3:3487 2.2.2.2:2387
- * @cliexend
-?*/
-VLIB_CLI_COMMAND (snat_det_close_session_in_command, static) = {
- .path = "snat deterministic close session in",
- .short_help = "snat deterministic close session in "
- "<in_addr>:<in_port> <ext_addr>:<ext_port>",
- .function = snat_det_close_session_in_fn,
-};
diff --git a/src/plugins/snat/snat.h b/src/plugins/snat/snat.h
deleted file mode 100644
index aa0f82fc9df..00000000000
--- a/src/plugins/snat/snat.h
+++ /dev/null
@@ -1,541 +0,0 @@
-
-/*
- * snat.h - simple nat definitions
- *
- * 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.
- */
-#ifndef __included_snat_h__
-#define __included_snat_h__
-
-#include <vnet/vnet.h>
-#include <vnet/ip/ip.h>
-#include <vnet/ethernet/ethernet.h>
-#include <vnet/ip/icmp46_packet.h>
-#include <vnet/api_errno.h>
-#include <vppinfra/bihash_8_8.h>
-#include <vppinfra/bihash_16_8.h>
-#include <vppinfra/dlist.h>
-#include <vppinfra/error.h>
-#include <vlibapi/api.h>
-
-
-#define SNAT_UDP_TIMEOUT 300
-#define SNAT_UDP_TIMEOUT_MIN 120
-#define SNAT_TCP_TRANSITORY_TIMEOUT 240
-#define SNAT_TCP_ESTABLISHED_TIMEOUT 7440
-#define SNAT_TCP_INCOMING_SYN 6
-#define SNAT_ICMP_TIMEOUT 60
-
-#define SNAT_FLAG_HAIRPINNING (1 << 0)
-
-/* Key */
-typedef struct {
- union
- {
- struct
- {
- ip4_address_t addr;
- u16 port;
- u16 protocol:3,
- fib_index:13;
- };
- u64 as_u64;
- };
-} snat_session_key_t;
-
-typedef struct {
- union
- {
- struct
- {
- ip4_address_t l_addr;
- ip4_address_t r_addr;
- u32 fib_index;
- u8 proto;
- u8 rsvd[3];
- };
- u64 as_u64[2];
- };
-} snat_unk_proto_ses_key_t;
-
-typedef struct {
- union
- {
- struct
- {
- ip4_address_t ext_host_addr;
- u16 ext_host_port;
- u16 out_port;
- };
- u64 as_u64;
- };
-} snat_det_out_key_t;
-
-typedef struct {
- union
- {
- struct
- {
- ip4_address_t addr;
- u32 fib_index;
- };
- u64 as_u64;
- };
-} snat_user_key_t;
-
-typedef struct {
- union
- {
- struct
- {
- ip4_address_t addr;
- u16 port;
- u16 fib_index;
- };
- u64 as_u64;
- };
-} snat_worker_key_t;
-
-
-#define foreach_snat_protocol \
- _(UDP, 0, udp, "udp") \
- _(TCP, 1, tcp, "tcp") \
- _(ICMP, 2, icmp, "icmp")
-
-typedef enum {
-#define _(N, i, n, s) SNAT_PROTOCOL_##N = i,
- foreach_snat_protocol
-#undef _
-} snat_protocol_t;
-
-
-#define foreach_snat_session_state \
- _(0, UNKNOWN, "unknown") \
- _(1, UDP_ACTIVE, "udp-active") \
- _(2, TCP_SYN_SENT, "tcp-syn-sent") \
- _(3, TCP_ESTABLISHED, "tcp-established") \
- _(4, TCP_FIN_WAIT, "tcp-fin-wait") \
- _(5, TCP_CLOSE_WAIT, "tcp-close-wait") \
- _(6, TCP_LAST_ACK, "tcp-last-ack") \
- _(7, ICMP_ACTIVE, "icmp-active")
-
-typedef enum {
-#define _(v, N, s) SNAT_SESSION_##N = v,
- foreach_snat_session_state
-#undef _
-} snat_session_state_t;
-
-
-#define SNAT_SESSION_FLAG_STATIC_MAPPING 1
-#define SNAT_SESSION_FLAG_UNKNOWN_PROTO 2
-
-typedef CLIB_PACKED(struct {
- snat_session_key_t out2in; /* 0-15 */
-
- snat_session_key_t in2out; /* 16-31 */
-
- u32 flags; /* 32-35 */
-
- /* per-user translations */
- u32 per_user_index; /* 36-39 */
-
- u32 per_user_list_head_index; /* 40-43 */
-
- /* Last heard timer */
- f64 last_heard; /* 44-51 */
-
- u64 total_bytes; /* 52-59 */
-
- u32 total_pkts; /* 60-63 */
-
- /* Outside address */
- u32 outside_address_index; /* 64-67 */
-
- /* External host address */
- ip4_address_t ext_host_addr; /* 68-71 */
-
-}) snat_session_t;
-
-
-typedef struct {
- ip4_address_t addr;
- u32 fib_index;
- u32 sessions_per_user_list_head_index;
- u32 nsessions;
- u32 nstaticsessions;
-} snat_user_t;
-
-typedef struct {
- ip4_address_t addr;
- u32 fib_index;
-#define _(N, i, n, s) \
- u32 busy_##n##_ports; \
- uword * busy_##n##_port_bitmap;
- foreach_snat_protocol
-#undef _
-} snat_address_t;
-
-typedef struct {
- u16 in_port;
- snat_det_out_key_t out;
- u8 state;
- u32 expire;
-} snat_det_session_t;
-
-typedef struct {
- ip4_address_t in_addr;
- u8 in_plen;
- ip4_address_t out_addr;
- u8 out_plen;
- u32 sharing_ratio;
- u16 ports_per_host;
- u32 ses_num;
- /* vector of sessions */
- snat_det_session_t * sessions;
-} snat_det_map_t;
-
-typedef struct {
- ip4_address_t local_addr;
- ip4_address_t external_addr;
- u16 local_port;
- u16 external_port;
- u8 addr_only;
- u32 vrf_id;
- u32 fib_index;
- snat_protocol_t proto;
-} snat_static_mapping_t;
-
-typedef struct {
- u32 sw_if_index;
- u8 is_inside;
-} snat_interface_t;
-
-typedef struct {
- ip4_address_t l_addr;
- u16 l_port;
- u16 e_port;
- u32 sw_if_index;
- u32 vrf_id;
- snat_protocol_t proto;
- int addr_only;
- int is_add;
-} snat_static_map_resolve_t;
-
-typedef struct {
- /* User pool */
- snat_user_t * users;
-
- /* Session pool */
- snat_session_t * sessions;
-
- /* Pool of doubly-linked list elements */
- dlist_elt_t * list_pool;
-
- u32 snat_thread_index;
-} snat_main_per_thread_data_t;
-
-struct snat_main_s;
-
-typedef u32 snat_icmp_match_function_t (struct snat_main_s *sm,
- vlib_node_runtime_t *node,
- u32 thread_index,
- vlib_buffer_t *b0,
- u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate,
- void *d,
- void *e);
-
-typedef u32 (snat_get_worker_function_t) (ip4_header_t * ip, u32 rx_fib_index);
-
-typedef struct snat_main_s {
- /* Main lookup tables */
- clib_bihash_8_8_t out2in;
- clib_bihash_8_8_t in2out;
-
- /* Unknown protocol sessions lookup tables */
- clib_bihash_16_8_t out2in_unk_proto;
- clib_bihash_16_8_t in2out_unk_proto;
-
- /* Find-a-user => src address lookup */
- clib_bihash_8_8_t user_hash;
-
- /* Non-translated packets worker lookup => src address + VRF */
- clib_bihash_8_8_t worker_by_in;
-
- /* Translated packets worker lookup => IP address + port number */
- clib_bihash_8_8_t worker_by_out;
-
- snat_icmp_match_function_t * icmp_match_in2out_cb;
- snat_icmp_match_function_t * icmp_match_out2in_cb;
-
- u32 num_workers;
- u32 first_worker_index;
- u32 next_worker;
- u32 * workers;
- snat_get_worker_function_t * worker_in2out_cb;
- snat_get_worker_function_t * worker_out2in_cb;
- u16 port_per_thread;
- u32 num_snat_thread;
-
- /* Per thread data */
- snat_main_per_thread_data_t * per_thread_data;
-
- /* Find a static mapping by local */
- clib_bihash_8_8_t static_mapping_by_local;
-
- /* Find a static mapping by external */
- clib_bihash_8_8_t static_mapping_by_external;
-
- /* Static mapping pool */
- snat_static_mapping_t * static_mappings;
-
- /* Interface pool */
- snat_interface_t * interfaces;
- snat_interface_t * output_feature_interfaces;
-
- /* Vector of outside addresses */
- snat_address_t * addresses;
-
- /* sw_if_indices whose intfc addresses should be auto-added */
- u32 * auto_add_sw_if_indices;
-
- /* vector of interface address static mappings to resolve. */
- snat_static_map_resolve_t *to_resolve;
-
- /* Randomize port allocation order */
- u32 random_seed;
-
- /* Worker handoff index */
- u32 fq_in2out_index;
- u32 fq_in2out_output_index;
- u32 fq_out2in_index;
-
- /* in2out and out2in node index */
- u32 in2out_node_index;
- u32 in2out_output_node_index;
- u32 out2in_node_index;
-
- /* Deterministic NAT */
- snat_det_map_t * det_maps;
-
- /* Config parameters */
- u8 static_mapping_only;
- u8 static_mapping_connection_tracking;
- u8 deterministic;
- u32 translation_buckets;
- u32 translation_memory_size;
- u32 user_buckets;
- u32 user_memory_size;
- u32 max_translations_per_user;
- u32 outside_vrf_id;
- u32 outside_fib_index;
- u32 inside_vrf_id;
- u32 inside_fib_index;
-
- /* tenant VRF aware address pool activation flag */
- u8 vrf_mode;
-
- /* values of various timeouts */
- u32 udp_timeout;
- u32 tcp_established_timeout;
- u32 tcp_transitory_timeout;
- u32 icmp_timeout;
-
- /* API message ID base */
- u16 msg_id_base;
-
- /* convenience */
- vlib_main_t * vlib_main;
- vnet_main_t * vnet_main;
- ip4_main_t * ip4_main;
- ip_lookup_main_t * ip4_lookup_main;
- api_main_t * api_main;
-} snat_main_t;
-
-extern snat_main_t snat_main;
-extern vlib_node_registration_t snat_in2out_node;
-extern vlib_node_registration_t snat_in2out_output_node;
-extern vlib_node_registration_t snat_out2in_node;
-extern vlib_node_registration_t snat_in2out_fast_node;
-extern vlib_node_registration_t snat_out2in_fast_node;
-extern vlib_node_registration_t snat_in2out_worker_handoff_node;
-extern vlib_node_registration_t snat_in2out_output_worker_handoff_node;
-extern vlib_node_registration_t snat_out2in_worker_handoff_node;
-extern vlib_node_registration_t snat_det_in2out_node;
-extern vlib_node_registration_t snat_det_out2in_node;
-extern vlib_node_registration_t snat_hairpin_dst_node;
-extern vlib_node_registration_t snat_hairpin_src_node;
-
-void snat_free_outside_address_and_port (snat_main_t * sm,
- snat_session_key_t * k,
- u32 address_index);
-
-int snat_alloc_outside_address_and_port (snat_main_t * sm,
- u32 fib_index,
- u32 thread_index,
- snat_session_key_t * k,
- u32 * address_indexp);
-
-int snat_static_mapping_match (snat_main_t * sm,
- snat_session_key_t match,
- snat_session_key_t * mapping,
- u8 by_external,
- u8 *is_addr_only);
-
-void snat_add_del_addr_to_fib (ip4_address_t * addr,
- u8 p_len,
- u32 sw_if_index,
- int is_add);
-
-format_function_t format_snat_user;
-
-typedef struct {
- u32 cached_sw_if_index;
- u32 cached_ip4_address;
-} snat_runtime_t;
-
-/** \brief Check if SNAT session is created from static mapping.
- @param s SNAT session
- @return 1 if SNAT session is created from static mapping otherwise 0
-*/
-#define snat_is_session_static(s) s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING
-
-/** \brief Check if SNAT session for unknown protocol.
- @param s SNAT session
- @return 1 if SNAT session for unknown protocol otherwise 0
-*/
-#define snat_is_unk_proto_session(s) s->flags & SNAT_SESSION_FLAG_UNKNOWN_PROTO
-
-/*
- * Why is this here? Because we don't need to touch this layer to
- * simply reply to an icmp. We need to change id to a unique
- * value to NAT an echo request/reply.
- */
-
-typedef struct {
- u16 identifier;
- u16 sequence;
-} icmp_echo_header_t;
-
-always_inline u32
-ip_proto_to_snat_proto (u8 ip_proto)
-{
- u32 snat_proto = ~0;
-
- snat_proto = (ip_proto == IP_PROTOCOL_UDP) ? SNAT_PROTOCOL_UDP : snat_proto;
- snat_proto = (ip_proto == IP_PROTOCOL_TCP) ? SNAT_PROTOCOL_TCP : snat_proto;
- snat_proto = (ip_proto == IP_PROTOCOL_ICMP) ? SNAT_PROTOCOL_ICMP : snat_proto;
- snat_proto = (ip_proto == IP_PROTOCOL_ICMP6) ? SNAT_PROTOCOL_ICMP : snat_proto;
-
- return snat_proto;
-}
-
-always_inline u8
-snat_proto_to_ip_proto (snat_protocol_t snat_proto)
-{
- u8 ip_proto = ~0;
-
- ip_proto = (snat_proto == SNAT_PROTOCOL_UDP) ? IP_PROTOCOL_UDP : ip_proto;
- ip_proto = (snat_proto == SNAT_PROTOCOL_TCP) ? IP_PROTOCOL_TCP : ip_proto;
- ip_proto = (snat_proto == SNAT_PROTOCOL_ICMP) ? IP_PROTOCOL_ICMP : ip_proto;
-
- return ip_proto;
-}
-
-typedef struct {
- u16 src_port, dst_port;
-} tcp_udp_header_t;
-
-u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e);
-u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e);
-u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e);
-u32 icmp_match_out2in_fast(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e);
-u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e);
-u32 icmp_match_out2in_det(snat_main_t *sm, vlib_node_runtime_t *node,
- u32 thread_index, vlib_buffer_t *b0, u8 *p_proto,
- snat_session_key_t *p_value,
- u8 *p_dont_translate, void *d, void *e);
-void increment_v4_address(ip4_address_t * a);
-void snat_add_address(snat_main_t *sm, ip4_address_t *addr, u32 vrf_id);
-int snat_del_address(snat_main_t *sm, ip4_address_t addr, u8 delete_sm);
-int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
- u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
- u32 sw_if_index, snat_protocol_t proto, int is_add);
-clib_error_t * snat_api_init(vlib_main_t * vm, snat_main_t * sm);
-int snat_set_workers (uword * bitmap);
-int snat_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del);
-int snat_interface_add_del_output_feature(u32 sw_if_index, u8 is_inside,
- int is_del);
-int snat_add_interface_address(snat_main_t *sm, u32 sw_if_index, int is_del);
-uword unformat_snat_protocol(unformat_input_t * input, va_list * args);
-u8 * format_snat_protocol(u8 * s, va_list * args);
-
-static_always_inline u8
-icmp_is_error_message (icmp46_header_t * icmp)
-{
- switch(icmp->type)
- {
- case ICMP4_destination_unreachable:
- case ICMP4_time_exceeded:
- case ICMP4_parameter_problem:
- case ICMP4_source_quench:
- case ICMP4_redirect:
- case ICMP4_alternate_host_address:
- return 1;
- }
- return 0;
-}
-
-static_always_inline u8
-is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0,
- u32 ip4_addr)
-{
- snat_runtime_t *rt = (snat_runtime_t *) node->runtime_data;
- ip4_address_t * first_int_addr;
-
- if (PREDICT_FALSE(rt->cached_sw_if_index != sw_if_index0))
- {
- first_int_addr =
- ip4_interface_first_address (sm->ip4_main, sw_if_index0,
- 0 /* just want the address */);
- rt->cached_sw_if_index = sw_if_index0;
- if (first_int_addr)
- rt->cached_ip4_address = first_int_addr->as_u32;
- else
- rt->cached_ip4_address = 0;
- }
-
- if (PREDICT_FALSE(ip4_addr == rt->cached_ip4_address))
- return 1;
- else
- return 0;
-}
-
-#endif /* __included_snat_h__ */
diff --git a/src/plugins/snat/snat_all_api_h.h b/src/plugins/snat/snat_all_api_h.h
deleted file mode 100644
index 490177008e0..00000000000
--- a/src/plugins/snat/snat_all_api_h.h
+++ /dev/null
@@ -1,19 +0,0 @@
-
-/*
- * snat_all_api_h.h - skeleton vpp engine plug-in api #include file
- *
- * Copyright (c) <current-year> <your-organization>
- * 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.
- */
-/* Include the generated file, see BUILT_SOURCES in Makefile.am */
-#include <snat/snat.api.h>
diff --git a/src/plugins/snat/snat_api.c b/src/plugins/snat/snat_api.c
deleted file mode 100644
index 227074f9cb4..00000000000
--- a/src/plugins/snat/snat_api.c
+++ /dev/null
@@ -1,1970 +0,0 @@
-/*
- * Copyright (c) 2017 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.
- */
-/**
- * @file
- * @brief SNAT plugin API implementation
- */
-
-#include <snat/snat.h>
-#include <snat/snat_det.h>
-#include <snat/nat64.h>
-#include <vlibapi/api.h>
-#include <vlibmemory/api.h>
-#include <vlibsocket/api.h>
-#include <snat/snat_msg_enum.h>
-#include <vnet/fib/fib_table.h>
-
-/* define message structures */
-#define vl_typedefs
-#include <snat/snat_all_api_h.h>
-#undef vl_typedefs
-
-/* define generated endian-swappers */
-#define vl_endianfun
-#include <snat/snat_all_api_h.h>
-#undef vl_endianfun
-
-#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
-
-#define REPLY_MSG_ID_BASE sm->msg_id_base
-#include <vlibapi/api_helper_macros.h>
-
-/* Get the API version number */
-#define vl_api_version(n,v) static u32 api_version=(v);
-#include <snat/snat_all_api_h.h>
-#undef vl_api_version
-
-/* Macro to finish up custom dump fns */
-#define FINISH \
- vec_add1 (s, 0); \
- vl_print (handle, (char *)s); \
- vec_free (s); \
- return handle;
-
-static void
- vl_api_snat_add_address_range_t_handler
- (vl_api_snat_add_address_range_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_add_address_range_reply_t *rmp;
- ip4_address_t this_addr;
- u32 start_host_order, end_host_order;
- u32 vrf_id;
- int i, count;
- int rv = 0;
- u32 *tmp;
-
- if (mp->is_ip4 != 1)
- {
- rv = VNET_API_ERROR_UNIMPLEMENTED;
- goto send_reply;
- }
-
- if (sm->static_mapping_only)
- {
- rv = VNET_API_ERROR_FEATURE_DISABLED;
- goto send_reply;
- }
-
- tmp = (u32 *) mp->first_ip_address;
- start_host_order = clib_host_to_net_u32 (tmp[0]);
- tmp = (u32 *) mp->last_ip_address;
- end_host_order = clib_host_to_net_u32 (tmp[0]);
-
- count = (end_host_order - start_host_order) + 1;
-
- vrf_id = clib_host_to_net_u32 (mp->vrf_id);
-
- if (count > 1024)
- clib_warning ("%U - %U, %d addresses...",
- format_ip4_address, mp->first_ip_address,
- format_ip4_address, mp->last_ip_address, count);
-
- memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
-
- for (i = 0; i < count; i++)
- {
- if (mp->is_add)
- snat_add_address (sm, &this_addr, vrf_id);
- else
- rv = snat_del_address (sm, this_addr, 0);
-
- if (rv)
- goto send_reply;
-
- increment_v4_address (&this_addr);
- }
-
-send_reply:
- REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
-}
-
-static void *vl_api_snat_add_address_range_t_print
- (vl_api_snat_add_address_range_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_add_address_range ");
- s = format (s, "%U ", format_ip4_address, mp->first_ip_address);
- if (memcmp (mp->first_ip_address, mp->last_ip_address, 4))
- {
- s = format (s, " - %U ", format_ip4_address, mp->last_ip_address);
- }
- FINISH;
-}
-
-static void
- send_snat_address_details
- (snat_address_t * a, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_snat_address_details_t *rmp;
- snat_main_t *sm = &snat_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_SNAT_ADDRESS_DETAILS + sm->msg_id_base);
- rmp->is_ip4 = 1;
- clib_memcpy (rmp->ip_address, &(a->addr), 4);
- if (a->fib_index != ~0)
- {
- fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP4);
- rmp->vrf_id = ntohl (fib->ft_table_id);
- }
- else
- rmp->vrf_id = ~0;
- rmp->context = context;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
-vl_api_snat_address_dump_t_handler (vl_api_snat_address_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- snat_main_t *sm = &snat_main;
- snat_address_t *a;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- /* *INDENT-OFF* */
- vec_foreach (a, sm->addresses)
- send_snat_address_details (a, q, mp->context);
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_address_dump_t_print
- (vl_api_snat_address_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_address_dump ");
-
- FINISH;
-}
-
-static void
- vl_api_snat_interface_add_del_feature_t_handler
- (vl_api_snat_interface_add_del_feature_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_interface_add_del_feature_reply_t *rmp;
- u8 is_del = mp->is_add == 0;
- u32 sw_if_index = ntohl (mp->sw_if_index);
- int rv = 0;
-
- VALIDATE_SW_IF_INDEX (mp);
-
- rv = snat_interface_add_del (sw_if_index, mp->is_inside, is_del);
-
- BAD_SW_IF_INDEX_LABEL;
-
- REPLY_MACRO (VL_API_SNAT_INTERFACE_ADD_DEL_FEATURE_REPLY);
-}
-
-static void *vl_api_snat_interface_add_del_feature_t_print
- (vl_api_snat_interface_add_del_feature_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_interface_add_del_feature ");
- s = format (s, "sw_if_index %d %s %s",
- clib_host_to_net_u32 (mp->sw_if_index),
- mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
-
- FINISH;
-}
-
-static void
- send_snat_interface_details
- (snat_interface_t * i, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_snat_interface_details_t *rmp;
- snat_main_t *sm = &snat_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_SNAT_INTERFACE_DETAILS + sm->msg_id_base);
- rmp->sw_if_index = ntohl (i->sw_if_index);
- rmp->is_inside = i->is_inside;
- rmp->context = context;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
-vl_api_snat_interface_dump_t_handler (vl_api_snat_interface_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- snat_main_t *sm = &snat_main;
- snat_interface_t *i;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- /* *INDENT-OFF* */
- pool_foreach (i, sm->interfaces,
- ({
- send_snat_interface_details(i, q, mp->context);
- }));
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_interface_dump_t_print
- (vl_api_snat_interface_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_interface_dump ");
-
- FINISH;
-}
-
-static void
- vl_api_snat_interface_add_del_output_feature_t_handler
- (vl_api_snat_interface_add_del_output_feature_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_interface_add_del_output_feature_reply_t *rmp;
- u8 is_del = mp->is_add == 0;
- u32 sw_if_index = ntohl (mp->sw_if_index);
- int rv = 0;
-
- VALIDATE_SW_IF_INDEX (mp);
-
- rv = snat_interface_add_del_output_feature (sw_if_index, mp->is_inside,
- is_del);
-
- BAD_SW_IF_INDEX_LABEL;
-
- REPLY_MACRO (VL_API_SNAT_INTERFACE_ADD_DEL_OUTPUT_FEATURE_REPLY);
-}
-
-static void *vl_api_snat_interface_add_del_output_feature_t_print
- (vl_api_snat_interface_add_del_output_feature_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_interface_add_del_output_feature ");
- s = format (s, "sw_if_index %d %s %s",
- clib_host_to_net_u32 (mp->sw_if_index),
- mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
-
- FINISH;
-}
-
-static void
-send_snat_interface_output_feature_details (snat_interface_t * i,
- unix_shared_memory_queue_t * q,
- u32 context)
-{
- vl_api_snat_interface_output_feature_details_t *rmp;
- snat_main_t *sm = &snat_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id =
- ntohs (VL_API_SNAT_INTERFACE_OUTPUT_FEATURE_DETAILS + sm->msg_id_base);
- rmp->sw_if_index = ntohl (i->sw_if_index);
- rmp->context = context;
- rmp->is_inside = i->is_inside;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
- vl_api_snat_interface_output_feature_dump_t_handler
- (vl_api_snat_interface_output_feature_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- snat_main_t *sm = &snat_main;
- snat_interface_t *i;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- /* *INDENT-OFF* */
- pool_foreach (i, sm->output_feature_interfaces,
- ({
- send_snat_interface_output_feature_details(i, q, mp->context);
- }));
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_interface_output_feature_dump_t_print
- (vl_api_snat_interface_output_feature_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_interface_output_feature_dump ");
-
- FINISH;
-}
-
-static void
- vl_api_snat_add_static_mapping_t_handler
- (vl_api_snat_add_static_mapping_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_add_static_mapping_reply_t *rmp;
- ip4_address_t local_addr, external_addr;
- u16 local_port = 0, external_port = 0;
- u32 vrf_id, external_sw_if_index;
- int rv = 0;
- snat_protocol_t proto;
-
- if (mp->is_ip4 != 1)
- {
- rv = VNET_API_ERROR_UNIMPLEMENTED;
- goto send_reply;
- }
-
- memcpy (&local_addr.as_u8, mp->local_ip_address, 4);
- memcpy (&external_addr.as_u8, mp->external_ip_address, 4);
- if (mp->addr_only == 0)
- {
- local_port = clib_net_to_host_u16 (mp->local_port);
- external_port = clib_net_to_host_u16 (mp->external_port);
- }
- vrf_id = clib_net_to_host_u32 (mp->vrf_id);
- external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
- proto = ip_proto_to_snat_proto (mp->protocol);
-
- rv = snat_add_static_mapping (local_addr, external_addr, local_port,
- external_port, vrf_id, mp->addr_only,
- external_sw_if_index, proto, mp->is_add);
-
-send_reply:
- REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
-}
-
-static void *vl_api_snat_add_static_mapping_t_print
- (vl_api_snat_add_static_mapping_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_add_static_mapping ");
- s = format (s, "protocol %d local_addr %U external_addr %U ",
- mp->protocol,
- format_ip4_address, mp->local_ip_address,
- format_ip4_address, mp->external_ip_address);
-
- if (mp->addr_only == 0)
- s = format (s, "local_port %d external_port %d ",
- clib_net_to_host_u16 (mp->local_port),
- clib_net_to_host_u16 (mp->external_port));
-
- if (mp->vrf_id != ~0)
- s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
-
- if (mp->external_sw_if_index != ~0)
- s = format (s, "external_sw_if_index %d",
- clib_net_to_host_u32 (mp->external_sw_if_index));
- FINISH;
-}
-
-static void
- send_snat_static_mapping_details
- (snat_static_mapping_t * m, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_snat_static_mapping_details_t *rmp;
- snat_main_t *sm = &snat_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id =
- ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS + sm->msg_id_base);
- rmp->is_ip4 = 1;
- rmp->addr_only = m->addr_only;
- clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
- clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
- rmp->local_port = htons (m->local_port);
- rmp->external_port = htons (m->external_port);
- rmp->external_sw_if_index = ~0;
- rmp->vrf_id = htonl (m->vrf_id);
- rmp->protocol = snat_proto_to_ip_proto (m->proto);
- rmp->context = context;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
- send_snat_static_map_resolve_details
- (snat_static_map_resolve_t * m, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_snat_static_mapping_details_t *rmp;
- snat_main_t *sm = &snat_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id =
- ntohs (VL_API_SNAT_STATIC_MAPPING_DETAILS + sm->msg_id_base);
- rmp->is_ip4 = 1;
- rmp->addr_only = m->addr_only;
- clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
- rmp->local_port = htons (m->l_port);
- rmp->external_port = htons (m->e_port);
- rmp->external_sw_if_index = htonl (m->sw_if_index);
- rmp->vrf_id = htonl (m->vrf_id);
- rmp->protocol = snat_proto_to_ip_proto (m->proto);
- rmp->context = context;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
- vl_api_snat_static_mapping_dump_t_handler
- (vl_api_snat_static_mapping_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- snat_main_t *sm = &snat_main;
- snat_static_mapping_t *m;
- snat_static_map_resolve_t *rp;
- int j;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- /* *INDENT-OFF* */
- pool_foreach (m, sm->static_mappings,
- ({
- send_snat_static_mapping_details (m, q, mp->context);
- }));
- /* *INDENT-ON* */
-
- for (j = 0; j < vec_len (sm->to_resolve); j++)
- {
- rp = sm->to_resolve + j;
- send_snat_static_map_resolve_details (rp, q, mp->context);
- }
-}
-
-static void *vl_api_snat_static_mapping_dump_t_print
- (vl_api_snat_static_mapping_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_static_mapping_dump ");
-
- FINISH;
-}
-
-static void
-vl_api_snat_control_ping_t_handler (vl_api_snat_control_ping_t * mp)
-{
- vl_api_snat_control_ping_reply_t *rmp;
- snat_main_t *sm = &snat_main;
- int rv = 0;
-
- /* *INDENT-OFF* */
- REPLY_MACRO2 (VL_API_SNAT_CONTROL_PING_REPLY,
- ({
- rmp->vpe_pid = ntohl (getpid ());
- }));
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_control_ping_t_print
- (vl_api_snat_control_ping_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_control_ping ");
-
- FINISH;
-}
-
-static void
-vl_api_snat_show_config_t_handler (vl_api_snat_show_config_t * mp)
-{
- vl_api_snat_show_config_reply_t *rmp;
- snat_main_t *sm = &snat_main;
- int rv = 0;
-
- /* *INDENT-OFF* */
- REPLY_MACRO2 (VL_API_SNAT_SHOW_CONFIG_REPLY,
- ({
- rmp->translation_buckets = htonl (sm->translation_buckets);
- rmp->translation_memory_size = htonl (sm->translation_memory_size);
- rmp->user_buckets = htonl (sm->user_buckets);
- rmp->user_memory_size = htonl (sm->user_memory_size);
- rmp->max_translations_per_user = htonl (sm->max_translations_per_user);
- rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
- rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
- rmp->static_mapping_only = sm->static_mapping_only;
- rmp->static_mapping_connection_tracking =
- sm->static_mapping_connection_tracking;
- rmp->deterministic = sm->deterministic;
- }));
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_show_config_t_print
- (vl_api_snat_show_config_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_show_config ");
-
- FINISH;
-}
-
-static void
-vl_api_snat_set_workers_t_handler (vl_api_snat_set_workers_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_set_workers_reply_t *rmp;
- int rv = 0;
- uword *bitmap = 0;
- u64 mask = clib_net_to_host_u64 (mp->worker_mask);
-
- if (sm->num_workers < 2)
- {
- rv = VNET_API_ERROR_FEATURE_DISABLED;
- goto send_reply;
- }
-
- bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
- rv = snat_set_workers (bitmap);
- clib_bitmap_free (bitmap);
-
-send_reply:
- REPLY_MACRO (VL_API_SNAT_SET_WORKERS_REPLY);
-}
-
-static void *vl_api_snat_set_workers_t_print
- (vl_api_snat_set_workers_t * mp, void *handle)
-{
- u8 *s;
- uword *bitmap = 0;
- u8 first = 1;
- int i;
- u64 mask = clib_net_to_host_u64 (mp->worker_mask);
-
- s = format (0, "SCRIPT: snat_set_workers ");
- bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
- /* *INDENT-OFF* */
- clib_bitmap_foreach (i, bitmap,
- ({
- if (first)
- s = format (s, "%d", i);
- else
- s = format (s, ",%d", i);
- first = 0;
- }));
- /* *INDENT-ON* */
- clib_bitmap_free (bitmap);
- FINISH;
-}
-
-static void
- send_snat_worker_details
- (u32 worker_index, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_snat_worker_details_t *rmp;
- snat_main_t *sm = &snat_main;
- vlib_worker_thread_t *w =
- vlib_worker_threads + worker_index + sm->first_worker_index;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_SNAT_WORKER_DETAILS + sm->msg_id_base);
- rmp->context = context;
- rmp->worker_index = htonl (worker_index);
- rmp->lcore_id = htonl (w->lcore_id);
- strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
-vl_api_snat_worker_dump_t_handler (vl_api_snat_worker_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- snat_main_t *sm = &snat_main;
- u32 *worker_index;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- /* *INDENT-OFF* */
- vec_foreach (worker_index, sm->workers)
- send_snat_worker_details(*worker_index, q, mp->context);
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_worker_dump_t_print
- (vl_api_snat_worker_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_worker_dump ");
-
- FINISH;
-}
-
-static void
- vl_api_snat_add_del_interface_addr_t_handler
- (vl_api_snat_add_del_interface_addr_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_add_del_interface_addr_reply_t *rmp;
- u8 is_del = mp->is_add == 0;
- u32 sw_if_index = ntohl (mp->sw_if_index);
- int rv = 0;
-
- VALIDATE_SW_IF_INDEX (mp);
-
- rv = snat_add_interface_address (sm, sw_if_index, is_del);
-
- BAD_SW_IF_INDEX_LABEL;
-
- REPLY_MACRO (VL_API_SNAT_ADD_DEL_INTERFACE_ADDR_REPLY);
-}
-
-static void *vl_api_snat_add_del_interface_addr_t_print
- (vl_api_snat_add_del_interface_addr_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_add_del_interface_addr ");
- s = format (s, "sw_if_index %d %s",
- clib_host_to_net_u32 (mp->sw_if_index),
- mp->is_add ? "" : "del");
-
- FINISH;
-}
-
-static void
- send_snat_interface_addr_details
- (u32 sw_if_index, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_snat_interface_addr_details_t *rmp;
- snat_main_t *sm = &snat_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id =
- ntohs (VL_API_SNAT_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
- rmp->sw_if_index = ntohl (sw_if_index);
- rmp->context = context;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
- vl_api_snat_interface_addr_dump_t_handler
- (vl_api_snat_interface_addr_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- snat_main_t *sm = &snat_main;
- u32 *i;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- /* *INDENT-OFF* */
- vec_foreach (i, sm->auto_add_sw_if_indices)
- send_snat_interface_addr_details(*i, q, mp->context);
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_interface_addr_dump_t_print
- (vl_api_snat_interface_addr_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_interface_addr_dump ");
-
- FINISH;
-}
-
-static void
- vl_api_snat_ipfix_enable_disable_t_handler
- (vl_api_snat_ipfix_enable_disable_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_ipfix_enable_disable_reply_t *rmp;
- int rv = 0;
-
- rv = snat_ipfix_logging_enable_disable (mp->enable,
- clib_host_to_net_u32
- (mp->domain_id),
- clib_host_to_net_u16
- (mp->src_port));
-
- REPLY_MACRO (VL_API_SNAT_IPFIX_ENABLE_DISABLE_REPLY);
-}
-
-static void *vl_api_snat_ipfix_enable_disable_t_print
- (vl_api_snat_ipfix_enable_disable_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_ipfix_enable_disable ");
- if (mp->domain_id)
- s = format (s, "domain %d ", clib_net_to_host_u32 (mp->domain_id));
- if (mp->src_port)
- s = format (s, "src_port %d ", clib_net_to_host_u16 (mp->src_port));
- if (!mp->enable)
- s = format (s, "disable ");
-
- FINISH;
-}
-
-static void
- send_snat_user_details
- (snat_user_t * u, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_snat_user_details_t *rmp;
- snat_main_t *sm = &snat_main;
- fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_SNAT_USER_DETAILS + sm->msg_id_base);
-
- rmp->vrf_id = ntohl (fib->ft_table_id);
-
- rmp->is_ip4 = 1;
- clib_memcpy (rmp->ip_address, &(u->addr), 4);
- rmp->nsessions = ntohl (u->nsessions);
- rmp->nstaticsessions = ntohl (u->nstaticsessions);
- rmp->context = context;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
-vl_api_snat_user_dump_t_handler (vl_api_snat_user_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- snat_main_t *sm = &snat_main;
- snat_main_per_thread_data_t *tsm;
- snat_user_t *u;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- /* *INDENT-OFF* */
- vec_foreach (tsm, sm->per_thread_data)
- vec_foreach (u, tsm->users)
- send_snat_user_details (u, q, mp->context);
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_user_dump_t_print
- (vl_api_snat_user_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_user_dump ");
-
- FINISH;
-}
-
-static void
- send_snat_user_session_details
- (snat_session_t * s, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_snat_user_session_details_t *rmp;
- snat_main_t *sm = &snat_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id =
- ntohs (VL_API_SNAT_USER_SESSION_DETAILS + sm->msg_id_base);
- rmp->is_ip4 = 1;
- clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
- clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
- rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
- rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
- rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
- rmp->total_pkts = ntohl (s->total_pkts);
- rmp->context = context;
- if (snat_is_unk_proto_session (s))
- {
- rmp->outside_port = 0;
- rmp->inside_port = 0;
- rmp->protocol = ntohs (s->in2out.port);
- }
- else
- {
- rmp->outside_port = s->out2in.port;
- rmp->inside_port = s->in2out.port;
- rmp->protocol = ntohs (snat_proto_to_ip_proto (s->in2out.protocol));
- }
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
- vl_api_snat_user_session_dump_t_handler
- (vl_api_snat_user_session_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- snat_main_t *sm = &snat_main;
- snat_main_per_thread_data_t *tsm;
- snat_session_t *s;
- clib_bihash_kv_8_8_t key, value;
- snat_user_key_t ukey;
- snat_user_t *u;
- u32 session_index, head_index, elt_index;
- dlist_elt_t *head, *elt;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
- if (!mp->is_ip4)
- return;
-
- clib_memcpy (&ukey.addr, mp->ip_address, 4);
- ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
- key.key = ukey.as_u64;
- if (!clib_bihash_search_8_8 (&sm->worker_by_in, &key, &value))
- tsm = vec_elt_at_index (sm->per_thread_data, value.value);
- else
- tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
- if (clib_bihash_search_8_8 (&sm->user_hash, &key, &value))
- return;
- u = pool_elt_at_index (tsm->users, value.value);
- if (!u->nsessions && !u->nstaticsessions)
- return;
-
- head_index = u->sessions_per_user_list_head_index;
- head = pool_elt_at_index (tsm->list_pool, head_index);
- elt_index = head->next;
- elt = pool_elt_at_index (tsm->list_pool, elt_index);
- session_index = elt->value;
- while (session_index != ~0)
- {
- s = pool_elt_at_index (tsm->sessions, session_index);
-
- send_snat_user_session_details (s, q, mp->context);
-
- elt_index = elt->next;
- elt = pool_elt_at_index (tsm->list_pool, elt_index);
- session_index = elt->value;
- }
-}
-
-static void *vl_api_snat_user_session_dump_t_print
- (vl_api_snat_user_session_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_user_session_dump ");
- s = format (s, "ip_address %U vrf_id %d\n",
- format_ip4_address, mp->ip_address,
- clib_net_to_host_u32 (mp->vrf_id));
-
- FINISH;
-}
-
-/****************************/
-/*** detrministic NAT/CGN ***/
-/****************************/
-
-static void
-vl_api_snat_add_det_map_t_handler (vl_api_snat_add_det_map_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_add_det_map_reply_t *rmp;
- int rv = 0;
- ip4_address_t in_addr, out_addr;
-
- clib_memcpy (&in_addr, mp->in_addr, 4);
- clib_memcpy (&out_addr, mp->out_addr, 4);
- rv = snat_det_add_map (sm, &in_addr, mp->in_plen, &out_addr,
- mp->out_plen, mp->is_add);
-
- REPLY_MACRO (VL_API_SNAT_ADD_DET_MAP_REPLY);
-}
-
-static void *vl_api_snat_add_det_map_t_print
- (vl_api_snat_add_det_map_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_add_det_map ");
- s = format (s, "inside address %U/%d outside address %U/%d\n",
- format_ip4_address, mp->in_addr, mp->in_plen,
- format_ip4_address, mp->out_addr, mp->out_plen);
-
- FINISH;
-}
-
-static void
-vl_api_snat_det_forward_t_handler (vl_api_snat_det_forward_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_det_forward_reply_t *rmp;
- int rv = 0;
- u16 lo_port = 0, hi_port = 0;
- snat_det_map_t *dm;
- ip4_address_t in_addr, out_addr;
-
- out_addr.as_u32 = 0;
- clib_memcpy (&in_addr, mp->in_addr, 4);
- dm = snat_det_map_by_user (sm, &in_addr);
- if (!dm)
- {
- rv = VNET_API_ERROR_NO_SUCH_ENTRY;
- goto send_reply;
- }
-
- snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
- hi_port = lo_port + dm->ports_per_host - 1;
-
-send_reply:
- /* *INDENT-OFF* */
- REPLY_MACRO2 (VL_API_SNAT_DET_FORWARD_REPLY,
- ({
- rmp->out_port_lo = ntohs (lo_port);
- rmp->out_port_hi = ntohs (hi_port);
- rmp->is_ip4 = 1;
- memset (rmp->out_addr, 0, 16);
- clib_memcpy (rmp->out_addr, &out_addr, 4);
- }))
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_det_forward_t_print
- (vl_api_snat_det_forward_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: smat_det_forward_t");
- s = format (s, "inside ip address %U\n", format_ip4_address, mp->in_addr);
-
- FINISH;
-}
-
-static void
-vl_api_snat_det_reverse_t_handler (vl_api_snat_det_reverse_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_det_reverse_reply_t *rmp;
- int rv = 0;
- ip4_address_t out_addr, in_addr;
- snat_det_map_t *dm;
-
- in_addr.as_u32 = 0;
- clib_memcpy (&out_addr, mp->out_addr, 4);
- dm = snat_det_map_by_out (sm, &out_addr);
- if (!dm)
- {
- rv = VNET_API_ERROR_NO_SUCH_ENTRY;
- goto send_reply;
- }
-
- snat_det_reverse (dm, &out_addr, htons (mp->out_port), &in_addr);
-
-send_reply:
- /* *INDENT-OFF* */
- REPLY_MACRO2 (VL_API_SNAT_DET_REVERSE_REPLY,
- ({
- rmp->is_ip4 = 1;
- memset (rmp->in_addr, 0, 16);
- clib_memcpy (rmp->in_addr, &in_addr, 4);
- }))
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_det_reverse_t_print
- (vl_api_snat_det_reverse_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: smat_det_reverse_t");
- s = format (s, "outside ip address %U outside port %d",
- format_ip4_address, mp->out_addr, ntohs (mp->out_port));
-
- FINISH;
-}
-
-static void
- sent_snat_det_map_details
- (snat_det_map_t * m, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_snat_det_map_details_t *rmp;
- snat_main_t *sm = &snat_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_MAP_DETAILS + sm->msg_id_base);
- rmp->is_ip4 = 1;
- clib_memcpy (rmp->in_addr, &m->in_addr, 4);
- rmp->in_plen = m->in_plen;
- clib_memcpy (rmp->out_addr, &m->out_addr, 4);
- rmp->out_plen = m->out_plen;
- rmp->sharing_ratio = htonl (m->sharing_ratio);
- rmp->ports_per_host = htons (m->ports_per_host);
- rmp->ses_num = htonl (m->ses_num);
- rmp->context = context;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
-vl_api_snat_det_map_dump_t_handler (vl_api_snat_det_map_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- snat_main_t *sm = &snat_main;
- snat_det_map_t *m;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- /* *INDENT-OFF* */
- vec_foreach(m, sm->det_maps)
- sent_snat_det_map_details(m, q, mp->context);
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_det_map_dump_t_print
- (vl_api_snat_det_map_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_det_map_dump ");
-
- FINISH;
-}
-
-static void
-vl_api_snat_det_set_timeouts_t_handler (vl_api_snat_det_set_timeouts_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_det_set_timeouts_reply_t *rmp;
- int rv = 0;
-
- sm->udp_timeout = ntohl (mp->udp);
- sm->tcp_established_timeout = ntohl (mp->tcp_established);
- sm->tcp_transitory_timeout = ntohl (mp->tcp_transitory);
- sm->icmp_timeout = ntohl (mp->icmp);
-
- REPLY_MACRO (VL_API_SNAT_DET_SET_TIMEOUTS_REPLY);
-}
-
-static void *vl_api_snat_det_set_timeouts_t_print
- (vl_api_snat_det_set_timeouts_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_det_set_timeouts ");
- s = format (s, "udp %d tcp_established %d tcp_transitory %d icmp %d\n",
- ntohl (mp->udp),
- ntohl (mp->tcp_established),
- ntohl (mp->tcp_transitory), ntohl (mp->icmp));
-
- FINISH;
-}
-
-static void
-vl_api_snat_det_get_timeouts_t_handler (vl_api_snat_det_get_timeouts_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_det_get_timeouts_reply_t *rmp;
- int rv = 0;
-
- /* *INDENT-OFF* */
- REPLY_MACRO2 (VL_API_SNAT_DET_GET_TIMEOUTS_REPLY,
- ({
- rmp->udp = htonl (sm->udp_timeout);
- rmp->tcp_established = htonl (sm->tcp_established_timeout);
- rmp->tcp_transitory = htonl (sm->tcp_transitory_timeout);
- rmp->icmp = htonl (sm->icmp_timeout);
- }))
- /* *INDENT-ON* */
-}
-
-static void *vl_api_snat_det_get_timeouts_t_print
- (vl_api_snat_det_get_timeouts_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_det_get_timeouts");
-
- FINISH;
-}
-
-static void
- vl_api_snat_det_close_session_out_t_handler
- (vl_api_snat_det_close_session_out_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_det_close_session_out_reply_t *rmp;
- ip4_address_t out_addr, ext_addr, in_addr;
- snat_det_out_key_t key;
- snat_det_map_t *dm;
- snat_det_session_t *ses;
- int rv = 0;
-
- clib_memcpy (&out_addr, mp->out_addr, 4);
- clib_memcpy (&ext_addr, mp->ext_addr, 4);
-
- dm = snat_det_map_by_out (sm, &out_addr);
- if (!dm)
- {
- rv = VNET_API_ERROR_NO_SUCH_ENTRY;
- goto send_reply;
- }
- snat_det_reverse (dm, &ext_addr, ntohs (mp->out_port), &in_addr);
- key.ext_host_addr = ext_addr;
- key.ext_host_port = mp->ext_port;
- key.out_port = mp->out_port;
- ses = snat_det_get_ses_by_out (dm, &in_addr, key.as_u64);
- if (!ses)
- {
- rv = VNET_API_ERROR_NO_SUCH_ENTRY;
- goto send_reply;
- }
- snat_det_ses_close (dm, ses);
-
-send_reply:
- REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY);
-}
-
-static void *vl_api_snat_det_close_session_out_t_print
- (vl_api_snat_det_close_session_out_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_det_close_session_out ");
- s = format (s, "out_addr %U out_port %d "
- "ext_addr %U ext_port %d\n",
- format_ip4_address, mp->out_addr, ntohs (mp->out_port),
- format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
-
- FINISH;
-}
-
-static void
- vl_api_snat_det_close_session_in_t_handler
- (vl_api_snat_det_close_session_in_t * mp)
-{
- snat_main_t *sm = &snat_main;
- vl_api_snat_det_close_session_in_reply_t *rmp;
- ip4_address_t in_addr, ext_addr;
- snat_det_out_key_t key;
- snat_det_map_t *dm;
- snat_det_session_t *ses;
- int rv = 0;
-
- clib_memcpy (&in_addr, mp->in_addr, 4);
- clib_memcpy (&ext_addr, mp->ext_addr, 4);
-
- dm = snat_det_map_by_user (sm, &in_addr);
- if (!dm)
- {
- rv = VNET_API_ERROR_NO_SUCH_ENTRY;
- goto send_reply;
- }
- key.ext_host_addr = ext_addr;
- key.ext_host_port = mp->ext_port;
- ses = snat_det_find_ses_by_in (dm, &in_addr, mp->in_port, key);
- if (!ses)
- {
- rv = VNET_API_ERROR_NO_SUCH_ENTRY;
- goto send_reply;
- }
- snat_det_ses_close (dm, ses);
-
-send_reply:
- REPLY_MACRO (VL_API_SNAT_DET_CLOSE_SESSION_OUT_REPLY);
-}
-
-static void *vl_api_snat_det_close_session_in_t_print
- (vl_api_snat_det_close_session_in_t * mp, void *handle)
-{
- u8 *s;
- s = format (0, "SCRIPT: snat_det_close_session_in ");
- s = format (s, "in_addr %U in_port %d "
- "ext_addr %U ext_port %d\n",
- format_ip4_address, mp->in_addr, ntohs (mp->in_port),
- format_ip4_address, mp->ext_addr, ntohs (mp->ext_port));
-
- FINISH;
-}
-
-static void
- send_snat_det_session_details
- (snat_det_session_t * s, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_snat_det_session_details_t *rmp;
- snat_main_t *sm = &snat_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_SESSION_DETAILS + sm->msg_id_base);
- rmp->is_ip4 = 1;
- rmp->in_port = s->in_port;
- clib_memcpy (rmp->ext_addr, &s->out.ext_host_addr, 4);
- rmp->ext_port = s->out.ext_host_port;
- rmp->out_port = s->out.out_port;
- rmp->state = s->state;
- rmp->expire = ntohl (s->expire);
- rmp->context = context;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
-vl_api_snat_det_session_dump_t_handler (vl_api_snat_det_session_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- snat_main_t *sm = &snat_main;
- ip4_address_t user_addr;
- snat_det_map_t *dm;
- snat_det_session_t *s, empty_ses;
- u16 i;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
- if (!mp->is_ip4)
- return;
-
- memset (&empty_ses, 0, sizeof (empty_ses));
- clib_memcpy (&user_addr, mp->user_addr, 4);
- dm = snat_det_map_by_user (sm, &user_addr);
- if (!dm)
- return;
-
- s = dm->sessions + snat_det_user_ses_offset (&user_addr, dm->in_plen);
- for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
- {
- if (s->out.as_u64)
- send_snat_det_session_details (s, q, mp->context);
- s++;
- }
-}
-
-static void *vl_api_snat_det_session_dump_t_print
- (vl_api_snat_det_session_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_det_session_dump ");
- s = format (s, "user_addr %U\n", format_ip4_address, mp->user_addr);
-
- FINISH;
-}
-
-/*************/
-/*** NAT64 ***/
-/*************/
-
-static void
- vl_api_nat64_add_del_pool_addr_range_t_handler
- (vl_api_nat64_add_del_pool_addr_range_t * mp)
-{
- vl_api_nat64_add_del_pool_addr_range_reply_t *rmp;
- snat_main_t *sm = &snat_main;
- nat64_main_t *nm = &nat64_main;
- int rv = 0;
- ip4_address_t this_addr;
- u32 start_host_order, end_host_order;
- u32 vrf_id;
- int i, count;
- u32 *tmp;
-
- if (nm->is_disabled)
- {
- rv = VNET_API_ERROR_FEATURE_DISABLED;
- goto send_reply;
- }
-
- tmp = (u32 *) mp->start_addr;
- start_host_order = clib_host_to_net_u32 (tmp[0]);
- tmp = (u32 *) mp->end_addr;
- end_host_order = clib_host_to_net_u32 (tmp[0]);
-
- count = (end_host_order - start_host_order) + 1;
-
- vrf_id = clib_host_to_net_u32 (mp->vrf_id);
-
- memcpy (&this_addr.as_u8, mp->start_addr, 4);
-
- for (i = 0; i < count; i++)
- {
- if ((rv = nat64_add_del_pool_addr (&this_addr, vrf_id, mp->is_add)))
- goto send_reply;
-
- increment_v4_address (&this_addr);
- }
-
-send_reply:
- REPLY_MACRO (VL_API_NAT64_ADD_DEL_POOL_ADDR_RANGE_REPLY);
-}
-
-static void *vl_api_nat64_add_del_pool_addr_range_t_print
- (vl_api_nat64_add_del_pool_addr_range_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: nat64_add_del_pool_addr_range ");
- s = format (s, "%U - %U vrf_id %u %s\n",
- format_ip4_address, mp->start_addr,
- format_ip4_address, mp->end_addr,
- ntohl (mp->vrf_id), mp->is_add ? "" : "del");
-
- FINISH;
-}
-
-typedef struct nat64_api_walk_ctx_t_
-{
- unix_shared_memory_queue_t *q;
- u32 context;
-} nat64_api_walk_ctx_t;
-
-static int
-nat64_api_pool_walk (snat_address_t * a, void *arg)
-{
- vl_api_nat64_pool_addr_details_t *rmp;
- snat_main_t *sm = &snat_main;
- nat64_api_walk_ctx_t *ctx = arg;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_NAT64_POOL_ADDR_DETAILS + sm->msg_id_base);
- clib_memcpy (rmp->address, &(a->addr), 4);
- if (a->fib_index != ~0)
- {
- fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP6);
- if (!fib)
- return -1;
- rmp->vrf_id = ntohl (fib->ft_table_id);
- }
- else
- rmp->vrf_id = ~0;
- rmp->context = ctx->context;
-
- vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
-
- return 0;
-}
-
-static void
-vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- nat64_main_t *nm = &nat64_main;
-
- if (nm->is_disabled)
- return;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- nat64_api_walk_ctx_t ctx = {
- .q = q,
- .context = mp->context,
- };
-
- nat64_pool_addr_walk (nat64_api_pool_walk, &ctx);
-}
-
-static void *
-vl_api_nat64_pool_addr_dump_t_print (vl_api_nat64_pool_addr_dump_t * mp,
- void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: nat64_pool_addr_dump\n");
-
- FINISH;
-}
-
-static void
-vl_api_nat64_add_del_interface_t_handler (vl_api_nat64_add_del_interface_t *
- mp)
-{
- snat_main_t *sm = &snat_main;
- nat64_main_t *nm = &nat64_main;
- vl_api_nat64_add_del_interface_reply_t *rmp;
- int rv = 0;
-
- if (nm->is_disabled)
- {
- rv = VNET_API_ERROR_FEATURE_DISABLED;
- goto send_reply;
- }
-
- VALIDATE_SW_IF_INDEX (mp);
-
- rv =
- nat64_add_del_interface (ntohl (mp->sw_if_index), mp->is_inside,
- mp->is_add);
-
- BAD_SW_IF_INDEX_LABEL;
-
-send_reply:
- REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_REPLY);
-}
-
-static void *
-vl_api_nat64_add_del_interface_t_print (vl_api_nat64_add_del_interface_t * mp,
- void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: nat64_add_del_interface ");
- s = format (s, "sw_if_index %d %s %s",
- clib_host_to_net_u32 (mp->sw_if_index),
- mp->is_inside ? "in" : "out", mp->is_add ? "" : "del");
-
- FINISH;
-}
-
-static int
-nat64_api_interface_walk (snat_interface_t * i, void *arg)
-{
- vl_api_nat64_interface_details_t *rmp;
- snat_main_t *sm = &snat_main;
- nat64_api_walk_ctx_t *ctx = arg;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_NAT64_INTERFACE_DETAILS + sm->msg_id_base);
- rmp->sw_if_index = ntohl (i->sw_if_index);
- rmp->is_inside = i->is_inside;
- rmp->context = ctx->context;
-
- vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
-
- return 0;
-}
-
-static void
-vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- nat64_main_t *nm = &nat64_main;
-
- if (nm->is_disabled)
- return;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- nat64_api_walk_ctx_t ctx = {
- .q = q,
- .context = mp->context,
- };
-
- nat64_interfaces_walk (nat64_api_interface_walk, &ctx);
-}
-
-static void *
-vl_api_nat64_interface_dump_t_print (vl_api_nat64_interface_dump_t * mp,
- void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_interface_dump ");
-
- FINISH;
-}
-
-static void
- vl_api_nat64_add_del_static_bib_t_handler
- (vl_api_nat64_add_del_static_bib_t * mp)
-{
- snat_main_t *sm = &snat_main;
- nat64_main_t *nm = &nat64_main;
- vl_api_nat64_add_del_static_bib_reply_t *rmp;
- ip6_address_t in_addr;
- ip4_address_t out_addr;
- int rv = 0;
-
- if (nm->is_disabled)
- {
- rv = VNET_API_ERROR_FEATURE_DISABLED;
- goto send_reply;
- }
-
- memcpy (&in_addr.as_u8, mp->i_addr, 16);
- memcpy (&out_addr.as_u8, mp->o_addr, 4);
-
- rv =
- nat64_add_del_static_bib_entry (&in_addr, &out_addr,
- clib_net_to_host_u16 (mp->i_port),
- clib_net_to_host_u16 (mp->o_port),
- mp->proto,
- clib_net_to_host_u32 (mp->vrf_id),
- mp->is_add);
-
-send_reply:
- REPLY_MACRO (VL_API_NAT64_ADD_DEL_STATIC_BIB_REPLY);
-}
-
-static void *vl_api_nat64_add_del_static_bib_t_print
- (vl_api_nat64_add_del_static_bib_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: nat64_add_del_static_bib ");
- s = format (s, "protocol %d i_addr %U o_addr %U ",
- mp->proto,
- format_ip6_address, mp->i_addr, format_ip4_address, mp->o_addr);
-
- if (mp->vrf_id != ~0)
- s = format (s, "vrf %d", clib_net_to_host_u32 (mp->vrf_id));
-
- FINISH;
-}
-
-static int
-nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg)
-{
- vl_api_nat64_bib_details_t *rmp;
- snat_main_t *sm = &snat_main;
- nat64_api_walk_ctx_t *ctx = arg;
- fib_table_t *fib;
-
- fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
- if (!fib)
- return -1;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_NAT64_BIB_DETAILS + sm->msg_id_base);
- rmp->context = ctx->context;
- clib_memcpy (rmp->i_addr, &(bibe->in_addr), 16);
- clib_memcpy (rmp->o_addr, &(bibe->out_addr), 4);
- rmp->i_port = bibe->in_port;
- rmp->o_port = bibe->out_port;
- rmp->vrf_id = ntohl (fib->ft_table_id);
- rmp->proto = bibe->proto;
- rmp->is_static = bibe->is_static;
- rmp->ses_num = ntohl (bibe->ses_num);
-
- vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
-
- return 0;
-}
-
-static void
-vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- nat64_main_t *nm = &nat64_main;
-
- if (nm->is_disabled)
- return;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- nat64_api_walk_ctx_t ctx = {
- .q = q,
- .context = mp->context,
- };
-
- nat64_db_bib_walk (&nm->db, mp->proto, nat64_api_bib_walk, &ctx);
-}
-
-static void *
-vl_api_nat64_bib_dump_t_print (vl_api_nat64_bib_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_bib_dump protocol %d", mp->proto);
-
- FINISH;
-}
-
-static void
-vl_api_nat64_set_timeouts_t_handler (vl_api_nat64_set_timeouts_t * mp)
-{
- snat_main_t *sm = &snat_main;
- nat64_main_t *nm = &nat64_main;
- vl_api_nat64_set_timeouts_reply_t *rmp;
- int rv = 0;
-
- if (nm->is_disabled)
- {
- rv = VNET_API_ERROR_FEATURE_DISABLED;
- goto send_reply;
- }
-
- rv = nat64_set_icmp_timeout (ntohl (mp->icmp));
- if (rv)
- goto send_reply;
- rv = nat64_set_udp_timeout (ntohl (mp->udp));
- if (rv)
- goto send_reply;
- rv =
- nat64_set_tcp_timeouts (ntohl (mp->tcp_trans), ntohl (mp->tcp_est),
- ntohl (mp->tcp_incoming_syn));
-
-send_reply:
- REPLY_MACRO (VL_API_NAT64_SET_TIMEOUTS_REPLY);
-}
-
-static void *vl_api_nat64_set_timeouts_t_print
- (vl_api_nat64_set_timeouts_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: nat64_set_timeouts ");
- s =
- format (s,
- "udp %d icmp %d, tcp_trans %d, tcp_est %d, tcp_incoming_syn %d\n",
- ntohl (mp->udp), ntohl (mp->icmp), ntohl (mp->tcp_trans),
- ntohl (mp->tcp_est), ntohl (mp->tcp_incoming_syn));
-
- FINISH;
-}
-
-static void
-vl_api_nat64_get_timeouts_t_handler (vl_api_nat64_get_timeouts_t * mp)
-{
- snat_main_t *sm = &snat_main;
- nat64_main_t *nm = &nat64_main;
- vl_api_nat64_get_timeouts_reply_t *rmp;
- int rv = 0;
-
- if (nm->is_disabled)
- return;
-
- /* *INDENT-OFF* */
- REPLY_MACRO2 (VL_API_NAT64_GET_TIMEOUTS_REPLY,
- ({
- rmp->udp = htonl (nat64_get_udp_timeout());
- rmp->icmp = htonl (nat64_get_icmp_timeout());
- rmp->tcp_trans = htonl (nat64_get_tcp_trans_timeout());
- rmp->tcp_est = htonl (nat64_get_tcp_est_timeout());
- rmp->tcp_incoming_syn = htonl (nat64_get_tcp_incoming_syn_timeout());
- }))
- /* *INDENT-ON* */
-}
-
-static void *vl_api_nat64_get_timeouts_t_print
- (vl_api_nat64_get_timeouts_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: nat64_get_timeouts");
-
- FINISH;
-}
-
-static int
-nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg)
-{
- vl_api_nat64_st_details_t *rmp;
- snat_main_t *sm = &snat_main;
- nat64_api_walk_ctx_t *ctx = arg;
- nat64_main_t *nm = &nat64_main;
- nat64_db_bib_entry_t *bibe;
- fib_table_t *fib;
-
- bibe = nat64_db_bib_entry_by_index (&nm->db, ste->proto, ste->bibe_index);
- if (!bibe)
- return -1;
-
- fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
- if (!fib)
- return -1;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_NAT64_ST_DETAILS + sm->msg_id_base);
- rmp->context = ctx->context;
- clib_memcpy (rmp->il_addr, &(bibe->in_addr), 16);
- clib_memcpy (rmp->ol_addr, &(bibe->out_addr), 4);
- rmp->il_port = bibe->in_port;
- rmp->ol_port = bibe->out_port;
- clib_memcpy (rmp->ir_addr, &(ste->in_r_addr), 16);
- clib_memcpy (rmp->or_addr, &(ste->out_r_addr), 4);
- rmp->il_port = ste->r_port;
- rmp->vrf_id = ntohl (fib->ft_table_id);
- rmp->proto = ste->proto;
-
- vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
-
- return 0;
-}
-
-static void
-vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- nat64_main_t *nm = &nat64_main;
-
- if (nm->is_disabled)
- return;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- nat64_api_walk_ctx_t ctx = {
- .q = q,
- .context = mp->context,
- };
-
- nat64_db_st_walk (&nm->db, mp->proto, nat64_api_st_walk, &ctx);
-}
-
-static void *
-vl_api_nat64_st_dump_t_print (vl_api_nat64_st_dump_t * mp, void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: snat_st_dump protocol %d", mp->proto);
-
- FINISH;
-}
-
-static void
-vl_api_nat64_add_del_prefix_t_handler (vl_api_nat64_add_del_prefix_t * mp)
-{
- vl_api_nat64_add_del_prefix_reply_t *rmp;
- snat_main_t *sm = &snat_main;
- nat64_main_t *nm = &nat64_main;
- ip6_address_t prefix;
- int rv = 0;
-
- if (nm->is_disabled)
- {
- rv = VNET_API_ERROR_FEATURE_DISABLED;
- goto send_reply;
- }
-
- memcpy (&prefix.as_u8, mp->prefix, 16);
-
- rv =
- nat64_add_del_prefix (&prefix, mp->prefix_len,
- clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
-send_reply:
- REPLY_MACRO (VL_API_NAT64_ADD_DEL_PREFIX_REPLY);
-}
-
-static void *
-vl_api_nat64_add_del_prefix_t_print (vl_api_nat64_add_del_prefix_t * mp,
- void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: nat64_add_del_prefix %U/%u vrf_id %u %s\n",
- format_ip6_address, mp->prefix, mp->prefix_len,
- ntohl (mp->vrf_id), mp->is_add ? "" : "del");
-
- FINISH;
-}
-
-static int
-nat64_api_prefix_walk (nat64_prefix_t * p, void *arg)
-{
- vl_api_nat64_prefix_details_t *rmp;
- snat_main_t *sm = &snat_main;
- nat64_api_walk_ctx_t *ctx = arg;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_NAT64_PREFIX_DETAILS + sm->msg_id_base);
- clib_memcpy (rmp->prefix, &(p->prefix), 16);
- rmp->prefix_len = p->plen;
- rmp->vrf_id = ntohl (p->vrf_id);
- rmp->context = ctx->context;
-
- vl_msg_api_send_shmem (ctx->q, (u8 *) & rmp);
-
- return 0;
-}
-
-static void
-vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- nat64_main_t *nm = &nat64_main;
-
- if (nm->is_disabled)
- return;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- return;
-
- nat64_api_walk_ctx_t ctx = {
- .q = q,
- .context = mp->context,
- };
-
- nat64_prefix_walk (nat64_api_prefix_walk, &ctx);
-}
-
-static void *
-vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
- void *handle)
-{
- u8 *s;
-
- s = format (0, "SCRIPT: nat64_prefix_dump\n");
-
- FINISH;
-}
-
-/* List of message types that this plugin understands */
-#define foreach_snat_plugin_api_msg \
-_(SNAT_ADD_ADDRESS_RANGE, snat_add_address_range) \
-_(SNAT_INTERFACE_ADD_DEL_FEATURE, snat_interface_add_del_feature) \
-_(SNAT_ADD_STATIC_MAPPING, snat_add_static_mapping) \
-_(SNAT_CONTROL_PING, snat_control_ping) \
-_(SNAT_STATIC_MAPPING_DUMP, snat_static_mapping_dump) \
-_(SNAT_SHOW_CONFIG, snat_show_config) \
-_(SNAT_ADDRESS_DUMP, snat_address_dump) \
-_(SNAT_INTERFACE_DUMP, snat_interface_dump) \
-_(SNAT_SET_WORKERS, snat_set_workers) \
-_(SNAT_WORKER_DUMP, snat_worker_dump) \
-_(SNAT_ADD_DEL_INTERFACE_ADDR, snat_add_del_interface_addr) \
-_(SNAT_INTERFACE_ADDR_DUMP, snat_interface_addr_dump) \
-_(SNAT_IPFIX_ENABLE_DISABLE, snat_ipfix_enable_disable) \
-_(SNAT_USER_DUMP, snat_user_dump) \
-_(SNAT_USER_SESSION_DUMP, snat_user_session_dump) \
-_(SNAT_INTERFACE_ADD_DEL_OUTPUT_FEATURE, \
- snat_interface_add_del_output_feature) \
-_(SNAT_INTERFACE_OUTPUT_FEATURE_DUMP, \
- snat_interface_output_feature_dump) \
-_(SNAT_ADD_DET_MAP, snat_add_det_map) \
-_(SNAT_DET_FORWARD, snat_det_forward) \
-_(SNAT_DET_REVERSE, snat_det_reverse) \
-_(SNAT_DET_MAP_DUMP, snat_det_map_dump) \
-_(SNAT_DET_SET_TIMEOUTS, snat_det_set_timeouts) \
-_(SNAT_DET_GET_TIMEOUTS, snat_det_get_timeouts) \
-_(SNAT_DET_CLOSE_SESSION_OUT, snat_det_close_session_out) \
-_(SNAT_DET_CLOSE_SESSION_IN, snat_det_close_session_in) \
-_(SNAT_DET_SESSION_DUMP, snat_det_session_dump) \
-_(NAT64_ADD_DEL_POOL_ADDR_RANGE, nat64_add_del_pool_addr_range) \
-_(NAT64_POOL_ADDR_DUMP, nat64_pool_addr_dump) \
-_(NAT64_ADD_DEL_INTERFACE, nat64_add_del_interface) \
-_(NAT64_INTERFACE_DUMP, nat64_interface_dump) \
-_(NAT64_ADD_DEL_STATIC_BIB, nat64_add_del_static_bib) \
-_(NAT64_BIB_DUMP, nat64_bib_dump) \
-_(NAT64_SET_TIMEOUTS, nat64_set_timeouts) \
-_(NAT64_GET_TIMEOUTS, nat64_get_timeouts) \
-_(NAT64_ST_DUMP, nat64_st_dump) \
-_(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix) \
-_(NAT64_PREFIX_DUMP, nat64_prefix_dump)
-
-/* Set up the API message handling tables */
-static clib_error_t *
-snat_plugin_api_hookup (vlib_main_t * vm)
-{
- snat_main_t *sm __attribute__ ((unused)) = &snat_main;
-#define _(N,n) \
- vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \
- #n, \
- vl_api_##n##_t_handler, \
- vl_noop_handler, \
- vl_api_##n##_t_endian, \
- vl_api_##n##_t_print, \
- sizeof(vl_api_##n##_t), 1);
- foreach_snat_plugin_api_msg;
-#undef _
-
- return 0;
-}
-
-#define vl_msg_name_crc_list
-#include <snat/snat_all_api_h.h>
-#undef vl_msg_name_crc_list
-
-static void
-setup_message_id_table (snat_main_t * sm, api_main_t * am)
-{
-#define _(id,n,crc) \
- vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base);
- foreach_vl_msg_name_crc_snat;
-#undef _
-}
-
-static void
-plugin_custom_dump_configure (snat_main_t * sm)
-{
-#define _(n,f) sm->api_main->msg_print_handlers \
- [VL_API_##n + sm->msg_id_base] \
- = (void *) vl_api_##f##_t_print;
- foreach_snat_plugin_api_msg;
-#undef _
-}
-
-clib_error_t *
-snat_api_init (vlib_main_t * vm, snat_main_t * sm)
-{
- u8 *name;
- clib_error_t *error = 0;
-
- name = format (0, "snat_%08x%c", api_version, 0);
-
- /* Ask for a correctly-sized block of API message decode slots */
- sm->msg_id_base =
- vl_msg_api_get_msg_ids ((char *) name, VL_MSG_FIRST_AVAILABLE);
-
- error = snat_plugin_api_hookup (vm);
-
- /* Add our API messages to the global name_crc hash table */
- setup_message_id_table (sm, sm->api_main);
-
- plugin_custom_dump_configure (sm);
-
- vec_free (name);
-
- return error;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/plugins/snat/snat_det.c b/src/plugins/snat/snat_det.c
deleted file mode 100644
index 2d6fce85c0a..00000000000
--- a/src/plugins/snat/snat_det.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * snat_det.c - deterministic NAT
- *
- * Copyright (c) 2017 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.
- */
-/**
- * @file
- * @brief deterministic NAT
- */
-
-#include <snat/snat_det.h>
-
-
-/**
- * @brief Add/delete deterministic NAT mapping.
- *
- * Create bijective mapping of inside address to outside address and port range
- * pairs, with the purpose of enabling deterministic NAT to reduce logging in
- * CGN deployments.
- *
- * @param sm SNAT main.
- * @param in_addr Inside network address.
- * @param in_plen Inside network prefix length.
- * @param out_addr Outside network address.
- * @param out_plen Outside network prefix length.
- * @param is_add If 0 delete, otherwise add.
- */
-int
-snat_det_add_map (snat_main_t * sm, ip4_address_t * in_addr, u8 in_plen,
- ip4_address_t * out_addr, u8 out_plen, int is_add)
-{
- snat_det_map_t *det_map;
- static snat_det_session_t empty_snat_det_session = { 0 };
- snat_interface_t *i;
- ip4_address_t in_cmp, out_cmp;
- u8 found = 0;
-
- in_cmp.as_u32 = in_addr->as_u32 & ip4_main.fib_masks[in_plen];
- out_cmp.as_u32 = out_addr->as_u32 & ip4_main.fib_masks[out_plen];
- vec_foreach (det_map, sm->det_maps)
- {
- /* Checking for overlapping addresses to be added here */
- if (det_map->in_addr.as_u32 == in_cmp.as_u32 &&
- det_map->in_plen == in_plen &&
- det_map->out_addr.as_u32 == out_cmp.as_u32 &&
- det_map->out_plen == out_plen)
- {
- found = 1;
- break;
- }
- }
-
- /* If found, don't add again */
- if (found && is_add)
- return VNET_API_ERROR_VALUE_EXIST;
-
- /* If not found, don't delete */
- if (!found && !is_add)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- if (is_add)
- {
- pool_get (sm->det_maps, det_map);
- memset (det_map, 0, sizeof (*det_map));
- det_map->in_addr.as_u32 = in_cmp.as_u32;
- det_map->in_plen = in_plen;
- det_map->out_addr.as_u32 = out_cmp.as_u32;
- det_map->out_plen = out_plen;
- det_map->sharing_ratio = (1 << (32 - in_plen)) / (1 << (32 - out_plen));
- det_map->ports_per_host = (65535 - 1023) / det_map->sharing_ratio;
-
- vec_validate_init_empty (det_map->sessions,
- SNAT_DET_SES_PER_USER * (1 << (32 - in_plen)) -
- 1, empty_snat_det_session);
- }
- else
- {
- vec_free (det_map->sessions);
- vec_del1 (sm->det_maps, det_map - sm->det_maps);
- }
-
- /* Add/del external address range to FIB */
- /* *INDENT-OFF* */
- pool_foreach (i, sm->interfaces,
- ({
- if (i->is_inside)
- continue;
-
- snat_add_del_addr_to_fib(out_addr, out_plen, i->sw_if_index, is_add);
- break;
- }));
- /* *INDENT-ON* */
- return 0;
-}
-
-/**
- * @brief The 'snat-det-expire-walk' process's main loop.
- *
- * Check expire time for active sessions.
- */
-static uword
-snat_det_expire_walk_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
- vlib_frame_t * f)
-{
- snat_main_t *sm = &snat_main;
- snat_det_map_t *dm;
- snat_det_session_t *ses;
-
- while (sm->deterministic)
- {
- vlib_process_wait_for_event_or_clock (vm, 10.0);
- vlib_process_get_events (vm, NULL);
- u32 now = (u32) vlib_time_now (vm);
- /* *INDENT-OFF* */
- pool_foreach (dm, sm->det_maps,
- ({
- vec_foreach(ses, dm->sessions)
- {
- /* Delete if session expired */
- if (ses->in_port && (ses->expire < now))
- snat_det_ses_close (dm, ses);
- }
- }));
- /* *INDENT-ON* */
- }
-
- return 0;
-}
-
-static vlib_node_registration_t snat_det_expire_walk_node;
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (snat_det_expire_walk_node, static) = {
- .function = snat_det_expire_walk_fn,
- .type = VLIB_NODE_TYPE_PROCESS,
- .name =
- "snat-det-expire-walk",
-};
-/* *INDENT-ON* */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/plugins/snat/snat_det.h b/src/plugins/snat/snat_det.h
deleted file mode 100644
index f4fdb256637..00000000000
--- a/src/plugins/snat/snat_det.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * snat_det.h - deterministic nat definitions
- *
- * Copyright (c) 2017 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.
- */
-/**
- * @file
- * @brief deterministic NAT definitions
- */
-
-#ifndef __included_snat_det_h__
-#define __included_snat_det_h__
-
-#include <vnet/ip/ip.h>
-#include <snat/snat.h>
-#include <snat/snat_ipfix_logging.h>
-
-
-#define SNAT_DET_SES_PER_USER 1000
-
-
-int snat_det_add_map (snat_main_t * sm, ip4_address_t * in_addr, u8 in_plen,
- ip4_address_t * out_addr, u8 out_plen, int is_add);
-
-always_inline int
-is_addr_in_net (ip4_address_t * addr, ip4_address_t * net, u8 plen)
-{
- if (net->as_u32 == (addr->as_u32 & ip4_main.fib_masks[plen]))
- return 1;
- return 0;
-}
-
-always_inline snat_det_map_t *
-snat_det_map_by_user (snat_main_t * sm, ip4_address_t * user_addr)
-{
- snat_det_map_t *dm;
-
- /* *INDENT-OFF* */
- pool_foreach (dm, sm->det_maps,
- ({
- if (is_addr_in_net(user_addr, &dm->in_addr, dm->in_plen))
- return dm;
- }));
- /* *INDENT-ON* */
- return 0;
-}
-
-always_inline snat_det_map_t *
-snat_det_map_by_out (snat_main_t * sm, ip4_address_t * out_addr)
-{
- snat_det_map_t *dm;
-
- /* *INDENT-OFF* */
- pool_foreach (dm, sm->det_maps,
- ({
- if (is_addr_in_net(out_addr, &dm->out_addr, dm->out_plen))
- return dm;
- }));
- /* *INDENT-ON* */
- return 0;
-}
-
-always_inline void
-snat_det_forward (snat_det_map_t * dm, ip4_address_t * in_addr,
- ip4_address_t * out_addr, u16 * lo_port)
-{
- u32 in_offset, out_offset;
-
- in_offset = clib_net_to_host_u32 (in_addr->as_u32) -
- clib_net_to_host_u32 (dm->in_addr.as_u32);
- out_offset = in_offset / dm->sharing_ratio;
- out_addr->as_u32 =
- clib_host_to_net_u32 (clib_net_to_host_u32 (dm->out_addr.as_u32) +
- out_offset);
- *lo_port = 1024 + dm->ports_per_host * (in_offset % dm->sharing_ratio);
-}
-
-always_inline void
-snat_det_reverse (snat_det_map_t * dm, ip4_address_t * out_addr, u16 out_port,
- ip4_address_t * in_addr)
-{
- u32 in_offset1, in_offset2, out_offset;
-
- out_offset = clib_net_to_host_u32 (out_addr->as_u32) -
- clib_net_to_host_u32 (dm->out_addr.as_u32);
- in_offset1 = out_offset * dm->sharing_ratio;
- in_offset2 = (out_port - 1024) / dm->ports_per_host;
- in_addr->as_u32 =
- clib_host_to_net_u32 (clib_net_to_host_u32 (dm->in_addr.as_u32) +
- in_offset1 + in_offset2);
-}
-
-always_inline u32
-snat_det_user_ses_offset (ip4_address_t * addr, u8 plen)
-{
- return (clib_net_to_host_u32 (addr->as_u32) & pow2_mask (32 - plen)) *
- SNAT_DET_SES_PER_USER;
-}
-
-always_inline snat_det_session_t *
-snat_det_get_ses_by_out (snat_det_map_t * dm, ip4_address_t * in_addr,
- u64 out_key)
-{
- u32 user_offset;
- u16 i;
-
- user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
- for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
- {
- if (dm->sessions[i + user_offset].out.as_u64 == out_key)
- return &dm->sessions[i + user_offset];
- }
-
- return 0;
-}
-
-always_inline snat_det_session_t *
-snat_det_find_ses_by_in (snat_det_map_t * dm, ip4_address_t * in_addr,
- u16 in_port, snat_det_out_key_t out_key)
-{
- snat_det_session_t *ses;
- u32 user_offset;
- u16 i;
-
- user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
- for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
- {
- ses = &dm->sessions[i + user_offset];
- if (ses->in_port == in_port &&
- ses->out.ext_host_addr.as_u32 == out_key.ext_host_addr.as_u32 &&
- ses->out.ext_host_port == out_key.ext_host_port)
- return &dm->sessions[i + user_offset];
- }
-
- return 0;
-}
-
-always_inline snat_det_session_t *
-snat_det_ses_create (snat_det_map_t * dm, ip4_address_t * in_addr,
- u16 in_port, snat_det_out_key_t * out)
-{
- u32 user_offset;
- u16 i;
-
- user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
-
- for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
- {
- if (!dm->sessions[i + user_offset].in_port)
- {
- if (__sync_bool_compare_and_swap
- (&dm->sessions[i + user_offset].in_port, 0, in_port))
- {
- dm->sessions[i + user_offset].out.as_u64 = out->as_u64;
- dm->sessions[i + user_offset].state = SNAT_SESSION_UNKNOWN;
- dm->sessions[i + user_offset].expire = 0;
- __sync_add_and_fetch (&dm->ses_num, 1);
- return &dm->sessions[i + user_offset];
- }
- }
- }
-
- snat_ipfix_logging_max_entries_per_user (in_addr->as_u32);
- return 0;
-}
-
-always_inline void
-snat_det_ses_close (snat_det_map_t * dm, snat_det_session_t * ses)
-{
- if (__sync_bool_compare_and_swap (&ses->in_port, ses->in_port, 0))
- {
- ses->out.as_u64 = 0;
- __sync_add_and_fetch (&dm->ses_num, -1);
- }
-}
-
-#endif /* __included_snat_det_h__ */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/plugins/snat/snat_ipfix_logging.c b/src/plugins/snat/snat_ipfix_logging.c
deleted file mode 100644
index c68dc540d15..00000000000
--- a/src/plugins/snat/snat_ipfix_logging.c
+++ /dev/null
@@ -1,835 +0,0 @@
-/*
- * snat_ipfix_logging.c - NAT Events IPFIX logging
- *
- * 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.
- */
-
-#include <vnet/flow/flow_report.h>
-#include <vlibmemory/api.h>
-#include <snat/snat.h>
-#include <snat/snat_ipfix_logging.h>
-
-snat_ipfix_logging_main_t snat_ipfix_logging_main;
-
-#define NAT44_SESSION_CREATE_LEN 26
-#define NAT_ADDRESSES_EXHAUTED_LEN 13
-#define MAX_ENTRIES_PER_USER_LEN 17
-
-#define NAT44_SESSION_CREATE_FIELD_COUNT 8
-#define NAT_ADDRESSES_EXHAUTED_FIELD_COUNT 3
-#define MAX_ENTRIES_PER_USER_FIELD_COUNT 4
-
-typedef struct {
- u8 nat_event;
- u32 src_ip;
- u32 nat_src_ip;
- snat_protocol_t snat_proto;
- u16 src_port;
- u16 nat_src_port;
- u32 vrf_id;
-} snat_ipfix_logging_nat44_ses_args_t;
-
-typedef struct {
- u32 pool_id;
-} snat_ipfix_logging_addr_exhausted_args_t;
-
-typedef struct {
- u32 src_ip;
-} snat_ipfix_logging_max_entries_per_user_args_t;
-
-/**
- * @brief Create an IPFIX template packet rewrite string
- *
- * @param frm flow report main
- * @param fr flow report
- * @param collector_address collector address
- * @param src_address source address
- * @param collector_port collector
- * @param event NAT event ID
- * @param quota_event NAT quota exceeded event ID
- *
- * @returns template packet
- */
-static inline u8 *
-snat_template_rewrite (flow_report_main_t * frm,
- flow_report_t * fr,
- ip4_address_t * collector_address,
- ip4_address_t * src_address,
- u16 collector_port,
- nat_event_t event,
- quota_exceed_event_t quota_event)
-{
- snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
- ip4_header_t *ip;
- udp_header_t *udp;
- ipfix_message_header_t *h;
- ipfix_set_header_t *s;
- ipfix_template_header_t *t;
- ipfix_field_specifier_t *f;
- ipfix_field_specifier_t *first_field;
- u8 *rewrite = 0;
- ip4_ipfix_template_packet_t *tp;
- u32 field_count = 0;
- flow_report_stream_t *stream;
-
- stream = &frm->streams[fr->stream_index];
- silm->stream_index = fr->stream_index;
-
- if (event == NAT_ADDRESSES_EXHAUTED)
- {
- field_count = NAT_ADDRESSES_EXHAUTED_FIELD_COUNT;
- silm->addr_exhausted_template_id = fr->template_id;
- }
- else if (event == NAT44_SESSION_CREATE)
- {
- field_count = NAT44_SESSION_CREATE_FIELD_COUNT;
- silm->nat44_session_template_id = fr->template_id;
- }
- else if (event == QUOTA_EXCEEDED)
- {
- if (quota_event == MAX_ENTRIES_PER_USER)
- {
- field_count = MAX_ENTRIES_PER_USER_FIELD_COUNT;
- silm->max_entries_per_user_template_id = fr->template_id;
- }
- }
-
- /* allocate rewrite space */
- vec_validate_aligned (rewrite,
- sizeof (ip4_ipfix_template_packet_t)
- + field_count * sizeof (ipfix_field_specifier_t) - 1,
- CLIB_CACHE_LINE_BYTES);
-
- tp = (ip4_ipfix_template_packet_t *) rewrite;
- ip = (ip4_header_t *) & tp->ip4;
- udp = (udp_header_t *) (ip + 1);
- h = (ipfix_message_header_t *) (udp + 1);
- s = (ipfix_set_header_t *) (h + 1);
- t = (ipfix_template_header_t *) (s + 1);
- first_field = f = (ipfix_field_specifier_t *) (t + 1);
-
- ip->ip_version_and_header_length = 0x45;
- ip->ttl = 254;
- ip->protocol = IP_PROTOCOL_UDP;
- ip->src_address.as_u32 = src_address->as_u32;
- ip->dst_address.as_u32 = collector_address->as_u32;
- udp->src_port = clib_host_to_net_u16 (stream->src_port);
- udp->dst_port = clib_host_to_net_u16 (collector_port);
- udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
-
- /* FIXUP: message header export_time */
- h->domain_id = clib_host_to_net_u32 (stream->domain_id);
-
- /* Add TLVs to the template */
- if (event == NAT_ADDRESSES_EXHAUTED)
- {
- f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
- f++;
- f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
- f++;
- f->e_id_length = ipfix_e_id_length (0, natPoolId, 4);
- f++;
- }
- else if (event == NAT44_SESSION_CREATE)
- {
- f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
- f++;
- f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
- f++;
- f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
- f++;
- f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
- f++;
- f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
- f++;
- f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
- f++;
- f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
- f++;
- f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
- f++;
- }
- else if (event == QUOTA_EXCEEDED)
- {
- if (quota_event == MAX_ENTRIES_PER_USER)
- {
- f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
- 8);
- f++;
- f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
- f++;
- f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
- f++;
- f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
- f++;
- }
- }
-
- /* Back to the template packet... */
- ip = (ip4_header_t *) & tp->ip4;
- udp = (udp_header_t *) (ip + 1);
-
- ASSERT (f - first_field);
- /* Field count in this template */
- t->id_count = ipfix_id_count (fr->template_id, f - first_field);
-
- /* set length in octets */
- s->set_id_length =
- ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
-
- /* message length in octets */
- h->version_length = version_length ((u8 *) f - (u8 *) h);
-
- ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
- ip->checksum = ip4_header_checksum (ip);
-
- return rewrite;
-}
-
-u8 *
-snat_template_rewrite_addr_exhausted (flow_report_main_t * frm,
- flow_report_t * fr,
- ip4_address_t * collector_address,
- ip4_address_t * src_address,
- u16 collector_port)
-{
- return snat_template_rewrite (frm, fr, collector_address, src_address,
- collector_port, NAT_ADDRESSES_EXHAUTED, 0);
-}
-
-u8 *
-snat_template_rewrite_nat44_session (flow_report_main_t * frm,
- flow_report_t * fr,
- ip4_address_t * collector_address,
- ip4_address_t * src_address,
- u16 collector_port)
-{
- return snat_template_rewrite (frm, fr, collector_address, src_address,
- collector_port, NAT44_SESSION_CREATE, 0);
-}
-
-u8 *
-snat_template_rewrite_max_entries_per_usr (flow_report_main_t * frm,
- flow_report_t * fr,
- ip4_address_t * collector_address,
- ip4_address_t * src_address,
- u16 collector_port)
-{
- return snat_template_rewrite (frm, fr, collector_address, src_address,
- collector_port, QUOTA_EXCEEDED,
- MAX_ENTRIES_PER_USER);
-}
-
-static inline void
-snat_ipfix_header_create (flow_report_main_t * frm,
- vlib_buffer_t * b0,
- u32 * offset)
-{
- snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
- flow_report_stream_t *stream;
- ip4_ipfix_template_packet_t * tp;
- ipfix_message_header_t * h = 0;
- ipfix_set_header_t * s = 0;
- ip4_header_t * ip;
- udp_header_t * udp;
-
- stream = &frm->streams[silm->stream_index];
-
- b0->current_data = 0;
- b0->current_length = sizeof (*ip) + sizeof (*udp) + sizeof (*h) +
- sizeof (*s);
- b0->flags |= (VLIB_BUFFER_TOTAL_LENGTH_VALID | VLIB_BUFFER_FLOW_REPORT);
- vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index;
- tp = vlib_buffer_get_current (b0);
- ip = (ip4_header_t *) &tp->ip4;
- udp = (udp_header_t *) (ip+1);
- h = (ipfix_message_header_t *)(udp+1);
- s = (ipfix_set_header_t *)(h+1);
-
- ip->ip_version_and_header_length = 0x45;
- ip->ttl = 254;
- ip->protocol = IP_PROTOCOL_UDP;
- ip->flags_and_fragment_offset = 0;
- ip->src_address.as_u32 = frm->src_address.as_u32;
- ip->dst_address.as_u32 = frm->ipfix_collector.as_u32;
- udp->src_port = clib_host_to_net_u16 (stream->src_port);
- udp->dst_port = clib_host_to_net_u16 (frm->collector_port);
- udp->checksum = 0;
-
- h->export_time = clib_host_to_net_u32 (
- (u32) (((f64)frm->unix_time_0) + (vlib_time_now(frm->vlib_main) -
- frm->vlib_time_0)));
- h->sequence_number = clib_host_to_net_u32 (stream->sequence_number++);
- h->domain_id = clib_host_to_net_u32 (stream->domain_id);
-
- *offset = (u32) (((u8 *)(s+1)) - (u8 *)tp);
-}
-
-static inline void
-snat_ipfix_send (flow_report_main_t * frm,
- vlib_frame_t * f,
- vlib_buffer_t * b0,
- u16 template_id)
-{
- ip4_ipfix_template_packet_t * tp;
- ipfix_message_header_t * h = 0;
- ipfix_set_header_t * s = 0;
- ip4_header_t * ip;
- udp_header_t * udp;
- vlib_main_t * vm = frm->vlib_main;
-
- tp = vlib_buffer_get_current (b0);
- ip = (ip4_header_t *) & tp->ip4;
- udp = (udp_header_t *) (ip + 1);
- h = (ipfix_message_header_t *) (udp + 1);
- s = (ipfix_set_header_t *) (h + 1);
-
- s->set_id_length = ipfix_set_id_length (template_id,
- b0->current_length -
- (sizeof (*ip) + sizeof (*udp) +
- sizeof (*h)));
- h->version_length = version_length (b0->current_length -
- (sizeof (*ip) + sizeof (*udp)));
-
- ip->length = clib_host_to_net_u16 (b0->current_length);
- ip->checksum = ip4_header_checksum (ip);
- udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
-
- if (frm->udp_checksum)
- {
- udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
- if (udp->checksum == 0)
- udp->checksum = 0xffff;
- }
-
- ASSERT (ip->checksum == ip4_header_checksum (ip));
-
- vlib_put_frame_to_node (vm, ip4_lookup_node.index, f);
-}
-
-static void
-snat_ipfix_logging_nat44_ses (u8 nat_event, u32 src_ip, u32 nat_src_ip,
- snat_protocol_t snat_proto, u16 src_port,
- u16 nat_src_port, u32 vrf_id, int do_flush)
-{
- snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
- flow_report_main_t *frm = &flow_report_main;
- vlib_frame_t *f;
- vlib_buffer_t *b0 = 0;
- u32 bi0 = ~0;
- u32 offset;
- vlib_main_t * vm = frm->vlib_main;
- u64 now;
- vlib_buffer_free_list_t *fl;
- u8 proto = ~0;
-
- if (!silm->enabled)
- return;
-
- proto = snat_proto_to_ip_proto (snat_proto);
-
- now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
- now += silm->milisecond_time_0;
-
- b0 = silm->nat44_session_buffer;
-
- if (PREDICT_FALSE (b0 == 0))
- {
- if (do_flush)
- return;
-
- if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
- {
- clib_warning ("can't allocate buffer for NAT IPFIX event");
- return;
- }
-
- b0 = silm->nat44_session_buffer =
- vlib_get_buffer (vm, bi0);
- fl = vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
- vlib_buffer_init_for_free_list (b0, fl);
- VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
- offset = 0;
- }
- else
- {
- bi0 = vlib_get_buffer_index (vm, b0);
- offset = silm->nat44_session_next_record_offset;
- }
-
- f = silm->nat44_session_frame;
- if (PREDICT_FALSE (f == 0))
- {
- u32 * to_next;
- f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
- silm->nat44_session_frame = f;
- to_next = vlib_frame_vector_args (f);
- to_next[0] = bi0;
- f->n_vectors = 1;
- }
-
- if (PREDICT_FALSE (offset == 0))
- snat_ipfix_header_create (frm, b0, &offset);
-
- if (PREDICT_TRUE (do_flush == 0))
- {
- u64 time_stamp = clib_host_to_net_u64 (now);
- clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
- offset += sizeof (time_stamp);
-
- clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
- offset += sizeof (nat_event);
-
- clib_memcpy (b0->data + offset, &src_ip, sizeof (src_ip));
- offset += sizeof (src_ip);
-
- clib_memcpy (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
- offset += sizeof (nat_src_ip);
-
- clib_memcpy (b0->data + offset, &proto, sizeof (proto));
- offset += sizeof (proto);
-
- clib_memcpy (b0->data + offset, &src_port, sizeof (src_port));
- offset += sizeof (src_port);
-
- clib_memcpy (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
- offset += sizeof (nat_src_port);
-
- clib_memcpy (b0->data + offset, &vrf_id, sizeof(vrf_id));
- offset += sizeof (vrf_id);
-
- b0->current_length += NAT44_SESSION_CREATE_LEN;
- }
-
- if (PREDICT_FALSE (do_flush || (offset + NAT44_SESSION_CREATE_LEN) > frm->path_mtu))
- {
- snat_ipfix_send (frm, f, b0, silm->nat44_session_template_id);
- silm->nat44_session_frame = 0;
- silm->nat44_session_buffer = 0;
- offset = 0;
- }
- silm->nat44_session_next_record_offset = offset;
- }
-
-static void
-snat_ipfix_logging_addr_exhausted (u32 pool_id, int do_flush)
-{
- snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
- flow_report_main_t *frm = &flow_report_main;
- vlib_frame_t *f;
- vlib_buffer_t *b0 = 0;
- u32 bi0 = ~0;
- u32 offset;
- vlib_main_t * vm = frm->vlib_main;
- u64 now;
- vlib_buffer_free_list_t *fl;
- u8 nat_event = NAT_ADDRESSES_EXHAUTED;
-
- if (!silm->enabled)
- return;
-
- now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
- now += silm->milisecond_time_0;
-
- b0 = silm->addr_exhausted_buffer;
-
- if (PREDICT_FALSE (b0 == 0))
- {
- if (do_flush)
- return;
-
- if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
- {
- clib_warning ("can't allocate buffer for NAT IPFIX event");
- return;
- }
-
- b0 = silm->addr_exhausted_buffer =
- vlib_get_buffer (vm, bi0);
- fl = vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
- vlib_buffer_init_for_free_list (b0, fl);
- VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
- offset = 0;
- }
- else
- {
- bi0 = vlib_get_buffer_index (vm, b0);
- offset = silm->addr_exhausted_next_record_offset;
- }
-
- f = silm->addr_exhausted_frame;
- if (PREDICT_FALSE (f == 0))
- {
- u32 * to_next;
- f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
- silm->addr_exhausted_frame = f;
- to_next = vlib_frame_vector_args (f);
- to_next[0] = bi0;
- f->n_vectors = 1;
- }
-
- if (PREDICT_FALSE (offset == 0))
- snat_ipfix_header_create (frm, b0, &offset);
-
- if (PREDICT_TRUE (do_flush == 0))
- {
- u64 time_stamp = clib_host_to_net_u64 (now);
- clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
- offset += sizeof (time_stamp);
-
- clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
- offset += sizeof (nat_event);
-
- clib_memcpy (b0->data + offset, &pool_id, sizeof(pool_id));
- offset += sizeof (pool_id);
-
- b0->current_length += NAT_ADDRESSES_EXHAUTED_LEN;
- }
-
- if (PREDICT_FALSE (do_flush || (offset + NAT_ADDRESSES_EXHAUTED_LEN) > frm->path_mtu))
- {
- snat_ipfix_send (frm, f, b0, silm->addr_exhausted_template_id);
- silm->addr_exhausted_frame = 0;
- silm->addr_exhausted_buffer = 0;
- offset = 0;
- }
- silm->addr_exhausted_next_record_offset = offset;
-}
-
-static void
-snat_ipfix_logging_max_entries_per_usr (u32 src_ip, int do_flush)
-{
- snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
- flow_report_main_t *frm = &flow_report_main;
- vlib_frame_t *f;
- vlib_buffer_t *b0 = 0;
- u32 bi0 = ~0;
- u32 offset;
- vlib_main_t * vm = frm->vlib_main;
- u64 now;
- vlib_buffer_free_list_t *fl;
- u8 nat_event = QUOTA_EXCEEDED;
- u32 quota_event = MAX_ENTRIES_PER_USER;
-
- if (!silm->enabled)
- return;
-
- now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
- now += silm->milisecond_time_0;
-
- b0 = silm->max_entries_per_user_buffer;
-
- if (PREDICT_FALSE (b0 == 0))
- {
- if (do_flush)
- return;
-
- if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
- {
- clib_warning ("can't allocate buffer for NAT IPFIX event");
- return;
- }
-
- b0 = silm->max_entries_per_user_buffer =
- vlib_get_buffer (vm, bi0);
- fl = vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
- vlib_buffer_init_for_free_list (b0, fl);
- VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
- offset = 0;
- }
- else
- {
- bi0 = vlib_get_buffer_index (vm, b0);
- offset = silm->max_entries_per_user_next_record_offset;
- }
-
- f = silm->max_entries_per_user_frame;
- if (PREDICT_FALSE (f == 0))
- {
- u32 * to_next;
- f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
- silm->max_entries_per_user_frame = f;
- to_next = vlib_frame_vector_args (f);
- to_next[0] = bi0;
- f->n_vectors = 1;
- }
-
- if (PREDICT_FALSE (offset == 0))
- snat_ipfix_header_create (frm, b0, &offset);
-
- if (PREDICT_TRUE (do_flush == 0))
- {
- u64 time_stamp = clib_host_to_net_u64 (now);
- clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
- offset += sizeof (time_stamp);
-
- clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
- offset += sizeof (nat_event);
-
- clib_memcpy (b0->data + offset, &quota_event, sizeof(quota_event));
- offset += sizeof (quota_event);
-
- clib_memcpy (b0->data + offset, &src_ip, sizeof (src_ip));
- offset += sizeof (src_ip);
-
- b0->current_length += MAX_ENTRIES_PER_USER_LEN;
- }
-
- if (PREDICT_FALSE (do_flush || (offset + MAX_ENTRIES_PER_USER_LEN) > frm->path_mtu))
- {
- snat_ipfix_send (frm, f, b0, silm->max_entries_per_user_template_id);
- silm->max_entries_per_user_frame = 0;
- silm->max_entries_per_user_buffer = 0;
- offset = 0;
- }
- silm->max_entries_per_user_next_record_offset = offset;
-}
-
-static void
-snat_ipfix_logging_nat44_ses_rpc_cb (snat_ipfix_logging_nat44_ses_args_t *a)
-{
- snat_ipfix_logging_nat44_ses(a->nat_event, a->src_ip, a->nat_src_ip,
- a->snat_proto, a->src_port, a->nat_src_port,
- a->vrf_id, 0);
-}
-
-/**
- * @brief Generate NAT44 session create event
- *
- * @param src_ip source IPv4 address
- * @param nat_src_ip transaltes source IPv4 address
- * @param snat_proto SNAT transport protocol
- * @param src_port source port
- * @param nat_src_port translated source port
- * @param vrf_id VRF ID
- */
-void
-snat_ipfix_logging_nat44_ses_create (u32 src_ip,
- u32 nat_src_ip,
- snat_protocol_t snat_proto,
- u16 src_port,
- u16 nat_src_port,
- u32 vrf_id)
-{
- snat_ipfix_logging_nat44_ses_args_t a;
-
- a.nat_event = NAT44_SESSION_CREATE;
- a.src_ip = src_ip;
- a.nat_src_ip = nat_src_ip;
- a.snat_proto = snat_proto;
- a.src_port = src_port;
- a.nat_src_port = nat_src_port;
- a.vrf_id = vrf_id;
-
- vl_api_rpc_call_main_thread (snat_ipfix_logging_nat44_ses_rpc_cb, (u8 *) &a,
- sizeof (a));
-}
-
-/**
- * @brief Generate NAT44 session delete event
- *
- * @param src_ip source IPv4 address
- * @param nat_src_ip transaltes source IPv4 address
- * @param snat_proto SNAT transport protocol
- * @param src_port source port
- * @param nat_src_port translated source port
- * @param vrf_id VRF ID
- */
-void
-snat_ipfix_logging_nat44_ses_delete (u32 src_ip,
- u32 nat_src_ip,
- snat_protocol_t snat_proto,
- u16 src_port,
- u16 nat_src_port,
- u32 vrf_id)
-{
- snat_ipfix_logging_nat44_ses_args_t a;
-
- a.nat_event = NAT44_SESSION_DELETE;
- a.src_ip = src_ip;
- a.nat_src_ip = nat_src_ip;
- a.snat_proto = snat_proto;
- a.src_port = src_port;
- a.nat_src_port = nat_src_port;
- a.vrf_id = vrf_id;
-
- vl_api_rpc_call_main_thread (snat_ipfix_logging_nat44_ses_rpc_cb, (u8 *) &a,
- sizeof (a));
-}
-
-vlib_frame_t *
-snat_data_callback_nat44_session (flow_report_main_t * frm,
- flow_report_t * fr,
- vlib_frame_t * f,
- u32 * to_next,
- u32 node_index)
-{
- snat_ipfix_logging_nat44_ses(0, 0, 0, 0, 0, 0, 0, 1);
- return f;
-}
-
-static void
-snat_ipfix_logging_addr_exhausted_rpc_cb
- (snat_ipfix_logging_addr_exhausted_args_t * a)
-{
- snat_ipfix_logging_addr_exhausted(a->pool_id, 0);
-}
-
-/**
- * @brief Generate NAT addresses exhausted event
- *
- * @param pool_id NAT pool ID
- */
-void
-snat_ipfix_logging_addresses_exhausted(u32 pool_id)
-{
- //TODO: This event SHOULD be rate limited
- snat_ipfix_logging_addr_exhausted_args_t a;
-
- a.pool_id = pool_id;
-
- vl_api_rpc_call_main_thread (snat_ipfix_logging_addr_exhausted_rpc_cb,
- (u8 *) &a, sizeof (a));
-}
-
-vlib_frame_t *
-snat_data_callback_addr_exhausted (flow_report_main_t * frm,
- flow_report_t * fr,
- vlib_frame_t * f,
- u32 * to_next,
- u32 node_index)
-{
- snat_ipfix_logging_addr_exhausted(0, 1);
- return f;
-}
-
-static void
-snat_ipfix_logging_max_entries_per_usr_rpc_cb
- (snat_ipfix_logging_max_entries_per_user_args_t * a)
-{
- snat_ipfix_logging_max_entries_per_usr(a->src_ip, 0);
-}
-
-/**
- * @brief Generate maximum entries per user exceeded event
- *
- * @param src_ip source IPv4 address
- */
-void
-snat_ipfix_logging_max_entries_per_user(u32 src_ip)
-{
- //TODO: This event SHOULD be rate limited
- snat_ipfix_logging_max_entries_per_user_args_t a;
-
- a.src_ip = src_ip;
-
- vl_api_rpc_call_main_thread (snat_ipfix_logging_max_entries_per_usr_rpc_cb,
- (u8 *) &a, sizeof (a));
-}
-
-vlib_frame_t *
-snat_data_callback_max_entries_per_usr (flow_report_main_t * frm,
- flow_report_t * fr,
- vlib_frame_t * f,
- u32 * to_next,
- u32 node_index)
-{
- snat_ipfix_logging_max_entries_per_usr(0, 1);
- return f;
-}
-
-/**
- * @brief Enable/disable SNAT IPFIX logging
- *
- * @param enable 1 if enable, 0 if disable
- * @param domain_id observation domain ID
- * @param src_port source port number
- *
- * @returns 0 if success
- */
-int
-snat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port)
-{
- snat_main_t * sm = &snat_main;
- snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
- flow_report_main_t *frm = &flow_report_main;
- vnet_flow_report_add_del_args_t a;
- int rv;
- u8 e = enable ? 1 : 0;
-
- if (silm->enabled == e)
- return 0;
-
- silm->enabled = e;
-
- memset (&a, 0, sizeof (a));
- a.is_add = enable;
- a.domain_id = domain_id ? domain_id : 1;
- a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
-
- if (sm->deterministic)
- {
- a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
- a.flow_data_callback = snat_data_callback_max_entries_per_usr;
-
- rv = vnet_flow_report_add_del (frm, &a, NULL);
- if (rv)
- {
- clib_warning ("vnet_flow_report_add_del returned %d", rv);
- return -1;
- }
- }
- else
- {
- a.rewrite_callback = snat_template_rewrite_nat44_session;
- a.flow_data_callback = snat_data_callback_nat44_session;
-
- rv = vnet_flow_report_add_del (frm, &a, NULL);
- if (rv)
- {
- clib_warning ("vnet_flow_report_add_del returned %d", rv);
- return -1;
- }
-
- a.rewrite_callback = snat_template_rewrite_addr_exhausted;
- a.flow_data_callback = snat_data_callback_addr_exhausted;
-
- rv = vnet_flow_report_add_del (frm, &a, NULL);
- if (rv)
- {
- clib_warning ("vnet_flow_report_add_del returned %d", rv);
- return -1;
- }
- }
-
- return 0;
-}
-
-/**
- * @brief Initialize SNAT IPFIX logging
- *
- * @param vm vlib main
- */
-void
-snat_ipfix_logging_init (vlib_main_t * vm)
-{
- snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
-
- silm->enabled = 0;
-
- /* Set up time reference pair */
- silm->vlib_time_0 = vlib_time_now (vm);
- silm->milisecond_time_0 = unix_time_now_nsec () * 1e-6;
-}
diff --git a/src/plugins/snat/snat_ipfix_logging.h b/src/plugins/snat/snat_ipfix_logging.h
deleted file mode 100644
index 45c1a7bf8e1..00000000000
--- a/src/plugins/snat/snat_ipfix_logging.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * snat_ipfix_logging.h - NAT Events IPFIX logging
- *
- * 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.
- */
-#ifndef __included_snat_ipfix_logging_h__
-#define __included_snat_ipfix_logging_h__
-
-typedef enum {
- NAT_ADDRESSES_EXHAUTED = 3,
- NAT44_SESSION_CREATE = 4,
- NAT44_SESSION_DELETE = 5,
- NAT_PORTS_EXHAUSTED = 12,
- QUOTA_EXCEEDED = 13,
-} nat_event_t;
-
-typedef enum {
- MAX_ENTRIES_PER_USER = 3,
-} quota_exceed_event_t;
-
-typedef struct {
- /** S-NAT IPFIX logging enabled */
- u8 enabled;
-
- /** ipfix buffers under construction */
- vlib_buffer_t *nat44_session_buffer;
- vlib_buffer_t *addr_exhausted_buffer;
- vlib_buffer_t *max_entries_per_user_buffer;
-
- /** frames containing ipfix buffers */
- vlib_frame_t *nat44_session_frame;
- vlib_frame_t *addr_exhausted_frame;
- vlib_frame_t *max_entries_per_user_frame;
-
- /** next record offset */
- u32 nat44_session_next_record_offset;
- u32 addr_exhausted_next_record_offset;
- u32 max_entries_per_user_next_record_offset;
-
- /** Time reference pair */
- u64 milisecond_time_0;
- f64 vlib_time_0;
-
- /** template IDs */
- u16 nat44_session_template_id;
- u16 addr_exhausted_template_id;
- u16 max_entries_per_user_template_id;
-
- /** stream index */
- u32 stream_index;
-} snat_ipfix_logging_main_t;
-
-extern snat_ipfix_logging_main_t snat_ipfix_logging_main;
-
-void snat_ipfix_logging_init (vlib_main_t * vm);
-int snat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port);
-void snat_ipfix_logging_nat44_ses_create (u32 src_ip, u32 nat_src_ip,
- snat_protocol_t snat_proto,
- u16 src_port, u16 nat_src_port,
- u32 vrf_id);
-void snat_ipfix_logging_nat44_ses_delete (u32 src_ip, u32 nat_src_ip,
- snat_protocol_t snat_proto,
- u16 src_port, u16 nat_src_port,
- u32 vrf_id);
-void snat_ipfix_logging_addresses_exhausted(u32 pool_id);
-void snat_ipfix_logging_max_entries_per_user(u32 src_ip);
-
-#endif /* __included_snat_ipfix_logging_h__ */
diff --git a/src/plugins/snat/snat_msg_enum.h b/src/plugins/snat/snat_msg_enum.h
deleted file mode 100644
index 2c76fd51158..00000000000
--- a/src/plugins/snat/snat_msg_enum.h
+++ /dev/null
@@ -1,31 +0,0 @@
-
-/*
- * snat_msg_enum.h - skeleton vpp engine plug-in message enumeration
- *
- * Copyright (c) <current-year> <your-organization>
- * 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.
- */
-#ifndef included_snat_msg_enum_h
-#define included_snat_msg_enum_h
-
-#include <vppinfra/byte_order.h>
-
-#define vl_msg_id(n,h) n,
-typedef enum {
-#include <snat/snat_all_api_h.h>
- /* We'll want to know how many messages IDs we need... */
- VL_MSG_FIRST_AVAILABLE,
-} vl_msg_id_t;
-#undef vl_msg_id
-
-#endif /* included_snat_msg_enum_h */
diff --git a/src/plugins/snat/snat_test.c b/src/plugins/snat/snat_test.c
deleted file mode 100644
index 905b8fac66c..00000000000
--- a/src/plugins/snat/snat_test.c
+++ /dev/null
@@ -1,1167 +0,0 @@
-
-/*
- * snat.c - skeleton vpp-api-test plug-in
- *
- * Copyright (c) <current-year> <your-organization>
- * 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.
- */
-#include <vat/vat.h>
-#include <vlibapi/api.h>
-#include <vlibmemory/api.h>
-#include <vlibsocket/api.h>
-#include <vppinfra/error.h>
-#include <vnet/ip/ip.h>
-#include <snat/snat.h>
-
-#define __plugin_msg_base snat_test_main.msg_id_base
-#include <vlibapi/vat_helper_macros.h>
-
-uword unformat_sw_if_index (unformat_input_t * input, va_list * args);
-
-/* Declare message IDs */
-#include <snat/snat_msg_enum.h>
-
-/* define message structures */
-#define vl_typedefs
-#include <snat/snat_all_api_h.h>
-#undef vl_typedefs
-
-/* declare message handlers for each api */
-
-#define vl_endianfun /* define message structures */
-#include <snat/snat_all_api_h.h>
-#undef vl_endianfun
-
-/* instantiate all the print functions we know about */
-#define vl_print(handle, ...)
-#define vl_printfun
-#include <snat/snat_all_api_h.h>
-#undef vl_printfun
-
-/* Get the API version number. */
-#define vl_api_version(n,v) static u32 api_version=(v);
-#include <snat/snat_all_api_h.h>
-#undef vl_api_version
-
-typedef struct {
- /* API message ID base */
- u16 msg_id_base;
- vat_main_t *vat_main;
-} snat_test_main_t;
-
-snat_test_main_t snat_test_main;
-
-#define foreach_standard_reply_retval_handler \
-_(snat_add_address_range_reply) \
-_(snat_interface_add_del_feature_reply) \
-_(snat_add_static_mapping_reply) \
-_(snat_set_workers_reply) \
-_(snat_add_del_interface_addr_reply) \
-_(snat_ipfix_enable_disable_reply) \
-_(snat_add_det_map_reply) \
-_(snat_det_set_timeouts_reply) \
-_(snat_det_close_session_out_reply) \
-_(snat_det_close_session_in_reply)
-
-#define _(n) \
- static void vl_api_##n##_t_handler \
- (vl_api_##n##_t * mp) \
- { \
- vat_main_t * vam = snat_test_main.vat_main; \
- i32 retval = ntohl(mp->retval); \
- if (vam->async_mode) { \
- vam->async_errors += (retval < 0); \
- } else { \
- vam->retval = retval; \
- vam->result_ready = 1; \
- } \
- }
-foreach_standard_reply_retval_handler;
-#undef _
-
-/*
- * Table of message reply handlers, must include boilerplate handlers
- * we just generated
- */
-#define foreach_vpe_api_reply_msg \
-_(SNAT_ADD_ADDRESS_RANGE_REPLY, snat_add_address_range_reply) \
-_(SNAT_INTERFACE_ADD_DEL_FEATURE_REPLY, \
- snat_interface_add_del_feature_reply) \
-_(SNAT_ADD_STATIC_MAPPING_REPLY, snat_add_static_mapping_reply) \
-_(SNAT_CONTROL_PING_REPLY, snat_control_ping_reply) \
-_(SNAT_STATIC_MAPPING_DETAILS, snat_static_mapping_details) \
-_(SNAT_SHOW_CONFIG_REPLY, snat_show_config_reply) \
-_(SNAT_ADDRESS_DETAILS, snat_address_details) \
-_(SNAT_INTERFACE_DETAILS, snat_interface_details) \
-_(SNAT_SET_WORKERS_REPLY, snat_set_workers_reply) \
-_(SNAT_WORKER_DETAILS, snat_worker_details) \
-_(SNAT_ADD_DEL_INTERFACE_ADDR_REPLY, \
- snat_add_del_interface_addr_reply) \
-_(SNAT_INTERFACE_ADDR_DETAILS, snat_interface_addr_details) \
-_(SNAT_IPFIX_ENABLE_DISABLE_REPLY, \
- snat_ipfix_enable_disable_reply) \
-_(SNAT_USER_DETAILS, snat_user_details) \
-_(SNAT_USER_SESSION_DETAILS, snat_user_session_details) \
-_(SNAT_ADD_DET_MAP_REPLY, snat_add_det_map_reply) \
-_(SNAT_DET_FORWARD_REPLY, snat_det_forward_reply) \
-_(SNAT_DET_REVERSE_REPLY, snat_det_reverse_reply) \
-_(SNAT_DET_MAP_DETAILS, snat_det_map_details) \
-_(SNAT_DET_SET_TIMEOUTS_REPLY, snat_det_set_timeouts_reply) \
-_(SNAT_DET_GET_TIMEOUTS_REPLY, snat_det_get_timeouts_reply) \
-_(SNAT_DET_CLOSE_SESSION_OUT_REPLY, \
- snat_det_close_session_out_reply) \
-_(SNAT_DET_CLOSE_SESSION_IN_REPLY, \
- snat_det_close_session_in_reply) \
-_(SNAT_DET_SESSION_DETAILS, snat_det_session_details)
-
-static int api_snat_add_address_range (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- ip4_address_t start_addr, end_addr;
- u32 start_host_order, end_host_order;
- vl_api_snat_add_address_range_t * mp;
- u8 is_add = 1;
- int count;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "%U - %U",
- unformat_ip4_address, &start_addr,
- unformat_ip4_address, &end_addr))
- ;
- else if (unformat (i, "%U", unformat_ip4_address, &start_addr))
- end_addr = start_addr;
- else if (unformat (i, "del"))
- is_add = 0;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
- }
-
- start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
- end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
-
- if (end_host_order < start_host_order)
- {
- errmsg ("end address less than start address\n");
- return -99;
- }
-
- count = (end_host_order - start_host_order) + 1;
-
- if (count > 1024)
- {
- errmsg ("%U - %U, %d addresses...\n",
- format_ip4_address, &start_addr,
- format_ip4_address, &end_addr,
- count);
- }
-
- M(SNAT_ADD_ADDRESS_RANGE, mp);
-
- memcpy (mp->first_ip_address, &start_addr, 4);
- memcpy (mp->last_ip_address, &end_addr, 4);
- mp->is_ip4 = 1;
- mp->is_add = is_add;
-
- S(mp);
- W (ret);
- return ret;
-}
-
-static int api_snat_interface_add_del_feature (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_interface_add_del_feature_t * mp;
- u32 sw_if_index;
- u8 sw_if_index_set = 0;
- u8 is_inside = 1;
- u8 is_add = 1;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "sw_if_index %d", &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "out"))
- is_inside = 0;
- else if (unformat (i, "in"))
- is_inside = 1;
- else if (unformat (i, "del"))
- is_add = 0;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
- }
-
- if (sw_if_index_set == 0)
- {
- errmsg ("interface / sw_if_index required\n");
- return -99;
- }
-
- M(SNAT_INTERFACE_ADD_DEL_FEATURE, mp);
- mp->sw_if_index = ntohl(sw_if_index);
- mp->is_add = is_add;
- mp->is_inside = is_inside;
-
- S(mp);
- W (ret);
- return ret;
-}
-
-static int api_snat_add_static_mapping(vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_add_static_mapping_t * mp;
- u8 external_addr_set = 0;
- u8 local_addr_set = 0;
- u8 is_add = 1;
- u8 addr_only = 1;
- ip4_address_t local_addr, external_addr;
- u32 local_port = 0, external_port = 0, vrf_id = ~0;
- u32 sw_if_index = ~0;
- u8 sw_if_index_set = 0;
- u32 proto = ~0;
- u8 proto_set = 0;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "local_addr %U", unformat_ip4_address, &local_addr))
- local_addr_set = 1;
- else if (unformat (i, "external_addr %U", unformat_ip4_address,
- &external_addr))
- external_addr_set = 1;
- else if (unformat (i, "local_port %u", &local_port))
- addr_only = 0;
- else if (unformat (i, "external_port %u", &external_port))
- addr_only = 0;
- else if (unformat (i, "external_if %U", unformat_sw_if_index, vam,
- &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "external_sw_if_index %d", &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "vrf %u", &vrf_id))
- ;
- else if (unformat (i, "protocol %u", &proto))
- proto_set = 1;
- else if (unformat (i, "del"))
- is_add = 0;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
- }
-
- if (!addr_only && !proto_set)
- {
- errmsg ("protocol required\n");
- return -99;
- }
-
- if (!local_addr_set)
- {
- errmsg ("local addr required\n");
- return -99;
- }
- if (!external_addr_set && !sw_if_index_set)
- {
- errmsg ("external addr or interface required\n");
- return -99;
- }
-
- M(SNAT_ADD_STATIC_MAPPING, mp);
- mp->is_add = is_add;
- mp->is_ip4 = 1;
- mp->addr_only = addr_only;
- mp->local_port = ntohs ((u16) local_port);
- mp->external_port = ntohs ((u16) external_port);
- mp->external_sw_if_index = ntohl (sw_if_index);
- mp->vrf_id = ntohl (vrf_id);
- mp->protocol = (u8) proto;
- memcpy (mp->local_ip_address, &local_addr, 4);
- memcpy (mp->external_ip_address, &external_addr, 4);
-
- S(mp);
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_control_ping_reply_t_handler
- (vl_api_snat_control_ping_reply_t * mp)
-{
- vat_main_t *vam = &vat_main;
- i32 retval = ntohl (mp->retval);
- if (vam->async_mode)
- {
- vam->async_errors += (retval < 0);
- }
- else
- {
- vam->retval = retval;
- vam->result_ready = 1;
- }
-}
-
-static void vl_api_snat_static_mapping_details_t_handler
- (vl_api_snat_static_mapping_details_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
-
- if (mp->addr_only && mp->external_sw_if_index != ~0)
- fformat (vam->ofp, "%15U%6s%15d%6s%11d%6d\n",
- format_ip4_address, &mp->local_ip_address, "",
- ntohl (mp->external_sw_if_index), "",
- ntohl (mp->vrf_id),
- mp->protocol);
- else if (mp->addr_only && mp->external_sw_if_index == ~0)
- fformat (vam->ofp, "%15U%6s%15U%6s%11d%6d\n",
- format_ip4_address, &mp->local_ip_address, "",
- format_ip4_address, &mp->external_ip_address, "",
- ntohl (mp->vrf_id),
- mp->protocol);
- else if (!mp->addr_only && mp->external_sw_if_index != ~0)
- fformat (vam->ofp, "%15U%6d%15d%6d%11d%6d\n",
- format_ip4_address, &mp->local_ip_address,
- ntohs (mp->local_port),
- ntohl (mp->external_sw_if_index),
- ntohs (mp->external_port),
- ntohl (mp->vrf_id),
- mp->protocol);
- else
- fformat (vam->ofp, "%15U%6d%15U%6d%11d%6d\n",
- format_ip4_address, &mp->local_ip_address,
- ntohs (mp->local_port),
- format_ip4_address, &mp->external_ip_address,
- ntohs (mp->external_port),
- ntohl (mp->vrf_id),
- mp->protocol);
-
-}
-
-static int api_snat_static_mapping_dump(vat_main_t * vam)
-{
- vl_api_snat_static_mapping_dump_t * mp;
- vl_api_snat_control_ping_t *mp_ping;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_static_mapping_dump");
- return -99;
- }
-
- fformat (vam->ofp, "%21s%21s\n", "local", "external");
- fformat (vam->ofp, "%15s%6s%15s%6s%11s%6s\n", "address", "port",
- "address/if_idx", "port", "vrf", "proto");
-
- M(SNAT_STATIC_MAPPING_DUMP, mp);
- S(mp);
-
- /* Use a control ping for synchronization */
- M(SNAT_CONTROL_PING, mp_ping);
- S(mp_ping);
-
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_show_config_reply_t_handler
- (vl_api_snat_show_config_reply_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
- i32 retval = ntohl (mp->retval);
-
- if (retval >= 0)
- {
- fformat (vam->ofp, "translation hash buckets %d\n",
- ntohl (mp->translation_buckets));
- fformat (vam->ofp, "translation hash memory %d\n",
- ntohl (mp->translation_memory_size));
- fformat (vam->ofp, "user hash buckets %d\n", ntohl (mp->user_buckets));
- fformat (vam->ofp, "user hash memory %d\n", ntohl (mp->user_memory_size));
- fformat (vam->ofp, "max translations per user %d\n",
- ntohl (mp->max_translations_per_user));
- fformat (vam->ofp, "outside VRF id %d\n", ntohl (mp->outside_vrf_id));
- fformat (vam->ofp, "inside VRF id %d\n", ntohl (mp->inside_vrf_id));
- if (mp->static_mapping_only)
- {
- fformat (vam->ofp, "static mapping only");
- if (mp->static_mapping_connection_tracking)
- fformat (vam->ofp, " connection tracking");
- fformat (vam->ofp, "\n");
- }
- }
- vam->retval = retval;
- vam->result_ready = 1;
-}
-
-static int api_snat_show_config(vat_main_t * vam)
-{
- vl_api_snat_show_config_t * mp;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_show_config");
- return -99;
- }
-
- M(SNAT_SHOW_CONFIG, mp);
- S(mp);
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_address_details_t_handler
- (vl_api_snat_address_details_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
-
- fformat (vam->ofp, "%U\n", format_ip4_address, &mp->ip_address);
-}
-
-static int api_snat_address_dump(vat_main_t * vam)
-{
- vl_api_snat_address_dump_t * mp;
- vl_api_snat_control_ping_t *mp_ping;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_address_dump");
- return -99;
- }
-
- M(SNAT_ADDRESS_DUMP, mp);
- S(mp);
-
- /* Use a control ping for synchronization */
- M(SNAT_CONTROL_PING, mp_ping);
- S(mp_ping);
-
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_interface_details_t_handler
- (vl_api_snat_interface_details_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
-
- fformat (vam->ofp, "sw_if_index %d %s\n", ntohl (mp->sw_if_index),
- mp->is_inside ? "in" : "out");
-}
-
-static int api_snat_interface_dump(vat_main_t * vam)
-{
- vl_api_snat_interface_dump_t * mp;
- vl_api_snat_control_ping_t *mp_ping;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_address_dump");
- return -99;
- }
-
- M(SNAT_INTERFACE_DUMP, mp);
- S(mp);
-
- /* Use a control ping for synchronization */
- M(SNAT_CONTROL_PING, mp_ping);
- S(mp_ping);
-
- W (ret);
- return ret;
-}
-
-static int api_snat_set_workers (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_set_workers_t * mp;
- uword *bitmap;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "%U", unformat_bitmap_list, &bitmap))
- ;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
- }
-
- M(SNAT_SET_WORKERS, mp);
- mp->worker_mask = clib_host_to_net_u64 (bitmap[0]);
-
- S(mp);
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_worker_details_t_handler
- (vl_api_snat_worker_details_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
-
- fformat (vam->ofp, "worker_index %d (%s at lcore %u)\n",
- ntohl (mp->worker_index), mp->name, ntohl (mp->lcore_id));
-}
-
-static int api_snat_worker_dump(vat_main_t * vam)
-{
- vl_api_snat_worker_dump_t * mp;
- vl_api_snat_control_ping_t *mp_ping;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_address_dump");
- return -99;
- }
-
- M(SNAT_WORKER_DUMP, mp);
- S(mp);
-
- /* Use a control ping for synchronization */
- M(SNAT_CONTROL_PING, mp_ping);
- S(mp_ping);
-
- W (ret);
- return ret;
-}
-
-static int api_snat_add_del_interface_addr (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_add_del_interface_addr_t * mp;
- u32 sw_if_index;
- u8 sw_if_index_set = 0;
- u8 is_add = 1;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "sw_if_index %d", &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "del"))
- is_add = 0;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
- }
-
- if (sw_if_index_set == 0)
- {
- errmsg ("interface / sw_if_index required\n");
- return -99;
- }
-
- M(SNAT_ADD_DEL_INTERFACE_ADDR, mp);
- mp->sw_if_index = ntohl(sw_if_index);
- mp->is_add = is_add;
-
- S(mp);
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_interface_addr_details_t_handler
- (vl_api_snat_interface_addr_details_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
-
- fformat (vam->ofp, "sw_if_index %d\n", ntohl (mp->sw_if_index));
-}
-
-static int api_snat_interface_addr_dump(vat_main_t * vam)
-{
- vl_api_snat_interface_addr_dump_t * mp;
- vl_api_snat_control_ping_t *mp_ping;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_address_dump");
- return -99;
- }
-
- M(SNAT_INTERFACE_ADDR_DUMP, mp);
- S(mp);
-
- /* Use a control ping for synchronization */
- M(SNAT_CONTROL_PING, mp_ping);
- S(mp_ping);
-
- W (ret);
- return ret;
-}
-
-static int api_snat_ipfix_enable_disable (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_ipfix_enable_disable_t * mp;
- u32 domain_id = 0;
- u32 src_port = 0;
- u8 enable = 1;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "domain %d", &domain_id))
- ;
- else if (unformat (i, "src_port %d", &src_port))
- ;
- else if (unformat (i, "disable"))
- enable = 0;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
- }
-
- M(SNAT_IPFIX_ENABLE_DISABLE, mp);
- mp->domain_id = htonl(domain_id);
- mp->src_port = htons((u16) src_port);
- mp->enable = enable;
-
- S(mp);
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_user_session_details_t_handler
- (vl_api_snat_user_session_details_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
-
- fformat(vam->ofp, "%s session %U:%d to %U:%d protocol id %d "
- "total packets %d total bytes %d\n",
- mp->is_static ? "static" : "dynamic",
- format_ip4_address, mp->inside_ip_address, ntohl(mp->inside_port),
- format_ip4_address, mp->outside_ip_address, ntohl(mp->outside_port),
- ntohl(mp->protocol), ntohl(mp->total_pkts), ntohl(mp->total_bytes));
-}
-
-static int api_snat_user_session_dump(vat_main_t * vam)
-{
- unformat_input_t* i = vam->input;
- vl_api_snat_user_session_dump_t * mp;
- vl_api_snat_control_ping_t *mp_ping;
- ip4_address_t addr;
- u32 vrf_id = ~0;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_address_dump");
- return -99;
- }
-
- if (unformat (i, "ip_address %U vrf_id %d",
- unformat_ip4_address, &addr, &vrf_id))
- ;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
-
- M(SNAT_USER_SESSION_DUMP, mp);
- S(mp);
-
- /* Use a control ping for synchronization */
- M(SNAT_CONTROL_PING, mp_ping);
- memset(mp->ip_address, 0, 16);
- clib_memcpy(mp->ip_address, &addr, 4);
- mp->vrf_id = htonl(vrf_id);
- mp->is_ip4 = 1;
- S(mp_ping);
-
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_user_details_t_handler
- (vl_api_snat_user_details_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
-
- fformat(vam->ofp, "user with ip %U with vrf_id %d "
- "with %d sessions and %d static sessions\n",
- format_ip4_address, mp->ip_address, ntohl(mp->vrf_id),
- ntohl(mp->nsessions), ntohl(mp->nstaticsessions));
-}
-
-static int api_snat_user_dump(vat_main_t * vam)
-{
- vl_api_snat_user_dump_t * mp;
- vl_api_snat_control_ping_t *mp_ping;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_address_dump");
- return -99;
- }
-
- M(SNAT_USER_DUMP, mp);
- S(mp);
-
- /* Use a control ping for synchronization */
- M(SNAT_CONTROL_PING, mp_ping);
- S(mp_ping);
-
- W (ret);
- return ret;
-}
-
-static int api_snat_add_det_map (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_add_det_map_t * mp;
- ip4_address_t in_addr, out_addr;
- u32 in_plen, out_plen;
- u8 is_add = 1;
- int ret;
-
- if (unformat (i, "in %U/%d out %U/%d",
- unformat_ip4_address, &in_addr, &in_plen,
- unformat_ip4_address, &out_addr, &out_plen))
- ;
- else if (unformat (i, "del"))
- is_add = 0;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
-
- M(SNAT_ADD_DET_MAP, mp);
- clib_memcpy(mp->in_addr, &in_addr, 4);
- mp->in_plen = in_plen;
- clib_memcpy(mp->out_addr, &out_addr, 4);
- mp->out_plen = out_plen;
- mp->is_add = is_add;
-
- S(mp);
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_det_forward_reply_t_handler
- (vl_api_snat_det_forward_reply_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
- i32 retval = ntohl(mp->retval);
-
- if (retval >= 0)
- {
- fformat (vam->ofp, "outside address %U", format_ip4_address, &mp->out_addr);
- fformat (vam->ofp, " outside port range start %d", ntohs(mp->out_port_lo));
- fformat (vam->ofp, " outside port range end %d\n", ntohs(mp->out_port_hi));
- }
-
- vam->retval = retval;
- vam->result_ready = 1;
-}
-
-static int api_snat_det_forward (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_det_forward_t * mp;
- ip4_address_t in_addr;
- int ret;
-
- if (unformat (i, "%U", unformat_ip4_address, &in_addr))
- ;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
-
- M(SNAT_DET_FORWARD, mp);
- clib_memcpy(mp->in_addr, &in_addr, 4);
-
- S(mp);
- W(ret);
- return ret;
-}
-
-static void vl_api_snat_det_reverse_reply_t_handler
- (vl_api_snat_det_reverse_reply_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
- i32 retval = ntohl(mp->retval);
-
- if (retval >= 0)
- {
- fformat (vam->ofp, "inside address %U\n", format_ip4_address, &mp->in_addr);
- }
-
- vam->retval = retval;
- vam->result_ready = 1;
-}
-
-static int api_snat_det_reverse (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_det_reverse_t * mp;
- ip4_address_t out_addr;
- u16 out_port;
- int ret;
-
- if (unformat (i, "%U %d", unformat_ip4_address, &out_addr, &out_port))
- ;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
-
- M(SNAT_DET_REVERSE, mp);
- clib_memcpy(mp->out_addr, &out_addr, 4);
- mp->out_port = htons(out_port);
-
- S(mp);
- W(ret);
- return ret;
-}
-
-static void vl_api_snat_det_map_details_t_handler
- (vl_api_snat_det_map_details_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
-
- fformat (vam->ofp, "Deterministic S-NAT mapping in %U/%d out %U/%d "
- "ports per host %d sharing ratio %d "
- "number of sessions %d",
- format_ip4_address, mp->in_addr, mp->in_plen,
- format_ip4_address, mp->out_addr, mp->out_plen,
- ntohs(mp->ports_per_host), ntohl(mp->sharing_ratio),
- ntohl(mp->ses_num));
-}
-
-static int api_snat_det_map_dump(vat_main_t * vam)
-{
- vl_api_snat_det_map_dump_t * mp;
- vl_api_snat_control_ping_t *mp_ping;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_det_map_dump");
- return -99;
- }
-
- M(SNAT_DET_MAP_DUMP, mp);
- S(mp);
-
- /* Use a control ping for synchronization */
- M(SNAT_CONTROL_PING, mp_ping);
- S(mp_ping);
-
- W (ret);
- return ret;
-}
-
-static int api_snat_det_set_timeouts (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_det_set_timeouts_t * mp;
- u32 udp = SNAT_UDP_TIMEOUT;
- u32 tcp_established = SNAT_TCP_ESTABLISHED_TIMEOUT;
- u32 tcp_transitory = SNAT_TCP_TRANSITORY_TIMEOUT;
- u32 icmp = SNAT_ICMP_TIMEOUT;
- int ret;
-
- if (unformat (i, "udp %d", &udp))
- ;
- else if (unformat (i, "tcp_established %d", &tcp_established))
- ;
- else if (unformat (i, "tcp_transitory %d", &tcp_transitory))
- ;
- else if (unformat (i, "icmp %d", &icmp))
- ;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
-
- M(SNAT_DET_SET_TIMEOUTS, mp);
- mp->udp = htonl(udp);
- mp->tcp_established = htonl(tcp_established);
- mp->tcp_transitory = htonl(tcp_transitory);
- mp->icmp = htonl(icmp);
-
- S(mp);
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_det_get_timeouts_reply_t_handler
- (vl_api_snat_det_get_timeouts_reply_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
- i32 retval = ntohl (mp->retval);
-
- if (retval >= 0)
- {
- fformat (vam->ofp, "udp timeout: %dsec\n", ntohl (mp->udp));
- fformat (vam->ofp, "tcp-established timeout: %dsec",
- ntohl (mp->tcp_established));
- fformat (vam->ofp, "tcp-transitory timeout: %dsec",
- ntohl (mp->tcp_transitory));
- fformat (vam->ofp, "icmp timeout: %dsec", ntohl (mp->icmp));
- }
- vam->retval = retval;
- vam->result_ready = 1;
-}
-
-static int api_snat_det_get_timeouts(vat_main_t * vam)
-{
- vl_api_snat_det_get_timeouts_t * mp;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_show_config");
- return -99;
- }
-
- M(SNAT_DET_GET_TIMEOUTS, mp);
- S(mp);
- W (ret);
- return ret;
-}
-
-static int api_snat_det_close_session_out (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_det_close_session_out_t * mp;
- ip4_address_t out_addr, ext_addr;
- u16 out_port, ext_port;
- int ret;
-
- if (unformat (i, "%U:%d %U:%d",
- unformat_ip4_address, &out_addr, &out_port,
- unformat_ip4_address, &ext_addr, &ext_port))
- ;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
-
- M(SNAT_DET_CLOSE_SESSION_OUT, mp);
- clib_memcpy(mp->out_addr, &out_addr, 4);
- mp->out_port = ntohs(out_port);
- clib_memcpy(mp->ext_addr, &ext_addr, 4);
- mp->ext_port = ntohs(ext_port);
-
- S(mp);
- W (ret);
- return ret;
-}
-
-static int api_snat_det_close_session_in (vat_main_t * vam)
-{
- unformat_input_t * i = vam->input;
- vl_api_snat_det_close_session_in_t * mp;
- ip4_address_t in_addr, ext_addr;
- u16 in_port, ext_port;
- int ret;
-
- if (unformat (i, "%U:%d %U:%d",
- unformat_ip4_address, &in_addr, &in_port,
- unformat_ip4_address, &ext_addr, &ext_port))
- ;
- else
- {
- clib_warning("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
-
- M(SNAT_DET_CLOSE_SESSION_IN, mp);
- clib_memcpy(mp->in_addr, &in_addr, 4);
- mp->in_port = ntohs(in_port);
- clib_memcpy(mp->ext_addr, &ext_addr, 4);
- mp->ext_port = ntohs(ext_port);
-
- S(mp);
- W (ret);
- return ret;
-}
-
-static void vl_api_snat_det_session_details_t_handler
- (vl_api_snat_det_session_details_t *mp)
-{
- snat_test_main_t * sm = &snat_test_main;
- vat_main_t *vam = sm->vat_main;
-
- fformat(vam->ofp, "deterministic session, external host address %U, "
- "external host port %d, outer port %d, inside port %d",
- format_ip4_address, mp->ext_addr, mp->ext_port,
- mp->out_port, mp->in_port);
-}
-
-static int api_snat_det_session_dump(vat_main_t * vam)
-{
- unformat_input_t* i = vam->input;
- vl_api_snat_det_session_dump_t * mp;
- vl_api_snat_control_ping_t *mp_ping;
- ip4_address_t user_addr;
- int ret;
-
- if (vam->json_output)
- {
- clib_warning ("JSON output not supported for snat_det_session_dump");
- return -99;
- }
-
- if (unformat (i, "user_addr %U", unformat_ip4_address, &user_addr))
- ;
- else
- {
- clib_warning ("unknown input '%U'", format_unformat_error, i);
- return -99;
- }
-
- M(SNAT_DET_SESSION_DUMP, mp);
- clib_memcpy (&mp->user_addr, &user_addr, 4);
- S(mp);
-
- /* Use a control ping for synchronization */
- M(SNAT_CONTROL_PING, mp_ping);
- S(mp_ping);
-
- W (ret);
- return ret;
-}
-
-/*
- * List of messages that the api test plugin sends,
- * and that the data plane plugin processes
- */
-#define foreach_vpe_api_msg \
-_(snat_add_address_range, "<start-addr> [- <end-addr] [del]") \
-_(snat_interface_add_del_feature, \
- "<intfc> | sw_if_index <id> [in] [out] [del]") \
-_(snat_add_static_mapping, "local_addr <ip> (external_addr <ip>" \
- " | external_if <intfc> | external_sw_if_ndex <id>) " \
- "[local_port <n>] [external_port <n>] [vrf <table-id>] [del] " \
- "protocol <n>") \
-_(snat_set_workers, "<wokrers_bitmap>") \
-_(snat_static_mapping_dump, "") \
-_(snat_show_config, "") \
-_(snat_address_dump, "") \
-_(snat_interface_dump, "") \
-_(snat_worker_dump, "") \
-_(snat_add_del_interface_addr, \
- "<intfc> | sw_if_index <id> [del]") \
-_(snat_interface_addr_dump, "") \
-_(snat_ipfix_enable_disable, "[domain <id>] [src_port <n>] " \
- "[disable]") \
-_(snat_user_dump, "") \
-_(snat_user_session_dump, "ip_address <ip> vrf_id <table-id>") \
-_(snat_add_det_map, "in <in_addr>/<in_plen> out " \
- "<out_addr>/<out_plen> [del]") \
-_(snat_det_forward, "<in_addr>") \
-_(snat_det_reverse, "<out_addr> <out_port>") \
-_(snat_det_map_dump, "") \
-_(snat_det_set_timeouts, "[udp <sec> | tcp_established <sec> | " \
- "tcp_transitory <sec> | icmp <sec>]") \
-_(snat_det_get_timeouts, "") \
-_(snat_det_close_session_out, "<out_addr>:<out_port> " \
- "<ext_addr>:<ext_port>") \
-_(snat_det_close_session_in, "<in_addr>:<in_port> " \
- "<out_addr>:<out_port>") \
-_(snat_det_session_dump, "ip_address <user_addr>")
-
-static void
-snat_vat_api_hookup (vat_main_t *vam)
-{
- snat_test_main_t * sm __attribute__((unused)) = &snat_test_main;
- /* Hook up handlers for replies from the data plane plug-in */
-#define _(N,n) \
- vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \
- #n, \
- vl_api_##n##_t_handler, \
- vl_noop_handler, \
- vl_api_##n##_t_endian, \
- vl_api_##n##_t_print, \
- sizeof(vl_api_##n##_t), 1);
- foreach_vpe_api_reply_msg;
-#undef _
-
- /* API messages we can send */
-#define _(n,h) \
- hash_set_mem (vam->function_by_name, #n, api_##n);
- foreach_vpe_api_msg;
-#undef _
-
- /* Help strings */
-#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
- foreach_vpe_api_msg;
-#undef _
-}
-
-clib_error_t * vat_plugin_register (vat_main_t *vam)
-{
- snat_test_main_t * sm = &snat_test_main;
- u8 * name;
-
- sm->vat_main = vam;
-
- /* Ask the vpp engine for the first assigned message-id */
- name = format (0, "snat_%08x%c", api_version, 0);
- sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name);
-
- if (sm->msg_id_base != (u16) ~0)
- snat_vat_api_hookup (vam);
-
- vec_free(name);
-
- return 0;
-}