cnat: Prepare extended snat policies
Type: refactor Change-Id: I9ca3333274d6f32b6aff57f0fb3d2049c066337a Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
This commit is contained in:
Nathan Skrzypczak
committed by
Dave Barach
parent
8786a4cd4a
commit
3fd77f7dea
@ -22,7 +22,7 @@ add_vpp_plugin(cnat
|
||||
cnat_session.c
|
||||
cnat_translation.c
|
||||
cnat_types.c
|
||||
cnat_snat.c
|
||||
cnat_snat_policy.c
|
||||
cnat_src_policy.c
|
||||
|
||||
API_FILES
|
||||
|
@ -159,7 +159,7 @@ define cnat_get_snat_addresses_reply
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
|
||||
autoreply define cnat_add_del_snat_prefix
|
||||
autoreply define cnat_snat_policy_add_del_exclude_pfx
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
@ -167,9 +167,29 @@ autoreply define cnat_add_del_snat_prefix
|
||||
vl_api_prefix_t prefix;
|
||||
};
|
||||
|
||||
enum cnat_snat_policies:u32
|
||||
enum cnat_snat_policy_table:u8
|
||||
{
|
||||
CNAT_SNAT_POLICY_NONE = 1,
|
||||
CNAT_POLICY_INCLUDE_V4 = 0,
|
||||
CNAT_POLICY_INCLUDE_V6 = 1,
|
||||
};
|
||||
|
||||
autoreply define cnat_snat_policy_add_del_if
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
u8 is_add;
|
||||
vl_api_cnat_snat_policy_table_t table;
|
||||
};
|
||||
|
||||
/* A snat policy controls what traffic is srcNATed */
|
||||
enum cnat_snat_policies:u8
|
||||
{
|
||||
/* No filter applied, srcNAT everything */
|
||||
CNAT_POLICY_NONE = 0,
|
||||
/* Filter by interface list : snat_policy_add_del_if
|
||||
* and prefix list : snat_policy_add_del_if */
|
||||
CNAT_POLICY_IF_PFX = 1,
|
||||
};
|
||||
|
||||
autoreply define cnat_set_snat_policy
|
||||
@ -178,6 +198,7 @@ autoreply define cnat_set_snat_policy
|
||||
u32 context;
|
||||
vl_api_cnat_snat_policies_t policy;
|
||||
};
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <cnat/cnat_translation.h>
|
||||
#include <cnat/cnat_session.h>
|
||||
#include <cnat/cnat_client.h>
|
||||
#include <cnat/cnat_snat.h>
|
||||
#include <cnat/cnat_snat_policy.h>
|
||||
|
||||
#include <vnet/ip/ip_types_api.h>
|
||||
|
||||
@ -292,14 +292,15 @@ vl_api_cnat_get_snat_addresses_t_handler (vl_api_cnat_get_snat_addresses_t
|
||||
* mp)
|
||||
{
|
||||
vl_api_cnat_get_snat_addresses_reply_t *rmp;
|
||||
cnat_snat_policy_main_t *cpm = &cnat_snat_policy_main;
|
||||
int rv = 0;
|
||||
|
||||
REPLY_MACRO2 (VL_API_CNAT_GET_SNAT_ADDRESSES_REPLY,
|
||||
({
|
||||
ip6_address_encode (&ip_addr_v6(&cnat_main.snat_ip6.ce_ip), rmp->snat_ip6);
|
||||
ip4_address_encode (&ip_addr_v4(&cnat_main.snat_ip4.ce_ip), rmp->snat_ip4);
|
||||
rmp->sw_if_index = clib_host_to_net_u32 (cnat_main.snat_ip6.ce_sw_if_index);
|
||||
}));
|
||||
REPLY_MACRO2 (
|
||||
VL_API_CNAT_GET_SNAT_ADDRESSES_REPLY, ({
|
||||
ip6_address_encode (&ip_addr_v6 (&cpm->snat_ip6.ce_ip), rmp->snat_ip6);
|
||||
ip4_address_encode (&ip_addr_v4 (&cpm->snat_ip4.ce_ip), rmp->snat_ip4);
|
||||
rmp->sw_if_index = clib_host_to_net_u32 (cpm->snat_ip6.ce_sw_if_index);
|
||||
}));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -321,39 +322,54 @@ vl_api_cnat_set_snat_addresses_t_handler (vl_api_cnat_set_snat_addresses_t
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_cnat_add_del_snat_prefix_t_handler
|
||||
(vl_api_cnat_add_del_snat_prefix_t * mp)
|
||||
vl_api_cnat_set_snat_policy_t_handler (vl_api_cnat_set_snat_policy_t *mp)
|
||||
{
|
||||
vl_api_cnat_add_del_snat_prefix_reply_t *rmp;
|
||||
vl_api_cnat_set_snat_policy_reply_t *rmp;
|
||||
int rv = 0;
|
||||
cnat_snat_policy_type_t policy = (cnat_snat_policy_type_t) mp->policy;
|
||||
|
||||
rv = cnat_set_snat_policy (policy);
|
||||
|
||||
REPLY_MACRO (VL_API_CNAT_SET_SNAT_POLICY_REPLY);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_cnat_snat_policy_add_del_exclude_pfx_t_handler (
|
||||
vl_api_cnat_snat_policy_add_del_exclude_pfx_t *mp)
|
||||
{
|
||||
vl_api_cnat_snat_policy_add_del_exclude_pfx_reply_t *rmp;
|
||||
ip_prefix_t pfx;
|
||||
int rv;
|
||||
|
||||
ip_prefix_decode2 (&mp->prefix, &pfx);
|
||||
if (mp->is_add)
|
||||
rv = cnat_add_snat_prefix (&pfx);
|
||||
rv = cnat_snat_policy_add_pfx (&pfx);
|
||||
else
|
||||
rv = cnat_del_snat_prefix (&pfx);
|
||||
rv = cnat_snat_policy_del_pfx (&pfx);
|
||||
|
||||
REPLY_MACRO (VL_API_CNAT_ADD_DEL_SNAT_PREFIX_REPLY);
|
||||
REPLY_MACRO (VL_API_CNAT_SNAT_POLICY_ADD_DEL_EXCLUDE_PFX_REPLY);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_cnat_set_snat_policy_t_handler (vl_api_cnat_set_snat_policy_t *mp)
|
||||
vl_api_cnat_snat_policy_add_del_if_t_handler (
|
||||
vl_api_cnat_snat_policy_add_del_if_t *mp)
|
||||
{
|
||||
vl_api_cnat_set_snat_policy_reply_t *rmp;
|
||||
vl_api_cnat_snat_policy_add_del_if_reply_t *rmp;
|
||||
u32 sw_if_index = ntohl (mp->sw_if_index);
|
||||
int rv = 0;
|
||||
vl_api_cnat_snat_policies_t policy = clib_net_to_host_u32 (mp->policy);
|
||||
switch (policy)
|
||||
{
|
||||
case CNAT_SNAT_POLICY_NONE:
|
||||
cnat_set_snat_policy (NULL);
|
||||
break;
|
||||
default:
|
||||
rv = 1;
|
||||
}
|
||||
|
||||
REPLY_MACRO (VL_API_CNAT_SET_SNAT_POLICY_REPLY);
|
||||
VALIDATE_SW_IF_INDEX (mp);
|
||||
|
||||
cnat_snat_interface_map_type_t table =
|
||||
(cnat_snat_interface_map_type_t) mp->table;
|
||||
|
||||
rv = cnat_snat_policy_add_del_if (sw_if_index, mp->is_add, table);
|
||||
|
||||
BAD_SW_IF_INDEX_LABEL;
|
||||
|
||||
REPLY_MACRO (VL_API_CNAT_SNAT_POLICY_ADD_DEL_IF_REPLY);
|
||||
}
|
||||
|
||||
#include <cnat/cnat.api.c>
|
||||
|
||||
static clib_error_t *
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <cnat/cnat_translation.h>
|
||||
#include <cnat/cnat_inline.h>
|
||||
#include <cnat/cnat_src_policy.h>
|
||||
#include <cnat/cnat_snat.h>
|
||||
#include <cnat/cnat_snat_policy.h>
|
||||
|
||||
#include <vnet/dpo/load_balance.h>
|
||||
#include <vnet/dpo/load_balance_map.h>
|
||||
@ -217,10 +217,8 @@ VLIB_REGISTER_NODE (cnat_input_feature_ip6_node) = {
|
||||
.type = VLIB_NODE_TYPE_INTERNAL,
|
||||
.n_errors = CNAT_N_ERROR,
|
||||
.error_strings = cnat_error_strings,
|
||||
.n_next_nodes = CNAT_FEATURE_N_NEXT,
|
||||
.next_nodes = {
|
||||
[CNAT_FEATURE_NEXT_DROP] = "error-drop",
|
||||
},
|
||||
.n_next_nodes = IP6_LOOKUP_N_NEXT,
|
||||
.next_nodes = IP6_LOOKUP_NEXT_NODES,
|
||||
};
|
||||
|
||||
VNET_FEATURE_INIT (cnat_in_ip6_feature, static) = {
|
||||
@ -236,8 +234,7 @@ cnat_output_feature_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
|
||||
vlib_buffer_t *b, cnat_node_ctx_t *ctx,
|
||||
int session_not_found, cnat_session_t *session)
|
||||
{
|
||||
cnat_main_t *cm = &cnat_main;
|
||||
cnat_snat_policy_main_t *cms = &cnat_snat_policy_main;
|
||||
cnat_snat_policy_main_t *cpm = &cnat_snat_policy_main;
|
||||
ip4_header_t *ip4 = NULL;
|
||||
ip_protocol_t iproto;
|
||||
ip6_header_t *ip6 = NULL;
|
||||
@ -275,32 +272,31 @@ cnat_output_feature_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
|
||||
/* session table hit */
|
||||
cnat_timestamp_update (session->value.cs_ts_index, ctx->now);
|
||||
}
|
||||
else if (!cms->snat_policy)
|
||||
else if (!cpm->snat_policy)
|
||||
goto trace;
|
||||
else
|
||||
{
|
||||
/* TODO: handle errors? */
|
||||
cms->snat_policy (vm, b, session, ctx, &do_snat);
|
||||
do_snat = cpm->snat_policy (b, session);
|
||||
if (do_snat != 1)
|
||||
goto trace;
|
||||
|
||||
if (AF_IP4 == ctx->af)
|
||||
{
|
||||
if (ip_address_is_zero (&cm->snat_ip4.ce_ip))
|
||||
if (ip_address_is_zero (&cpm->snat_ip4.ce_ip))
|
||||
goto trace;
|
||||
|
||||
ip46_address_set_ip4 (&session->value.cs_ip[VLIB_RX],
|
||||
&ip_addr_v4 (&cm->snat_ip4.ce_ip));
|
||||
&ip_addr_v4 (&cpm->snat_ip4.ce_ip));
|
||||
ip46_address_set_ip4 (&session->value.cs_ip[VLIB_TX],
|
||||
&ip4->dst_address);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ip_address_is_zero (&cm->snat_ip6.ce_ip))
|
||||
if (ip_address_is_zero (&cpm->snat_ip6.ce_ip))
|
||||
goto trace;
|
||||
|
||||
ip46_address_set_ip6 (&session->value.cs_ip[VLIB_RX],
|
||||
&ip_addr_v6 (&cm->snat_ip6.ce_ip));
|
||||
&ip_addr_v6 (&cpm->snat_ip6.ce_ip));
|
||||
ip46_address_set_ip6 (&session->value.cs_ip[VLIB_TX],
|
||||
&ip6->dst_address);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
#include <vlibmemory/api.h>
|
||||
#include <cnat/cnat_node.h>
|
||||
#include <cnat/cnat_snat.h>
|
||||
#include <cnat/cnat_snat_policy.h>
|
||||
#include <cnat/cnat_inline.h>
|
||||
#include <cnat/cnat_src_policy.h>
|
||||
|
||||
@ -36,7 +36,7 @@ cnat_snat_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
|
||||
vlib_buffer_t *b, cnat_node_ctx_t *ctx,
|
||||
int session_not_found, cnat_session_t *session)
|
||||
{
|
||||
cnat_main_t *cm = &cnat_main;
|
||||
cnat_snat_policy_main_t *cpm = &cnat_snat_policy_main;
|
||||
ip4_header_t *ip4 = NULL;
|
||||
ip_protocol_t iproto;
|
||||
ip6_header_t *ip6 = NULL;
|
||||
@ -45,7 +45,7 @@ cnat_snat_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
|
||||
u16 next0;
|
||||
u16 sport;
|
||||
u8 trace_flags = 0;
|
||||
int rv;
|
||||
int rv, do_snat;
|
||||
|
||||
if (AF_IP4 == ctx->af)
|
||||
{
|
||||
@ -80,12 +80,11 @@ cnat_snat_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
|
||||
ip46_address_set_ip4 (&ip46_dst_address, &ip4->dst_address);
|
||||
else
|
||||
ip46_address_set_ip6 (&ip46_dst_address, &ip6->dst_address);
|
||||
rv = cnat_search_snat_prefix (&ip46_dst_address, ctx->af);
|
||||
if (!rv)
|
||||
{
|
||||
/* Prefix table hit, we shouldn't source NAT */
|
||||
goto trace;
|
||||
}
|
||||
|
||||
do_snat = cpm->snat_policy (b, session);
|
||||
if (!do_snat)
|
||||
goto trace;
|
||||
|
||||
/* New flow, create the sessions if necessary. session will be a snat
|
||||
session, and rsession will be a dnat session
|
||||
Note: packet going through this path are going to the outside,
|
||||
@ -93,19 +92,19 @@ cnat_snat_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
|
||||
a VIP) */
|
||||
if (AF_IP4 == ctx->af)
|
||||
{
|
||||
if (!(cm->snat_ip4.ce_flags & CNAT_EP_FLAG_RESOLVED))
|
||||
if (!(cpm->snat_ip4.ce_flags & CNAT_EP_FLAG_RESOLVED))
|
||||
goto trace;
|
||||
ip46_address_set_ip4 (&session->value.cs_ip[VLIB_RX],
|
||||
&ip_addr_v4 (&cm->snat_ip4.ce_ip));
|
||||
&ip_addr_v4 (&cpm->snat_ip4.ce_ip));
|
||||
ip46_address_set_ip4 (&session->value.cs_ip[VLIB_TX],
|
||||
&ip4->dst_address);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(cm->snat_ip6.ce_flags & CNAT_EP_FLAG_RESOLVED))
|
||||
if (!(cpm->snat_ip6.ce_flags & CNAT_EP_FLAG_RESOLVED))
|
||||
goto trace;
|
||||
ip46_address_set_ip6 (&session->value.cs_ip[VLIB_RX],
|
||||
&ip_addr_v6 (&cm->snat_ip6.ce_ip));
|
||||
&ip_addr_v6 (&cpm->snat_ip6.ce_ip));
|
||||
ip46_address_set_ip6 (&session->value.cs_ip[VLIB_TX],
|
||||
&ip6->dst_address);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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 __CNAT_SNAT_H__
|
||||
#define __CNAT_SNAT_H__
|
||||
|
||||
#include <cnat/cnat_types.h>
|
||||
#include <cnat/cnat_session.h>
|
||||
|
||||
/* function to use to decide whether to snat connections in the output
|
||||
feature */
|
||||
typedef void (*cnat_snat_policy_t) (vlib_main_t *vm, vlib_buffer_t *b,
|
||||
cnat_session_t *session,
|
||||
cnat_node_ctx_t *ctx, u8 *do_snat);
|
||||
|
||||
typedef struct cnat_snat_policy_main_t_
|
||||
{
|
||||
/* SNAT policy for the output feature node */
|
||||
cnat_snat_policy_t snat_policy;
|
||||
|
||||
} cnat_snat_policy_main_t;
|
||||
|
||||
extern cnat_snat_policy_main_t cnat_snat_policy_main;
|
||||
|
||||
extern void cnat_set_snat (ip4_address_t * ip4, ip6_address_t * ip6,
|
||||
u32 sw_if_index);
|
||||
extern int cnat_add_snat_prefix (ip_prefix_t * pfx);
|
||||
extern int cnat_del_snat_prefix (ip_prefix_t * pfx);
|
||||
extern void cnat_set_snat_policy (cnat_snat_policy_t fp);
|
||||
|
||||
int cnat_search_snat_prefix (ip46_address_t * addr, ip_address_family_t af);
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
|
||||
#endif
|
542
src/plugins/cnat/cnat_snat_policy.c
Normal file
542
src/plugins/cnat/cnat_snat_policy.c
Normal file
File diff suppressed because it is too large
Load Diff
95
src/plugins/cnat/cnat_snat_policy.h
Normal file
95
src/plugins/cnat/cnat_snat_policy.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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 __CNAT_SNAT_H__
|
||||
#define __CNAT_SNAT_H__
|
||||
|
||||
#include <cnat/cnat_types.h>
|
||||
#include <cnat/cnat_session.h>
|
||||
|
||||
/* function to use to decide whether to snat connections in the output
|
||||
* feature. Returns 1 if we should source NAT */
|
||||
typedef int (*cnat_snat_policy_t) (vlib_buffer_t *b, cnat_session_t *session);
|
||||
|
||||
typedef struct cnat_snat_pfx_table_meta_t_
|
||||
{
|
||||
u32 dst_address_length_refcounts[129];
|
||||
u16 *prefix_lengths_in_search_order;
|
||||
uword *non_empty_dst_address_length_bitmap;
|
||||
} cnat_snat_pfx_table_meta_t;
|
||||
|
||||
typedef struct cnat_snat_exclude_pfx_table_t_
|
||||
{
|
||||
/* Stores (ip family, prefix & mask) */
|
||||
clib_bihash_24_8_t ip_hash;
|
||||
/* family dependant cache */
|
||||
cnat_snat_pfx_table_meta_t meta[2];
|
||||
/* Precomputed ip masks (ip4 & ip6) */
|
||||
ip6_address_t ip_masks[129];
|
||||
} cnat_snat_exclude_pfx_table_t;
|
||||
|
||||
typedef enum cnat_snat_interface_map_type_t_
|
||||
{
|
||||
CNAT_SNAT_IF_MAP_INCLUDE_V4 = AF_IP4,
|
||||
CNAT_SNAT_IF_MAP_INCLUDE_V6 = AF_IP6,
|
||||
CNAT_N_SNAT_IF_MAP,
|
||||
} cnat_snat_interface_map_type_t;
|
||||
|
||||
typedef enum cnat_snat_policy_type_t_
|
||||
{
|
||||
CNAT_SNAT_POLICY_NONE = 0,
|
||||
CNAT_SNAT_POLICY_IF_PFX = 1,
|
||||
} cnat_snat_policy_type_t;
|
||||
|
||||
typedef struct cnat_snat_policy_main_t_
|
||||
{
|
||||
/* Longest prefix Match table for source NATing */
|
||||
cnat_snat_exclude_pfx_table_t excluded_pfx;
|
||||
|
||||
/* interface maps including or excluding sw_if_indexes */
|
||||
clib_bitmap_t *interface_maps[CNAT_N_SNAT_IF_MAP];
|
||||
|
||||
/* SNAT policy for the output feature node */
|
||||
cnat_snat_policy_t snat_policy;
|
||||
|
||||
/* Ip4 Address to use for source NATing */
|
||||
cnat_endpoint_t snat_ip4;
|
||||
|
||||
/* Ip6 Address to use for source NATing */
|
||||
cnat_endpoint_t snat_ip6;
|
||||
|
||||
} cnat_snat_policy_main_t;
|
||||
|
||||
extern cnat_snat_policy_main_t cnat_snat_policy_main;
|
||||
|
||||
extern void cnat_set_snat (ip4_address_t *ip4, ip6_address_t *ip6,
|
||||
u32 sw_if_index);
|
||||
extern int cnat_snat_policy_add_pfx (ip_prefix_t *pfx);
|
||||
extern int cnat_snat_policy_del_pfx (ip_prefix_t *pfx);
|
||||
extern int cnat_set_snat_policy (cnat_snat_policy_type_t policy);
|
||||
extern int cnat_snat_policy_add_del_if (u32 sw_if_index, u8 is_add,
|
||||
cnat_snat_interface_map_type_t table);
|
||||
|
||||
int cnat_search_snat_prefix (ip46_address_t *addr, ip_address_family_t af);
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
|
||||
#endif
|
@ -26,9 +26,6 @@
|
||||
cnat_translation_t *cnat_translation_pool;
|
||||
clib_bihash_8_8_t cnat_translation_db;
|
||||
addr_resolution_t *tr_resolutions;
|
||||
|
||||
typedef void (*cnat_if_addr_add_cb_t) (addr_resolution_t * ar,
|
||||
ip_address_t * address, u8 is_del);
|
||||
cnat_if_addr_add_cb_t *cnat_if_addr_add_cbs;
|
||||
|
||||
static fib_node_type_t cnat_translation_fib_node_type;
|
||||
@ -774,32 +771,6 @@ cnat_if_addr_add_del_backend_cb (addr_resolution_t * ar,
|
||||
ct->flags |= CNAT_TRANSLATION_STACKED;
|
||||
}
|
||||
|
||||
static void
|
||||
cnat_if_addr_add_del_snat_cb (addr_resolution_t * ar, ip_address_t * address,
|
||||
u8 is_del)
|
||||
{
|
||||
cnat_endpoint_t *ep;
|
||||
ep = AF_IP4 == ar->af ? &cnat_main.snat_ip4 : &cnat_main.snat_ip6;
|
||||
|
||||
if (!is_del && ep->ce_flags & CNAT_EP_FLAG_RESOLVED)
|
||||
return;
|
||||
|
||||
if (is_del)
|
||||
{
|
||||
ep->ce_flags &= ~CNAT_EP_FLAG_RESOLVED;
|
||||
/* Are there remaining addresses ? */
|
||||
if (0 == cnat_resolve_addr (ar->sw_if_index, ar->af, address))
|
||||
is_del = 0;
|
||||
}
|
||||
|
||||
if (!is_del)
|
||||
{
|
||||
ip_address_copy (&ep->ce_ip, address);
|
||||
ep->ce_flags |= CNAT_EP_FLAG_RESOLVED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
cnat_if_addr_add_del_callback (u32 sw_if_index, ip_address_t * address,
|
||||
u8 is_del)
|
||||
@ -839,6 +810,14 @@ cnat_ip4_if_addr_add_del_callback (struct ip4_main_t *im,
|
||||
cnat_if_addr_add_del_callback (sw_if_index, &addr, is_del);
|
||||
}
|
||||
|
||||
void
|
||||
cnat_translation_register_addr_add_cb (cnat_addr_resol_type_t typ,
|
||||
cnat_if_addr_add_cb_t fn)
|
||||
{
|
||||
vec_validate (cnat_if_addr_add_cbs, CNAT_ADDR_N_RESOLUTIONS);
|
||||
cnat_if_addr_add_cbs[typ] = fn;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
cnat_translation_init (vlib_main_t * vm)
|
||||
{
|
||||
@ -860,12 +839,11 @@ cnat_translation_init (vlib_main_t * vm)
|
||||
cb6.function = cnat_ip6_if_addr_add_del_callback;
|
||||
vec_add1 (i6m->add_del_interface_address_callbacks, cb6);
|
||||
|
||||
vec_validate (cnat_if_addr_add_cbs, CNAT_ADDR_N_RESOLUTIONS);
|
||||
cnat_if_addr_add_cbs[CNAT_RESOLV_ADDR_BACKEND] =
|
||||
cnat_if_addr_add_del_backend_cb;
|
||||
cnat_if_addr_add_cbs[CNAT_RESOLV_ADDR_SNAT] = cnat_if_addr_add_del_snat_cb;
|
||||
cnat_if_addr_add_cbs[CNAT_RESOLV_ADDR_TRANSLATION] =
|
||||
cnat_if_addr_add_del_translation_cb;
|
||||
cnat_translation_register_addr_add_cb (CNAT_RESOLV_ADDR_BACKEND,
|
||||
cnat_if_addr_add_del_backend_cb);
|
||||
cnat_translation_register_addr_add_cb (CNAT_RESOLV_ADDR_TRANSLATION,
|
||||
cnat_if_addr_add_del_translation_cb);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
@ -231,6 +231,15 @@ extern void cnat_translation_watch_addr (index_t cti, u64 opaque,
|
||||
extern void cnat_translation_unwatch_addr (u32 cti,
|
||||
cnat_addr_resol_type_t type);
|
||||
|
||||
/**
|
||||
* Register a call back for endpoint->address resolution
|
||||
*/
|
||||
typedef void (*cnat_if_addr_add_cb_t) (addr_resolution_t *ar,
|
||||
ip_address_t *address, u8 is_del);
|
||||
|
||||
extern void cnat_translation_register_addr_add_cb (cnat_addr_resol_type_t typ,
|
||||
cnat_if_addr_add_cb_t fn);
|
||||
|
||||
/*
|
||||
* Data plane functions
|
||||
*/
|
||||
|
@ -181,6 +181,7 @@ cnat_config (vlib_main_t * vm, unformat_input_t * input)
|
||||
cm->translation_hash_buckets = CNAT_DEFAULT_TRANSLATION_BUCKETS;
|
||||
cm->snat_hash_memory = CNAT_DEFAULT_SNAT_MEMORY;
|
||||
cm->snat_hash_buckets = CNAT_DEFAULT_SNAT_BUCKETS;
|
||||
cm->snat_if_map_length = CNAT_DEFAULT_SNAT_IF_MAP_LEN;
|
||||
cm->scanner_timeout = CNAT_DEFAULT_SCANNER_TIMEOUT;
|
||||
cm->session_max_age = CNAT_DEFAULT_SESSION_MAX_AGE;
|
||||
cm->tcp_max_age = CNAT_DEFAULT_TCP_MAX_AGE;
|
||||
@ -204,6 +205,8 @@ cnat_config (vlib_main_t * vm, unformat_input_t * input)
|
||||
;
|
||||
else if (unformat (input, "snat-db-buckets %u", &cm->snat_hash_buckets))
|
||||
;
|
||||
else if (unformat (input, "snat-if-map-len %u", &cm->snat_if_map_length))
|
||||
;
|
||||
else if (unformat (input, "snat-db-memory %U",
|
||||
unformat_memory_size, &cm->snat_hash_memory))
|
||||
;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#define CNAT_DEFAULT_SESSION_BUCKETS 1024
|
||||
#define CNAT_DEFAULT_TRANSLATION_BUCKETS 1024
|
||||
#define CNAT_DEFAULT_SNAT_BUCKETS 1024
|
||||
#define CNAT_DEFAULT_SNAT_IF_MAP_LEN 4096
|
||||
|
||||
#define CNAT_DEFAULT_SESSION_MEMORY (1 << 20)
|
||||
#define CNAT_DEFAULT_TRANSLATION_MEMORY (256 << 10)
|
||||
@ -81,23 +82,6 @@ typedef struct
|
||||
u16 sequence;
|
||||
} cnat_echo_header_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 dst_address_length_refcounts[129];
|
||||
u16 *prefix_lengths_in_search_order;
|
||||
uword *non_empty_dst_address_length_bitmap;
|
||||
} cnat_snat_pfx_table_meta_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Stores (ip family, prefix & mask) */
|
||||
clib_bihash_24_8_t ip_hash;
|
||||
/* family dependant cache */
|
||||
cnat_snat_pfx_table_meta_t meta[2];
|
||||
/* Precomputed ip masks (ip4 & ip6) */
|
||||
ip6_address_t ip_masks[129];
|
||||
} cnat_snat_pfx_table_t;
|
||||
|
||||
typedef struct cnat_main_
|
||||
{
|
||||
/* Memory size of the session bihash */
|
||||
@ -118,6 +102,10 @@ typedef struct cnat_main_
|
||||
/* Number of buckets of the source NAT prefix bihash */
|
||||
u32 snat_hash_buckets;
|
||||
|
||||
/* Bit map for include / exclude sw_if_index
|
||||
* so max number of expected interfaces */
|
||||
u32 snat_if_map_length;
|
||||
|
||||
/* Timeout after which to clear sessions (in seconds) */
|
||||
u32 session_max_age;
|
||||
|
||||
@ -131,15 +119,6 @@ typedef struct cnat_main_
|
||||
/* Lock for the timestamp pool */
|
||||
clib_rwlock_t ts_lock;
|
||||
|
||||
/* Ip4 Address to use for source NATing */
|
||||
cnat_endpoint_t snat_ip4;
|
||||
|
||||
/* Ip6 Address to use for source NATing */
|
||||
cnat_endpoint_t snat_ip6;
|
||||
|
||||
/* Longest prefix Match table for source NATing */
|
||||
cnat_snat_pfx_table_t snat_pfx_table;
|
||||
|
||||
/* Index of the scanner process node */
|
||||
uword scanner_node_index;
|
||||
|
||||
|
@ -573,6 +573,17 @@ class TestCNatSourceNAT(VppTestCase):
|
||||
feature_name="cnat-snat-ip4",
|
||||
sw_if_index=self.pg0.sw_if_index)
|
||||
|
||||
policie_tbls = VppEnum.vl_api_cnat_snat_policy_table_t
|
||||
self.vapi.cnat_set_snat_policy(
|
||||
policy=VppEnum.vl_api_cnat_snat_policies_t.CNAT_POLICY_IF_PFX)
|
||||
for i in self.pg_interfaces:
|
||||
self.vapi.cnat_snat_policy_add_del_if(
|
||||
sw_if_index=i.sw_if_index, is_add=1,
|
||||
table=policie_tbls.CNAT_POLICY_INCLUDE_V6)
|
||||
self.vapi.cnat_snat_policy_add_del_if(
|
||||
sw_if_index=i.sw_if_index, is_add=1,
|
||||
table=policie_tbls.CNAT_POLICY_INCLUDE_V4)
|
||||
|
||||
def tearDown(self):
|
||||
self.vapi.cnat_session_purge()
|
||||
for i in self.pg_interfaces:
|
||||
@ -808,7 +819,8 @@ class TestCNatSourceNAT(VppTestCase):
|
||||
self.assertEqual(rx[IP46].src, remote_addr)
|
||||
|
||||
# add remote host to exclude list
|
||||
self.vapi.cnat_add_del_snat_prefix(prefix=exclude_prefix, is_add=1)
|
||||
self.vapi.cnat_snat_policy_add_del_exclude_pfx(
|
||||
prefix=exclude_prefix, is_add=1)
|
||||
self.vapi.cnat_session_purge()
|
||||
|
||||
rxs = self.send_and_expect(
|
||||
@ -822,7 +834,8 @@ class TestCNatSourceNAT(VppTestCase):
|
||||
self.assertEqual(rx[IP46].src, client_addr)
|
||||
|
||||
# remove remote host from exclude list
|
||||
self.vapi.cnat_add_del_snat_prefix(prefix=exclude_prefix, is_add=0)
|
||||
self.vapi.cnat_snat_policy_add_del_exclude_pfx(
|
||||
prefix=exclude_prefix, is_add=0)
|
||||
self.vapi.cnat_session_purge()
|
||||
|
||||
rxs = self.send_and_expect(
|
||||
|
Reference in New Issue
Block a user