nat: move deterministic nat to det44 sub feature
Type: refactor Change-Id: I0bb203102a0e13dd7448e2125925ab356bbd7937 Signed-off-by: Filip Varga <fivarga@cisco.com>
This commit is contained in:
@@ -30,9 +30,6 @@ add_vpp_plugin(nat
|
||||
out2in.c
|
||||
out2in_ed.c
|
||||
nat_ipfix_logging.c
|
||||
nat_det.c
|
||||
nat_det_in2out.c
|
||||
nat_det_out2in.c
|
||||
nat_dpo.c
|
||||
nat44_cli.c
|
||||
nat44_handoff.c
|
||||
@@ -56,8 +53,6 @@ add_vpp_plugin(nat
|
||||
nat44_handoff.c
|
||||
nat64_in2out.c
|
||||
nat64_out2in.c
|
||||
nat_det_in2out.c
|
||||
nat_det_out2in.c
|
||||
out2in.c
|
||||
out2in_ed.c
|
||||
|
||||
@@ -116,3 +111,22 @@ add_vpp_plugin(nat66
|
||||
|
||||
LINK_LIBRARIES nat
|
||||
)
|
||||
|
||||
add_vpp_plugin(det44
|
||||
SOURCES
|
||||
det44/det44.c
|
||||
det44/det44_cli.c
|
||||
det44/det44_api.c
|
||||
det44/det44_in2out.c
|
||||
det44/det44_out2in.c
|
||||
|
||||
MULTIARCH_SOURCES
|
||||
det44/det44_in2out.c
|
||||
det44/det44_out2in.c
|
||||
|
||||
API_FILES
|
||||
det44/det44.api
|
||||
nat_types.api
|
||||
|
||||
LINK_LIBRARIES nat
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ features:
|
||||
- Endpoint dependent NAT
|
||||
- TCP MSS clamping
|
||||
- Local bypass (DHCP)
|
||||
- CGN - deterministic NAT
|
||||
- DET44 - deterministic NAT (CGN)
|
||||
- NAT64
|
||||
- NAT66
|
||||
- DS-lite
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* det44.h - deterministic NAT definitions
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Deterministic NAT (CGN) inlines
|
||||
*/
|
||||
|
||||
#ifndef __included_det44_inlines_h__
|
||||
#define __included_det44_inlines_h__
|
||||
|
||||
static_always_inline int
|
||||
det44_is_interface_addr (vlib_node_runtime_t * node,
|
||||
u32 sw_if_index0, u32 ip4_addr)
|
||||
{
|
||||
det44_runtime_t *rt = (det44_runtime_t *) node->runtime_data;
|
||||
det44_main_t *dm = &det44_main;
|
||||
ip4_address_t *first_int_addr;
|
||||
|
||||
if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index0))
|
||||
{
|
||||
first_int_addr = ip4_interface_first_address (dm->ip4_main,
|
||||
sw_if_index0, 0);
|
||||
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 (rt->cached_ip4_address == ip4_addr))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if packet should be translated
|
||||
*
|
||||
* Packets aimed at outside interface and external address with active session
|
||||
* should be translated.
|
||||
*
|
||||
* @param node NAT runtime data
|
||||
* @param sw_if_index0 index of the inside interface
|
||||
* @param ip0 IPv4 header
|
||||
* @param proto0 NAT protocol
|
||||
* @param rx_fib_index0 RX FIB index
|
||||
*
|
||||
* @returns 0 if packet should be translated otherwise 1
|
||||
*/
|
||||
static_always_inline int
|
||||
det44_translate (vlib_node_runtime_t * node, u32 sw_if_index0,
|
||||
ip4_header_t * ip0, u32 proto0, u32 rx_fib_index0)
|
||||
{
|
||||
det44_main_t *dm = &det44_main;
|
||||
fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
|
||||
det44_fib_t *outside_fib;
|
||||
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 interface address */
|
||||
if (PREDICT_FALSE (!det44_is_interface_addr (node, sw_if_index0,
|
||||
ip0->dst_address.as_u32)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* find out if there is outside feature enabled for this destination */
|
||||
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)
|
||||
{
|
||||
// TODO: go over use cases
|
||||
/* *INDENT-OFF* */
|
||||
vec_foreach (outside_fib, dm->outside_fibs)
|
||||
{
|
||||
fei = fib_table_lookup (outside_fib->fib_index, &pfx);
|
||||
if (FIB_NODE_INDEX_INVALID != fei)
|
||||
{
|
||||
sw_if_index = fib_entry_get_resolving_interface (fei);
|
||||
if (sw_if_index != ~0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
if (sw_if_index != ~0)
|
||||
{
|
||||
det44_interface_t *i;
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach (i, dm->interfaces, ({
|
||||
/* NAT packet aimed at outside interface */
|
||||
if ((det44_interface_is_outside (i)) && (sw_if_index == i->sw_if_index))
|
||||
return 0;
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* __included_det44_inlines_h__ */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ import "vnet/ip/ip_types.api";
|
||||
import "vnet/interface_types.api";
|
||||
|
||||
/**
|
||||
* @file nat.api
|
||||
* @file dslite.api
|
||||
* @brief VPP control-plane API messages.
|
||||
*
|
||||
* This file defines VPP control-plane API messages which are generally
|
||||
|
||||
@@ -267,9 +267,13 @@ format_dslite_ce_trace (u8 * s, va_list * args)
|
||||
|
||||
VLIB_INIT_FUNCTION (dslite_init);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_PLUGIN_REGISTER () =
|
||||
{
|
||||
.version = VPP_BUILD_VER,.description = "Dual-Stack Lite",};
|
||||
.version = VPP_BUILD_VER,
|
||||
.description = "Dual-Stack Lite",
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
|
||||
@@ -789,8 +789,7 @@ icmp_in2out (snat_main_t * sm,
|
||||
|
||||
if (vnet_buffer (b0)->sw_if_index[VLIB_TX] == ~0)
|
||||
{
|
||||
if (sm->deterministic ||
|
||||
0 != snat_icmp_hairpinning (sm, b0, ip0, icmp0,
|
||||
if (0 != snat_icmp_hairpinning (sm, b0, ip0, icmp0,
|
||||
sm->endpoint_dependent))
|
||||
vnet_buffer (b0)->sw_if_index[VLIB_TX] = fib_index;
|
||||
}
|
||||
|
||||
@@ -989,174 +989,6 @@ define nat44_forwarding_is_enabled_reply {
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Deterministic NAT (CGN) APIs
|
||||
*/
|
||||
|
||||
/** \brief Add/delete NAT deterministic mapping
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_add - true if add, false if delete
|
||||
@param in_addr - inside IPv4 address
|
||||
@param in_plen - inside IPv4 address prefix length
|
||||
@param out_addr - outside IPv4 address
|
||||
@param out_plen - outside IPv4 address prefix length
|
||||
*/
|
||||
autoreply define nat_det_add_del_map {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
bool is_add;
|
||||
vl_api_ip4_address_t in_addr;
|
||||
u8 in_plen;
|
||||
vl_api_ip4_address_t out_addr;
|
||||
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 in_addr - inside IP address
|
||||
*/
|
||||
define nat_det_forward {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_ip4_address_t in_addr;
|
||||
};
|
||||
|
||||
/** \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 out_addr - outside IPv4 address
|
||||
*/
|
||||
define nat_det_forward_reply {
|
||||
u32 context;
|
||||
i32 retval;
|
||||
u16 out_port_lo;
|
||||
u16 out_port_hi;
|
||||
vl_api_ip4_address_t out_addr;
|
||||
};
|
||||
|
||||
/** \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 out_addr - outside IPv4 address
|
||||
*/
|
||||
define nat_det_reverse {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u16 out_port;
|
||||
vl_api_ip4_address_t out_addr;
|
||||
};
|
||||
|
||||
/** \brief Get inside address from outside address and port reply
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param retval - return code
|
||||
@param in_addr - inside IP address
|
||||
*/
|
||||
define nat_det_reverse_reply {
|
||||
u32 context;
|
||||
i32 retval;
|
||||
vl_api_ip4_address_t in_addr;
|
||||
};
|
||||
|
||||
/** \brief Dump NAT deterministic mappings
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
*/
|
||||
define nat_det_map_dump {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
/** \brief NAT users response
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param in_addr - inside IPv4 address
|
||||
@param in_plen - inside IPv4 address prefix length
|
||||
@param out_addr - outside IPv4 address
|
||||
@param out_plen - outside IPv4 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 nat_det_map_details {
|
||||
u32 context;
|
||||
vl_api_ip4_address_t in_addr;
|
||||
u8 in_plen;
|
||||
vl_api_ip4_address_t out_addr;
|
||||
u8 out_plen;
|
||||
u32 sharing_ratio;
|
||||
u16 ports_per_host;
|
||||
u32 ses_num;
|
||||
};
|
||||
|
||||
/** \brief Close deterministic NAT 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 out_addr - outside IPv4 address
|
||||
@param out_port - outside port
|
||||
@param ext_addr - external host IPv4 address
|
||||
@param ext_port - external host port
|
||||
*/
|
||||
autoreply define nat_det_close_session_out {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_ip4_address_t out_addr;
|
||||
u16 out_port;
|
||||
vl_api_ip4_address_t ext_addr;
|
||||
u16 ext_port;
|
||||
};
|
||||
|
||||
/** \brief Close deterministic NAT 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 in_addr - inside IP address
|
||||
@param in_port - inside port
|
||||
@param ext_addr - external host IP address
|
||||
@param ext_port - external host port
|
||||
*/
|
||||
autoreply define nat_det_close_session_in {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_ip4_address_t in_addr;
|
||||
u16 in_port;
|
||||
vl_api_ip4_address_t ext_addr;
|
||||
u16 ext_port;
|
||||
};
|
||||
|
||||
/** \brief Dump determinstic NAT sessions
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param user_addr - address of an inside user whose sessions to dump
|
||||
*/
|
||||
define nat_det_session_dump {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_ip4_address_t user_addr;
|
||||
};
|
||||
|
||||
/** \brief Deterministic NAT sessions reply
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param in_port - inside port
|
||||
@param ext_addr - external host IPv4 address
|
||||
@param ext_port - external host port
|
||||
@param out_port - outside NAT port
|
||||
@param state - session state
|
||||
@param expire - session expiration timestamp
|
||||
*/
|
||||
define nat_det_session_details {
|
||||
u32 context;
|
||||
u16 in_port;
|
||||
vl_api_ip4_address_t ext_addr;
|
||||
u16 ext_port;
|
||||
u16 out_port;
|
||||
u8 state;
|
||||
u32 expire;
|
||||
};
|
||||
|
||||
/*
|
||||
* NAT64 APIs
|
||||
*/
|
||||
|
||||
+60
-122
File diff suppressed because it is too large
Load Diff
@@ -68,21 +68,6 @@ typedef struct
|
||||
u32 arc_next_index;
|
||||
} nat_pre_trace_t;
|
||||
|
||||
/* deterministic session outside key */
|
||||
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;
|
||||
|
||||
/* user (internal host) key */
|
||||
typedef struct
|
||||
{
|
||||
@@ -306,36 +291,6 @@ typedef struct
|
||||
u32 refcount;
|
||||
} nat_outside_fib_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Inside network port */
|
||||
u16 in_port;
|
||||
/* Outside network address and port */
|
||||
snat_det_out_key_t out;
|
||||
/* Session state */
|
||||
u8 state;
|
||||
/* Expire timeout */
|
||||
u32 expire;
|
||||
} snat_det_session_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* inside IP address range */
|
||||
ip4_address_t in_addr;
|
||||
u8 in_plen;
|
||||
/* outside IP address range */
|
||||
ip4_address_t out_addr;
|
||||
u8 out_plen;
|
||||
/* inside IP addresses / outside IP addresses */
|
||||
u32 sharing_ratio;
|
||||
/* number of ports available to internal host */
|
||||
u16 ports_per_host;
|
||||
/* session counter */
|
||||
u32 ses_num;
|
||||
/* vector of sessions */
|
||||
snat_det_session_t *sessions;
|
||||
} snat_det_map_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* backend IP address */
|
||||
@@ -590,8 +545,6 @@ typedef struct snat_main_s
|
||||
u32 out2in_fast_node_index;
|
||||
u32 ed_out2in_node_index;
|
||||
u32 ed_out2in_slowpath_node_index;
|
||||
u32 det_in2out_node_index;
|
||||
u32 det_out2in_node_index;
|
||||
|
||||
u32 hairpinning_node_index;
|
||||
u32 hairpin_dst_node_index;
|
||||
@@ -600,17 +553,12 @@ typedef struct snat_main_s
|
||||
u32 ed_hairpin_dst_node_index;
|
||||
u32 ed_hairpin_src_node_index;
|
||||
|
||||
|
||||
/* Deterministic NAT mappings */
|
||||
snat_det_map_t *det_maps;
|
||||
|
||||
/* If forwarding is enabled */
|
||||
u8 forwarding_enabled;
|
||||
|
||||
/* Config parameters */
|
||||
u8 static_mapping_only;
|
||||
u8 static_mapping_connection_tracking;
|
||||
u8 deterministic;
|
||||
u8 out2in_dpo;
|
||||
u8 endpoint_dependent;
|
||||
|
||||
@@ -736,8 +684,6 @@ extern vlib_node_registration_t snat_out2in_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 nat44_ed_in2out_node;
|
||||
extern vlib_node_registration_t nat44_ed_in2out_output_node;
|
||||
extern vlib_node_registration_t nat44_ed_out2in_node;
|
||||
@@ -750,7 +696,6 @@ format_function_t format_snat_user;
|
||||
format_function_t format_snat_static_mapping;
|
||||
format_function_t format_snat_static_map_to_resolve;
|
||||
format_function_t format_snat_session;
|
||||
format_function_t format_det_map_ses;
|
||||
format_function_t format_snat_key;
|
||||
format_function_t format_static_mapping_key;
|
||||
format_function_t format_nat_protocol;
|
||||
@@ -1068,20 +1013,6 @@ u32 icmp_match_out2in_slow (snat_main_t * sm, vlib_node_runtime_t * node,
|
||||
nat_protocol_t * proto, void *d, void *e,
|
||||
u8 * dont_translate);
|
||||
|
||||
/* ICMP deterministic NAT session match functions */
|
||||
u32 icmp_match_out2in_det (snat_main_t * sm, vlib_node_runtime_t * node,
|
||||
u32 thread_index, vlib_buffer_t * b0,
|
||||
ip4_header_t * ip0, ip4_address_t * addr,
|
||||
u16 * port, u32 * fib_index,
|
||||
nat_protocol_t * proto, void *d, void *e,
|
||||
u8 * dont_translate);
|
||||
u32 icmp_match_in2out_det (snat_main_t * sm, vlib_node_runtime_t * node,
|
||||
u32 thread_index, vlib_buffer_t * b0,
|
||||
ip4_header_t * ip0, ip4_address_t * addr,
|
||||
u16 * port, u32 * fib_index,
|
||||
nat_protocol_t * proto, void *d, void *e,
|
||||
u8 * dont_translate);
|
||||
|
||||
/* ICMP endpoint-dependent session match functions */
|
||||
u32 icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node,
|
||||
u32 thread_index, vlib_buffer_t * b0,
|
||||
|
||||
@@ -100,7 +100,7 @@ nat44_user_del (ip4_address_t * addr, u32 fib_index)
|
||||
snat_user_key_t user_key;
|
||||
clib_bihash_kv_8_8_t kv, value;
|
||||
|
||||
if (sm->deterministic || sm->endpoint_dependent)
|
||||
if (sm->endpoint_dependent)
|
||||
return rv;
|
||||
|
||||
user_key.addr.as_u32 = addr->as_u32;
|
||||
|
||||
@@ -458,28 +458,6 @@ VLIB_REGISTER_NODE (nat44_ed_classify_node) = {
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
VLIB_NODE_FN (nat44_det_classify_node) (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
return nat44_classify_node_fn_inline (vm, node, frame);
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_REGISTER_NODE (nat44_det_classify_node) = {
|
||||
.name = "nat44-det-classify",
|
||||
.vector_size = sizeof (u32),
|
||||
.format_trace = format_nat44_classify_trace,
|
||||
.type = VLIB_NODE_TYPE_INTERNAL,
|
||||
.n_next_nodes = NAT44_CLASSIFY_N_NEXT,
|
||||
.next_nodes = {
|
||||
[NAT44_CLASSIFY_NEXT_IN2OUT] = "nat44-det-in2out",
|
||||
[NAT44_CLASSIFY_NEXT_OUT2IN] = "nat44-det-out2in",
|
||||
[NAT44_CLASSIFY_NEXT_DROP] = "error-drop",
|
||||
},
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
VLIB_NODE_FN (nat44_handoff_classify_node) (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame)
|
||||
|
||||
+7
-522
File diff suppressed because it is too large
Load Diff
+2
-455
File diff suppressed because it is too large
Load Diff
@@ -1,175 +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 <nat/nat_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)
|
||||
{
|
||||
u32 num_sessions = (1 << (32 - in_plen));
|
||||
if (num_sessions > UINT32_MAX / 1000)
|
||||
{
|
||||
// don't let it overflow
|
||||
return VNET_API_ERROR_INVALID_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_sessions = num_sessions * 1000 - 1;
|
||||
}
|
||||
|
||||
u32 sharing_ratio = (1 << (32 - in_plen)) / (1 << (32 - out_plen));
|
||||
if (!sharing_ratio)
|
||||
{
|
||||
// avoid division by zero
|
||||
return VNET_API_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
pool_get (sm->det_maps, det_map);
|
||||
clib_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 = sharing_ratio;
|
||||
det_map->ports_per_host = (65535 - 1023) / det_map->sharing_ratio;
|
||||
|
||||
vec_validate_init_empty (det_map->sessions, num_sessions,
|
||||
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 (nat_interface_is_inside(i))
|
||||
continue;
|
||||
|
||||
snat_add_del_addr_to_fib(out_addr, out_plen, i->sw_if_index, is_add);
|
||||
break;
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The 'nat-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 =
|
||||
"nat-det-expire-walk",
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
@@ -1,199 +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_nat_det_h__
|
||||
#define __included_nat_det_h__
|
||||
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <nat/nat.h>
|
||||
#include <nat/nat_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 (u32 thread_index, 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 (clib_atomic_bool_cmp_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;
|
||||
clib_atomic_add_fetch (&dm->ses_num, 1);
|
||||
return &dm->sessions[i + user_offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snat_ipfix_logging_max_entries_per_user (thread_index,
|
||||
SNAT_DET_SES_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 (clib_atomic_bool_cmp_and_swap (&ses->in_port, ses->in_port, 0))
|
||||
{
|
||||
ses->out.as_u64 = 0;
|
||||
clib_atomic_add_fetch (&dm->ses_num, -1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __included_nat_det_h__ */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <nat/nat.h>
|
||||
#include <nat/nat_inlines.h>
|
||||
#include <nat/nat_det.h>
|
||||
|
||||
uword
|
||||
unformat_nat_protocol (unformat_input_t * input, va_list * args)
|
||||
@@ -297,39 +296,6 @@ format_snat_static_map_to_resolve (u8 * s, va_list * args)
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
|
||||
@@ -1528,83 +1528,78 @@ snat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port)
|
||||
a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
|
||||
a.flow_data_callback = data_callback;
|
||||
|
||||
if (sm->deterministic)
|
||||
/* TODO: ipfix needs to be separated from NAT base plugin
|
||||
a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
a.rewrite_callback = snat_template_rewrite_nat44_session;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.rewrite_callback = snat_template_rewrite_addr_exhausted;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.rewrite_callback = nat_template_rewrite_max_sessions;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.rewrite_callback = nat_template_rewrite_max_bibs;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.rewrite_callback = nat_template_rewrite_nat64_bib;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.rewrite_callback = nat_template_rewrite_nat64_session;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm->endpoint_dependent)
|
||||
{
|
||||
a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a.rewrite_callback = snat_template_rewrite_nat44_session;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.rewrite_callback = snat_template_rewrite_addr_exhausted;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.rewrite_callback = nat_template_rewrite_max_sessions;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.rewrite_callback = nat_template_rewrite_max_bibs;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.rewrite_callback = nat_template_rewrite_nat64_bib;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
a.rewrite_callback = nat_template_rewrite_nat64_session;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm->endpoint_dependent)
|
||||
{
|
||||
a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
|
||||
|
||||
rv = vnet_flow_report_add_del (frm, &a, NULL);
|
||||
if (rv)
|
||||
{
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-284
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user