nat: static mappings in flow hash

Put static mappings in flow hash, drop existing hash tables used for
static mappings. Drop refcount variables and use hash table as a single
point of truth. Allow creating a static mapping conflicting with dynamic
mapping, which will take precedence after dynamic mapping is freed, so
that the existing flow can finish transferring data.

Type: fix
Signed-off-by: Klement Sekera <ksekera@cisco.com>
Change-Id: Idfde8efabc09971be38921d4b0ca5ccf4e9fe412
This commit is contained in:
Klement Sekera
2021-05-26 13:02:35 +02:00
parent 4450b03ba2
commit ff334db797
31 changed files with 1341 additions and 1502 deletions
+1
View File
@@ -40,6 +40,7 @@
#include <nat/lib/lib.h>
#include <nat/lib/inlines.h>
#include <nat/lib/ipfix_logging.h>
#include <nat/lib/nat_proto.h>
/* Session state */
#define foreach_det44_session_state \
+1
View File
@@ -21,6 +21,7 @@
#define included_nat_lib_alloc_h__
#include <vnet/ip/ip.h>
#include <nat/lib/nat_proto.h>
typedef struct nat_ip4_pool_addr_s nat_ip4_pool_addr_t;
typedef struct nat_ip4_addr_port_s nat_ip4_addr_port_t;
-31
View File
@@ -20,37 +20,6 @@
#include <vnet/ip/icmp46_packet.h>
always_inline nat_protocol_t
ip_proto_to_nat_proto (u8 ip_proto)
{
static const nat_protocol_t lookup_table[256] = {
[IP_PROTOCOL_TCP] = NAT_PROTOCOL_TCP,
[IP_PROTOCOL_UDP] = NAT_PROTOCOL_UDP,
[IP_PROTOCOL_ICMP] = NAT_PROTOCOL_ICMP,
[IP_PROTOCOL_ICMP6] = NAT_PROTOCOL_ICMP,
};
return lookup_table[ip_proto];
}
static_always_inline u8
nat_proto_to_ip_proto (nat_protocol_t nat_proto)
{
ASSERT (nat_proto <= NAT_PROTOCOL_ICMP);
static const u8 lookup_table[256] = {
[NAT_PROTOCOL_OTHER] = ~0,
[NAT_PROTOCOL_TCP] = IP_PROTOCOL_TCP,
[NAT_PROTOCOL_UDP] = IP_PROTOCOL_UDP,
[NAT_PROTOCOL_ICMP] = IP_PROTOCOL_ICMP,
};
ASSERT (NAT_PROTOCOL_OTHER == nat_proto || NAT_PROTOCOL_TCP == nat_proto
|| NAT_PROTOCOL_UDP == nat_proto || NAT_PROTOCOL_ICMP == nat_proto);
return lookup_table[nat_proto];
}
static_always_inline u8
icmp_type_is_error_message (u8 icmp_type)
{
+15 -39
View File
@@ -51,7 +51,7 @@ typedef struct
u8 nat_event;
u32 src_ip;
u32 nat_src_ip;
nat_protocol_t nat_proto;
ip_protocol_t proto;
u16 src_port;
u16 nat_src_port;
u32 vrf_id;
@@ -577,9 +577,8 @@ nat_ipfix_send (flow_report_main_t *frm, vlib_frame_t *f, vlib_buffer_t *b0,
static void
nat_ipfix_logging_nat44_ses (u32 thread_index, u8 nat_event, u32 src_ip,
u32 nat_src_ip, nat_protocol_t nat_proto,
u16 src_port, u16 nat_src_port, u32 fib_index,
int do_flush)
u32 nat_src_ip, ip_protocol_t proto, u16 src_port,
u16 nat_src_port, u32 fib_index, int do_flush)
{
nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
@@ -590,12 +589,9 @@ nat_ipfix_logging_nat44_ses (u32 thread_index, u8 nat_event, u32 src_ip,
u32 offset;
vlib_main_t *vm = vlib_get_main ();
u64 now;
u8 proto;
u16 template_id;
u32 vrf_id;
proto = nat_proto_to_ip_proto (nat_proto);
now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
now += silm->milisecond_time_0;
@@ -1307,54 +1303,34 @@ nat_ipfix_flush_from_main (void)
/**
* @brief Generate NAT44 session create event
*
* @param thread_index thread index
* @param src_ip source IPv4 address
* @param nat_src_ip transaltes source IPv4 address
* @param nat_proto NAT transport protocol
* @param src_port source port
* @param nat_src_port translated source port
* @param vrf_id VRF ID
*/
void
nat_ipfix_logging_nat44_ses_create (u32 thread_index,
u32 src_ip,
u32 nat_src_ip,
nat_protocol_t nat_proto,
u16 src_port,
u16 nat_src_port, u32 fib_index)
nat_ipfix_logging_nat44_ses_create (u32 thread_index, u32 src_ip,
u32 nat_src_ip, ip_protocol_t proto,
u16 src_port, u16 nat_src_port,
u32 fib_index)
{
skip_if_disabled ();
nat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_CREATE, src_ip,
nat_src_ip, nat_proto, src_port, nat_src_port,
fib_index, 0);
nat_src_ip, proto, src_port, nat_src_port,
fib_index, 0);
}
/**
* @brief Generate NAT44 session delete event
*
* @param thread_index thread index
* @param src_ip source IPv4 address
* @param nat_src_ip transaltes source IPv4 address
* @param nat_proto NAT transport protocol
* @param src_port source port
* @param nat_src_port translated source port
* @param vrf_id VRF ID
*/
void
nat_ipfix_logging_nat44_ses_delete (u32 thread_index,
u32 src_ip,
u32 nat_src_ip,
nat_protocol_t nat_proto,
u16 src_port,
u16 nat_src_port, u32 fib_index)
nat_ipfix_logging_nat44_ses_delete (u32 thread_index, u32 src_ip,
u32 nat_src_ip, ip_protocol_t proto,
u16 src_port, u16 nat_src_port,
u32 fib_index)
{
skip_if_disabled ();
nat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_DELETE, src_ip,
nat_src_ip, nat_proto, src_port, nat_src_port,
fib_index, 0);
nat_src_ip, proto, src_port, nat_src_port,
fib_index, 0);
}
/**
+6 -8
View File
@@ -117,15 +117,13 @@ int nat_ipfix_logging_enabled ();
void nat_ipfix_logging_init (vlib_main_t * vm);
int nat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port);
void nat_ipfix_logging_nat44_ses_create (u32 thread_index, u32 src_ip,
u32 nat_src_ip,
nat_protocol_t nat_proto,
u16 src_port, u16 nat_src_port,
u32 fib_index);
u32 nat_src_ip, ip_protocol_t proto,
u16 src_port, u16 nat_src_port,
u32 fib_index);
void nat_ipfix_logging_nat44_ses_delete (u32 thread_index, u32 src_ip,
u32 nat_src_ip,
nat_protocol_t nat_proto,
u16 src_port, u16 nat_src_port,
u32 fib_index);
u32 nat_src_ip, ip_protocol_t proto,
u16 src_port, u16 nat_src_port,
u32 fib_index);
void nat_ipfix_logging_addresses_exhausted(u32 thread_index, u32 pool_id);
void nat_ipfix_logging_max_entries_per_user(u32 thread_index,
u32 limit, u32 src_ip);
+1
View File
@@ -14,6 +14,7 @@
*/
#include <nat/lib/lib.h>
#include <nat/lib/nat_proto.h>
uword
unformat_nat_protocol (unformat_input_t *input, va_list *args)
-40
View File
@@ -54,19 +54,6 @@ typedef enum
#undef _
} nat_error_t;
#define foreach_nat_protocol \
_ (OTHER, 0, other, "other") \
_ (UDP, 1, udp, "udp") \
_ (TCP, 2, tcp, "tcp") \
_ (ICMP, 3, icmp, "icmp")
typedef enum
{
#define _(N, i, n, s) NAT_PROTOCOL_##N = i,
foreach_nat_protocol
#undef _
} nat_protocol_t;
/* default protocol timeouts */
#define NAT_UDP_TIMEOUT 300
#define NAT_TCP_TRANSITORY_TIMEOUT 240
@@ -95,29 +82,6 @@ nat_reset_timeouts (nat_timeouts_t * timeouts)
timeouts->icmp = NAT_ICMP_TIMEOUT;
}
static_always_inline u32
nat_session_get_timeout (nat_timeouts_t *timeouts, nat_protocol_t proto,
u8 state)
{
switch (proto)
{
case NAT_PROTOCOL_ICMP:
return timeouts->icmp;
case NAT_PROTOCOL_UDP:
return timeouts->udp;
case NAT_PROTOCOL_TCP:
{
if (state)
return timeouts->tcp.transitory;
else
return timeouts->tcp.established;
}
default:
return timeouts->udp;
}
return 0;
}
static_always_inline u32
nat_calc_bihash_buckets (u32 n_elts)
{
@@ -138,10 +102,6 @@ nat_calc_bihash_buckets (u32 n_elts)
return lower_pow2;
}
u8 *format_nat_protocol (u8 *s, va_list *args);
uword unformat_nat_protocol (unformat_input_t *input, va_list *args);
#endif /* included_nat_lib_h__ */
/*
* fd.io coding-style-patch-verification: ON
+75
View File
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2021 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_nat_proto_h__
#define included_nat_proto_h__
#include <vnet/ip/ip.h>
#define foreach_nat_protocol \
_ (OTHER, 0, other, "other") \
_ (UDP, 1, udp, "udp") \
_ (TCP, 2, tcp, "tcp") \
_ (ICMP, 3, icmp, "icmp")
typedef enum
{
#define _(N, i, n, s) NAT_PROTOCOL_##N = i,
foreach_nat_protocol
#undef _
} nat_protocol_t;
always_inline nat_protocol_t
ip_proto_to_nat_proto (ip_protocol_t ip_proto)
{
static const nat_protocol_t lookup_table[256] = {
[IP_PROTOCOL_TCP] = NAT_PROTOCOL_TCP,
[IP_PROTOCOL_UDP] = NAT_PROTOCOL_UDP,
[IP_PROTOCOL_ICMP] = NAT_PROTOCOL_ICMP,
[IP_PROTOCOL_ICMP6] = NAT_PROTOCOL_ICMP,
};
return lookup_table[ip_proto];
}
static_always_inline ip_protocol_t
nat_proto_to_ip_proto (nat_protocol_t nat_proto)
{
ASSERT (nat_proto <= NAT_PROTOCOL_ICMP);
static const u8 lookup_table[256] = {
[NAT_PROTOCOL_OTHER] = ~0,
[NAT_PROTOCOL_TCP] = IP_PROTOCOL_TCP,
[NAT_PROTOCOL_UDP] = IP_PROTOCOL_UDP,
[NAT_PROTOCOL_ICMP] = IP_PROTOCOL_ICMP,
};
ASSERT (NAT_PROTOCOL_OTHER == nat_proto || NAT_PROTOCOL_TCP == nat_proto ||
NAT_PROTOCOL_UDP == nat_proto || NAT_PROTOCOL_ICMP == nat_proto);
return lookup_table[nat_proto];
}
u8 *format_nat_protocol (u8 *s, va_list *args);
uword unformat_nat_protocol (unformat_input_t *input, va_list *args);
#endif /* included_nat_proto_h__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
+1 -108
View File
@@ -23,38 +23,7 @@
#include <nat/lib/nat_syslog.h>
#include <nat/lib/inlines.h>
#define NAT_FACILITY SYSLOG_FACILITY_LOCAL0
#define NAT_APPNAME "NAT"
#define SADD_SDEL_SEVERITY SYSLOG_SEVERITY_INFORMATIONAL
#define APMADD_APMDEL_SEVERITY SYSLOG_SEVERITY_INFORMATIONAL
#define SADD_MSGID "SADD"
#define SDEL_MSGID "SDEL"
#define APMADD_MSGID "APMADD"
#define APMDEL_MSGID "APMDEL"
#define NSESS_SDID "nsess"
#define NAPMAP_SDID "napmap"
#define SSUBIX_SDPARAM_NAME "SSUBIX"
#define SVLAN_SDPARAM_NAME "SVLAN"
#define IATYP_SDPARAM_NAME "IATYP"
#define ISADDR_SDPARAM_NAME "ISADDR"
#define ISPORT_SDPARAM_NAME "ISPORT"
#define IDADDR_SDPARAM_NAME "IDADDR"
#define IDPORT_SDPARAM_NAME "IDPORT"
#define XATYP_SDPARAM_NAME "XATYP"
#define XSADDR_SDPARAM_NAME "XSADDR"
#define XSPORT_SDPARAM_NAME "XSPORT"
#define XDADDR_SDPARAM_NAME "XDADDR"
#define XDPORT_SDPARAM_NAME "XDPORT"
#define PROTO_SDPARAM_NAME "PROTO"
#define SV6ENC_SDPARAM_NAME "SV6ENC"
#define IATYP_IPV4 "IPv4"
#define IATYP_IPV6 "IPv6"
#include <nat/lib/nat_syslog_constants.h>
static inline void
nat_syslog_nat44_apmap (u32 ssubix, u32 sfibix, ip4_address_t * isaddr,
@@ -141,82 +110,6 @@ nat_syslog_dslite_apmdel (u32 ssubix, ip6_address_t * sv6enc,
proto, 0, sv6enc);
}
static inline void
nat_syslog_nat44_sess (u32 ssubix, u32 sfibix, ip4_address_t * isaddr,
u16 isport, ip4_address_t * xsaddr, u16 xsport,
ip4_address_t * idaddr, u16 idport,
ip4_address_t * xdaddr, u16 xdport,
nat_protocol_t proto, u8 is_add, u8 is_twicenat)
{
syslog_msg_t syslog_msg;
fib_table_t *fib;
if (!syslog_is_enabled ())
return;
if (syslog_severity_filter_block (SADD_SDEL_SEVERITY))
return;
fib = fib_table_get (sfibix, FIB_PROTOCOL_IP4);
syslog_msg_init (&syslog_msg, NAT_FACILITY, SADD_SDEL_SEVERITY, NAT_APPNAME,
is_add ? SADD_MSGID : SDEL_MSGID);
syslog_msg_sd_init (&syslog_msg, NSESS_SDID);
syslog_msg_add_sd_param (&syslog_msg, SSUBIX_SDPARAM_NAME, "%d", ssubix);
syslog_msg_add_sd_param (&syslog_msg, SVLAN_SDPARAM_NAME, "%d",
fib->ft_table_id);
syslog_msg_add_sd_param (&syslog_msg, IATYP_SDPARAM_NAME, IATYP_IPV4);
syslog_msg_add_sd_param (&syslog_msg, ISADDR_SDPARAM_NAME, "%U",
format_ip4_address, isaddr);
syslog_msg_add_sd_param (&syslog_msg, ISPORT_SDPARAM_NAME, "%d",
clib_net_to_host_u16 (isport));
syslog_msg_add_sd_param (&syslog_msg, XATYP_SDPARAM_NAME, IATYP_IPV4);
syslog_msg_add_sd_param (&syslog_msg, XSADDR_SDPARAM_NAME, "%U",
format_ip4_address, xsaddr);
syslog_msg_add_sd_param (&syslog_msg, XSPORT_SDPARAM_NAME, "%d",
clib_net_to_host_u16 (xsport));
syslog_msg_add_sd_param (&syslog_msg, PROTO_SDPARAM_NAME, "%d",
nat_proto_to_ip_proto (proto));
syslog_msg_add_sd_param (&syslog_msg, XDADDR_SDPARAM_NAME, "%U",
format_ip4_address, xdaddr);
syslog_msg_add_sd_param (&syslog_msg, XDPORT_SDPARAM_NAME, "%d",
clib_net_to_host_u16 (xdport));
if (is_twicenat)
{
syslog_msg_add_sd_param (&syslog_msg, IDADDR_SDPARAM_NAME, "%U",
format_ip4_address, idaddr);
syslog_msg_add_sd_param (&syslog_msg, IDPORT_SDPARAM_NAME, "%d",
clib_net_to_host_u16 (idport));
}
syslog_msg_send (&syslog_msg);
}
void
nat_syslog_nat44_sadd (u32 ssubix, u32 sfibix, ip4_address_t * isaddr,
u16 isport, ip4_address_t * idaddr, u16 idport,
ip4_address_t * xsaddr, u16 xsport,
ip4_address_t * xdaddr, u16 xdport,
nat_protocol_t proto, u8 is_twicenat)
{
nat_syslog_nat44_sess (ssubix, sfibix, isaddr, isport, xsaddr, xsport,
idaddr, idport, xdaddr, xdport, proto, 1,
is_twicenat);
}
void
nat_syslog_nat44_sdel (u32 ssubix, u32 sfibix, ip4_address_t * isaddr,
u16 isport, ip4_address_t * idaddr, u16 idport,
ip4_address_t * xsaddr, u16 xsport,
ip4_address_t * xdaddr, u16 xdport,
nat_protocol_t proto, u8 is_twicenat)
{
nat_syslog_nat44_sess (ssubix, sfibix, isaddr, isport, xsaddr, xsport,
idaddr, idport, xdaddr, xdport, proto, 0,
is_twicenat);
}
static inline void
nat_syslog_nat64_sess (u32 sfibix, ip6_address_t * isaddr, u16 isport,
ip4_address_t * xsaddr, u16 xsport,
+1 -12
View File
@@ -20,6 +20,7 @@
#define __included_nat_syslog_h__
#include <nat/lib/lib.h>
#include <nat/lib/nat_proto.h>
void nat_syslog_nat44_apmadd (u32 ssubix, u32 sfibix, ip4_address_t * isaddr,
u16 isport, ip4_address_t * xsaddr, u16 xsport,
@@ -41,18 +42,6 @@ nat_syslog_dslite_apmdel (u32 ssubix, ip6_address_t * sv6enc,
ip4_address_t * xsaddr, u16 xsport,
nat_protocol_t proto);
void nat_syslog_nat44_sadd (u32 ssubix, u32 sfibix, ip4_address_t * isaddr,
u16 isport, ip4_address_t * idaddr, u16 idport,
ip4_address_t * xsaddr, u16 xsport,
ip4_address_t * xdaddr, u16 xdport,
nat_protocol_t proto, u8 is_twicenat);
void nat_syslog_nat44_sdel (u32 ssubix, u32 sfibix, ip4_address_t * isaddr,
u16 isport, ip4_address_t * idaddr, u16 idport,
ip4_address_t * xsaddr, u16 xsport,
ip4_address_t * xdaddr, u16 xdport,
nat_protocol_t proto, u8 is_twicenat);
void nat_syslog_nat64_sadd (u32 sfibix, ip6_address_t * isaddr, u16 isport,
ip4_address_t * xsaddr, u16 xsport,
ip4_address_t * xdaddr, u16 xdport,
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2021 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 NAT syslog logging constants
*/
#ifndef __included_nat_syslog_constants_h__
#define __included_nat_syslog_constants_h__
#define NAT_FACILITY SYSLOG_FACILITY_LOCAL0
#define NAT_APPNAME "NAT"
#define SADD_SDEL_SEVERITY SYSLOG_SEVERITY_INFORMATIONAL
#define APMADD_APMDEL_SEVERITY SYSLOG_SEVERITY_INFORMATIONAL
#define SADD_MSGID "SADD"
#define SDEL_MSGID "SDEL"
#define APMADD_MSGID "APMADD"
#define APMDEL_MSGID "APMDEL"
#define NSESS_SDID "nsess"
#define NAPMAP_SDID "napmap"
#define SSUBIX_SDPARAM_NAME "SSUBIX"
#define SVLAN_SDPARAM_NAME "SVLAN"
#define IATYP_SDPARAM_NAME "IATYP"
#define ISADDR_SDPARAM_NAME "ISADDR"
#define ISPORT_SDPARAM_NAME "ISPORT"
#define IDADDR_SDPARAM_NAME "IDADDR"
#define IDPORT_SDPARAM_NAME "IDPORT"
#define XATYP_SDPARAM_NAME "XATYP"
#define XSADDR_SDPARAM_NAME "XSADDR"
#define XSPORT_SDPARAM_NAME "XSPORT"
#define XDADDR_SDPARAM_NAME "XDADDR"
#define XDPORT_SDPARAM_NAME "XDPORT"
#define PROTO_SDPARAM_NAME "PROTO"
#define SV6ENC_SDPARAM_NAME "SV6ENC"
#define IATYP_IPV4 "IPv4"
#define IATYP_IPV6 "IPv6"
#endif /* __included_nat_syslog_constants_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
+43 -71
View File
@@ -39,6 +39,11 @@
/* default number of worker handoff frame queue elements */
#define NAT_FQ_NELTS_DEFAULT 64
/* number of attempts to get a port for ED overloading algorithm, if rolling
* a dice this many times doesn't produce a free port, it's treated
* as if there were no free ports available to conserve resources */
#define ED_PORT_ALLOC_ATTEMPTS (10)
/* NAT buffer flags */
#define SNAT_FLAG_HAIRPINNING (1 << 0)
@@ -172,7 +177,6 @@ typedef enum
/* Session flags */
#define SNAT_SESSION_FLAG_STATIC_MAPPING (1 << 0)
#define SNAT_SESSION_FLAG_UNKNOWN_PROTO (1 << 1)
#define SNAT_SESSION_FLAG_LOAD_BALANCING (1 << 2)
#define SNAT_SESSION_FLAG_TWICE_NAT (1 << 3)
#define SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT (1 << 4)
@@ -308,7 +312,7 @@ typedef CLIB_PACKED(struct
u16 port;
} in2out;
nat_protocol_t nat_proto;
ip_protocol_t proto;
nat_6t_flow_t i2o;
nat_6t_flow_t o2i;
@@ -356,12 +360,6 @@ typedef struct
{
ip4_address_t addr;
u32 fib_index;
#define _(N, i, n, s) \
u32 busy_##n##_ports; \
u32 * busy_##n##_ports_per_thread; \
u32 busy_##n##_port_refcounts[65535];
foreach_nat_protocol
#undef _
} snat_address_t;
typedef struct
@@ -426,7 +424,7 @@ typedef struct
u32 vrf_id;
u32 fib_index;
/* protocol */
nat_protocol_t proto;
ip_protocol_t proto;
/* 0 = disabled, otherwise client IP affinity sticky time in seconds */
u32 affinity;
/* worker threads used by backends/local host */
@@ -455,7 +453,7 @@ typedef struct
u16 e_port;
u32 sw_if_index;
u32 vrf_id;
nat_protocol_t proto;
ip_protocol_t proto;
u32 flags;
int addr_only;
int twice_nat;
@@ -500,15 +498,10 @@ u32 nat44_ed_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip,
/* Return worker thread index for given packet */
/* NAT address and port allocation function */
typedef int (nat_alloc_out_addr_and_port_function_t) (snat_address_t *
addresses,
u32 fib_index,
u32 thread_index,
nat_protocol_t proto,
ip4_address_t * addr,
u16 * port,
u16 port_per_thread,
u32 snat_thread_index);
typedef int (nat_alloc_out_addr_and_port_function_t) (
snat_address_t *addresses, u32 fib_index, u32 thread_index,
ip_protocol_t proto, ip4_address_t *addr, u16 *port, u16 port_per_thread,
u32 snat_thread_index);
typedef struct snat_main_s
{
@@ -521,12 +514,6 @@ typedef struct snat_main_s
/* 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;
@@ -715,12 +702,8 @@ extern fib_source_t nat_fib_src_low;
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_snat_key;
format_function_t format_static_mapping_key;
format_function_t format_nat_protocol;
format_function_t format_nat_addr_and_port_alloc_alg;
/* unformat functions */
unformat_function_t unformat_nat_protocol;
/** \brief Check if SNAT session is created from static mapping.
@param s SNAT session
@@ -732,16 +715,6 @@ nat44_ed_is_session_static (snat_session_t *s)
return s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING;
}
/** \brief Check if SNAT session for unknown protocol.
@param s SNAT session
@return true if SNAT session for unknown protocol otherwise 0
*/
always_inline bool
snat_is_unk_proto_session (snat_session_t *s)
{
return s->flags & SNAT_SESSION_FLAG_UNKNOWN_PROTO;
}
/** \brief Check if NAT session is twice NAT.
@param s NAT session
@return true if NAT session is twice NAT
@@ -910,25 +883,25 @@ int nat44_ed_add_interface_address (u32 sw_if_index, u8 twice_nat);
int nat44_ed_del_interface_address (u32 sw_if_index, u8 twice_nat);
int nat44_ed_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
u16 l_port, u16 e_port, nat_protocol_t proto,
u16 l_port, u16 e_port, ip_protocol_t proto,
u32 vrf_id, u32 sw_if_index, u32 flags,
ip4_address_t pool_addr, u8 *tag);
int nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
u16 l_port, u16 e_port, nat_protocol_t proto,
u16 l_port, u16 e_port, ip_protocol_t proto,
u32 vrf_id, u32 sw_if_index, u32 flags);
int nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
nat_protocol_t proto,
ip_protocol_t proto,
nat44_lb_addr_port_t *locals, u32 flags,
u8 *tag, u32 affinity);
int nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
nat_protocol_t proto, u32 flags);
ip_protocol_t proto, u32 flags);
int nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port,
ip4_address_t l_addr, u16 l_port,
nat_protocol_t proto, u32 vrf_id,
ip_protocol_t proto, u32 vrf_id,
u8 probability, u8 is_add);
/**
@@ -947,16 +920,8 @@ int nat44_ed_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port,
ip4_address_t *eh_addr, u16 eh_port, u8 proto,
u32 vrf_id, int is_in);
/**
* @brief Free NAT44 session data (lookup keys, external address port)
*
* @param sm snat global configuration data
* @param s NAT session
* @param thread_index thread index
* @param is_ha is HA event
*/
void nat_free_session_data (snat_main_t * sm, snat_session_t * s,
u32 thread_index, u8 is_ha);
void nat44_ed_free_session_data (snat_main_t *sm, snat_session_t *s,
u32 thread_index, u8 is_ha);
/**
* @brief Set NAT44 session limit (session limit, vrf id)
@@ -976,19 +941,6 @@ int nat44_set_session_limit (u32 session_limit, u32 vrf_id);
*/
int nat44_update_session_limit (u32 session_limit, u32 vrf_id);
/**
* @brief Free outside address and port pair
*
* @param addresses vector of outside addresses
* @param thread_index thread index
* @param key address, port and protocol
*/
void
snat_free_outside_address_and_port (snat_address_t * addresses,
u32 thread_index,
ip4_address_t * addr,
u16 port, nat_protocol_t protocol);
void expire_per_vrf_sessions (u32 fib_index);
/**
@@ -1011,9 +963,9 @@ void expire_per_vrf_sessions (u32 fib_index);
*/
int snat_static_mapping_match (
vlib_main_t *vm, snat_main_t *sm, ip4_address_t match_addr, u16 match_port,
u32 match_fib_index, nat_protocol_t match_protocol,
u32 match_fib_index, ip_protocol_t match_protocol,
ip4_address_t *mapping_addr, u16 *mapping_port, u32 *mapping_fib_index,
u8 by_external, u8 *is_addr_only, twice_nat_type_t *twice_nat,
int by_external, u8 *is_addr_only, twice_nat_type_t *twice_nat,
lb_nat_type_t *lb, ip4_address_t *ext_host_addr, u8 *is_identity_nat,
snat_static_mapping_t **out);
@@ -1060,11 +1012,11 @@ typedef enum
nat_translation_error_e nat_6t_flow_buf_translate_i2o (
vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip,
nat_6t_flow_t *f, nat_protocol_t proto, int is_output_feature);
nat_6t_flow_t *f, ip_protocol_t proto, int is_output_feature);
nat_translation_error_e nat_6t_flow_buf_translate_o2i (
vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip,
nat_6t_flow_t *f, nat_protocol_t proto, int is_output_feature);
nat_6t_flow_t *f, ip_protocol_t proto, int is_output_feature);
void nat_6t_l3_l4_csum_calc (nat_6t_flow_t *f);
@@ -1072,6 +1024,26 @@ format_function_t format_nat_ed_translation_error;
format_function_t format_nat_6t_flow;
format_function_t format_ed_session_kvp;
snat_static_mapping_t *nat44_ed_sm_i2o_lookup (snat_main_t *sm,
ip4_address_t addr, u16 port,
u32 fib_index, u8 proto);
snat_static_mapping_t *nat44_ed_sm_o2i_lookup (snat_main_t *sm,
ip4_address_t addr, u16 port,
u32 fib_index, u8 proto);
void nat_syslog_nat44_sadd (u32 ssubix, u32 sfibix, ip4_address_t *isaddr,
u16 isport, ip4_address_t *idaddr, u16 idport,
ip4_address_t *xsaddr, u16 xsport,
ip4_address_t *xdaddr, u16 xdport, u8 proto,
u8 is_twicenat);
void nat_syslog_nat44_sdel (u32 ssubix, u32 sfibix, ip4_address_t *isaddr,
u16 isport, ip4_address_t *idaddr, u16 idport,
ip4_address_t *xsaddr, u16 xsport,
ip4_address_t *xdaddr, u16 xdport, u8 proto,
u8 is_twicenat);
#endif /* __included_nat44_ed_h__ */
/*
* fd.io coding-style-patch-verification: ON
+3 -4
View File
@@ -37,10 +37,9 @@ format_affinity_kvp (u8 * s, va_list * args)
k.as_u64[1] = v->key[1];
s = format (s, "client %U backend %U:%d proto %U index %llu",
format_ip4_address, &k.client_addr,
format_ip4_address, &k.service_addr,
clib_net_to_host_u16 (k.service_port),
format_nat_protocol, k.proto);
format_ip4_address, &k.client_addr, format_ip4_address,
&k.service_addr, clib_net_to_host_u16 (k.service_port),
format_ip_protocol, k.proto);
return s;
}
+47 -46
View File
@@ -628,7 +628,7 @@ static void
ip4_address_t l_addr, e_addr, pool_addr = { 0 };
u32 sw_if_index, flags = 0, vrf_id;
u16 l_port = 0, e_port = 0;
nat_protocol_t proto = 0;
ip_protocol_t proto = 0;
u8 *tag = 0;
memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
@@ -641,7 +641,7 @@ static void
{
l_port = mp->local_port;
e_port = mp->external_port;
proto = ip_proto_to_nat_proto (mp->protocol);
proto = mp->protocol;
}
if (mp->flags & NAT_API_IS_TWICE_NAT)
@@ -702,7 +702,7 @@ static void
ip4_address_t l_addr, e_addr, pool_addr;
u32 sw_if_index, flags = 0, vrf_id;
u16 l_port = 0, e_port = 0;
nat_protocol_t proto;
ip_protocol_t proto;
u8 *tag = 0;
memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
@@ -748,7 +748,7 @@ static void
memcpy (&e_addr.as_u8, mp->external_ip_address, 4);
}
proto = ip_proto_to_nat_proto (mp->protocol);
proto = mp->protocol;
vrf_id = clib_net_to_host_u32 (mp->vrf_id);
if (mp->is_add)
@@ -812,7 +812,7 @@ send_nat44_static_mapping_details (snat_static_mapping_t * m,
}
else
{
rmp->protocol = nat_proto_to_ip_proto (m->proto);
rmp->protocol = m->proto;
rmp->external_port = m->external_port;
rmp->local_port = m->local_port;
}
@@ -849,7 +849,7 @@ send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m,
}
else
{
rmp->protocol = nat_proto_to_ip_proto (m->proto);
rmp->protocol = m->proto;
rmp->external_port = m->e_port;
rmp->local_port = m->l_port;
}
@@ -898,7 +898,7 @@ static void
ip4_address_t addr, pool_addr = { 0 };
u32 sw_if_index, flags, vrf_id;
nat_protocol_t proto = 0;
ip_protocol_t proto = 0;
u16 port = 0;
u8 *tag = 0;
@@ -911,7 +911,7 @@ static void
else
{
port = mp->port;
proto = ip_proto_to_nat_proto (mp->protocol);
proto = mp->protocol;
}
sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
@@ -964,7 +964,7 @@ send_nat44_identity_mapping_details (snat_static_mapping_t * m, int index,
rmp->port = m->local_port;
rmp->sw_if_index = ~0;
rmp->vrf_id = htonl (local->vrf_id);
rmp->protocol = nat_proto_to_ip_proto (m->proto);
rmp->protocol = m->proto;
rmp->context = context;
if (m->tag)
strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
@@ -991,7 +991,7 @@ send_nat44_identity_map_resolve_details (snat_static_map_resolve_t * m,
rmp->port = m->l_port;
rmp->sw_if_index = htonl (m->sw_if_index);
rmp->vrf_id = htonl (m->vrf_id);
rmp->protocol = nat_proto_to_ip_proto (m->proto);
rmp->protocol = m->proto;
rmp->context = context;
if (m->tag)
strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
@@ -1140,7 +1140,7 @@ vl_api_nat44_add_del_lb_static_mapping_t_handler (
vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
nat44_lb_addr_port_t *locals = 0;
ip4_address_t e_addr;
nat_protocol_t proto;
ip_protocol_t proto;
u32 flags = 0;
u8 *tag = 0;
int rv = 0;
@@ -1148,7 +1148,7 @@ vl_api_nat44_add_del_lb_static_mapping_t_handler (
locals = unformat_nat44_lb_addr_port (mp->locals,
clib_net_to_host_u32 (mp->local_num));
clib_memcpy (&e_addr, mp->external_addr, 4);
proto = ip_proto_to_nat_proto (mp->protocol);
proto = mp->protocol;
if (mp->flags & NAT_API_IS_TWICE_NAT)
{
@@ -1193,11 +1193,11 @@ vl_api_nat44_lb_static_mapping_add_del_local_t_handler (
vl_api_nat44_lb_static_mapping_add_del_local_reply_t *rmp;
int rv = 0;
ip4_address_t e_addr, l_addr;
nat_protocol_t proto;
ip_protocol_t proto;
clib_memcpy (&e_addr, mp->external_addr, 4);
clib_memcpy (&l_addr, mp->local.addr, 4);
proto = ip_proto_to_nat_proto (mp->protocol);
proto = mp->protocol;
rv = nat44_ed_add_del_lb_static_mapping_local (
e_addr, mp->external_port, l_addr, mp->local.port, proto,
@@ -1219,13 +1219,14 @@ send_nat44_lb_static_mapping_details (snat_static_mapping_t *m,
rmp = vl_msg_api_alloc (
sizeof (*rmp) + (pool_elts (m->locals) * sizeof (nat44_lb_addr_port_t)));
clib_memset (rmp, 0, sizeof (*rmp));
rmp->_vl_msg_id =
ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
rmp->external_port = m->external_port;
rmp->protocol = nat_proto_to_ip_proto (m->proto);
rmp->protocol = m->proto;
rmp->context = context;
if (is_sm_self_twice_nat (m->flags))
@@ -1740,25 +1741,16 @@ send_nat44_user_session_details (snat_session_t * s,
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 = s->out2in.port;
rmp->inside_port = s->in2out.port;
rmp->protocol = clib_host_to_net_u16 (s->proto);
clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
rmp->ext_host_port = s->ext_host_port;
if (nat44_ed_is_twice_nat_session (s))
{
rmp->outside_port = 0;
rmp->inside_port = 0;
rmp->protocol = ntohs (s->in2out.port);
clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
rmp->ext_host_nat_port = s->ext_host_nat_port;
}
else
{
rmp->outside_port = s->out2in.port;
rmp->inside_port = s->in2out.port;
rmp->protocol = ntohs (nat_proto_to_ip_proto (s->nat_proto));
}
clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
rmp->ext_host_port = s->ext_host_port;
if (nat44_ed_is_twice_nat_session (s))
{
clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
rmp->ext_host_nat_port = s->ext_host_nat_port;
}
vl_api_send_msg (reg, (u8 *) rmp);
}
@@ -1824,18 +1816,9 @@ send_nat44_user_session_v2_details (snat_session_t *s,
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 (nat_proto_to_ip_proto (s->nat_proto));
}
rmp->outside_port = s->out2in.port;
rmp->inside_port = s->in2out.port;
rmp->protocol = clib_host_to_net_u16 (s->proto);
clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
rmp->ext_host_port = s->ext_host_port;
if (nat44_ed_is_twice_nat_session (s))
@@ -1844,8 +1827,26 @@ send_nat44_user_session_v2_details (snat_session_t *s,
rmp->ext_host_nat_port = s->ext_host_nat_port;
}
sess_timeout_time = s->last_heard + (f64) nat_session_get_timeout (
&sm->timeouts, s->nat_proto, s->state);
sess_timeout_time = s->last_heard;
switch (s->proto)
{
case IP_PROTOCOL_TCP:
if (s->state)
sess_timeout_time += sm->timeouts.tcp.established;
else
sess_timeout_time += sm->timeouts.tcp.transitory;
break;
case IP_PROTOCOL_UDP:
sess_timeout_time += sm->timeouts.udp;
break;
case IP_PROTOCOL_ICMP:
sess_timeout_time += sm->timeouts.icmp;
break;
default:
sess_timeout_time += sm->timeouts.udp;
break;
}
rmp->is_timed_out = (now >= sess_timeout_time);
vl_api_send_msg (reg, (u8 *) rmp);
+16 -26
View File
@@ -98,7 +98,6 @@ nat44_handoff_classify_node_fn_inline (vlib_main_t * vm,
u32 next0 = NAT_NEXT_IN2OUT_CLASSIFY;
ip4_header_t *ip0;
snat_address_t *ap;
clib_bihash_kv_8_8_t kv0, value0;
/* speculatively enqueue b0 to the current next frame */
bi0 = from[0];
@@ -122,23 +121,19 @@ nat44_handoff_classify_node_fn_inline (vlib_main_t * vm,
if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
{
init_nat_k (&kv0, ip0->dst_address, 0, 0, 0);
/* try to classify the fragment based on IP header alone */
if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external,
&kv0, &value0))
m = nat44_ed_sm_o2i_lookup (sm, ip0->dst_address, 0, 0, 0);
if (m)
{
m = pool_elt_at_index (sm->static_mappings, value0.value);
if (m->local_addr.as_u32 != m->external_addr.as_u32)
next0 = NAT_NEXT_OUT2IN_CLASSIFY;
goto enqueue0;
}
init_nat_k (&kv0, ip0->dst_address,
vnet_buffer (b0)->ip.reass.l4_dst_port, 0,
ip_proto_to_nat_proto (ip0->protocol));
if (!clib_bihash_search_8_8
(&sm->static_mapping_by_external, &kv0, &value0))
m = nat44_ed_sm_o2i_lookup (
sm, ip0->dst_address, vnet_buffer (b0)->ip.reass.l4_dst_port,
0, ip0->protocol);
if (m)
{
m = pool_elt_at_index (sm->static_mappings, value0.value);
if (m->local_addr.as_u32 != m->external_addr.as_u32)
next0 = NAT_NEXT_OUT2IN_CLASSIFY;
}
@@ -202,7 +197,6 @@ nat44_ed_classify_node_fn_inline (vlib_main_t * vm,
u32 sw_if_index0, rx_fib_index0;
ip4_header_t *ip0;
snat_address_t *ap;
clib_bihash_kv_8_8_t kv0, value0;
clib_bihash_kv_16_8_t ed_kv0, ed_value0;
/* speculatively enqueue b0 to the current next frame */
@@ -227,11 +221,11 @@ nat44_ed_classify_node_fn_inline (vlib_main_t * vm,
rx_fib_index0 =
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
sw_if_index0);
init_ed_k (&ed_kv0, ip0->src_address,
init_ed_k (&ed_kv0, ip0->src_address.as_u32,
vnet_buffer (b0)->ip.reass.l4_src_port,
ip0->dst_address,
vnet_buffer (b0)->ip.reass.l4_dst_port,
rx_fib_index0, ip0->protocol);
ip0->dst_address.as_u32,
vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0,
ip0->protocol);
/* process whole packet */
if (!clib_bihash_search_16_8 (&sm->flow_hash, &ed_kv0,
&ed_value0))
@@ -272,23 +266,19 @@ nat44_ed_classify_node_fn_inline (vlib_main_t * vm,
if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
{
init_nat_k (&kv0, ip0->dst_address, 0, 0, 0);
/* try to classify the fragment based on IP header alone */
if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external,
&kv0, &value0))
m = nat44_ed_sm_o2i_lookup (sm, ip0->dst_address, 0, 0, 0);
if (m)
{
m = pool_elt_at_index (sm->static_mappings, value0.value);
if (m->local_addr.as_u32 != m->external_addr.as_u32)
next0 = NAT_NEXT_OUT2IN_ED_FAST_PATH;
goto enqueue0;
}
init_nat_k (&kv0, ip0->dst_address,
vnet_buffer (b0)->ip.reass.l4_dst_port, 0,
ip_proto_to_nat_proto (ip0->protocol));
if (!clib_bihash_search_8_8
(&sm->static_mapping_by_external, &kv0, &value0))
m = nat44_ed_sm_o2i_lookup (
sm, ip0->dst_address, vnet_buffer (b0)->ip.reass.l4_dst_port,
0, ip0->protocol);
if (m)
{
m = pool_elt_at_index (sm->static_mappings, value0.value);
if (m->local_addr.as_u32 != m->external_addr.as_u32)
next0 = NAT_NEXT_OUT2IN_ED_FAST_PATH;
}
File diff suppressed because it is too large Load Diff
+15 -70
View File
@@ -20,39 +20,6 @@
#include <nat/nat44-ed/nat44_ed.h>
#include <nat/nat44-ed/nat44_ed_inlines.h>
uword
unformat_nat_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 = NAT_PROTOCOL_##N;
foreach_nat_protocol
#undef _
else
return 0;
return 1;
}
u8 *
format_nat_protocol (u8 * s, va_list * args)
{
u32 i = va_arg (*args, u32);
u8 *t = 0;
switch (i)
{
#define _(N, j, n, str) case NAT_PROTOCOL_##N: t = (u8 *) str; break;
foreach_nat_protocol
#undef _
default:
s = format (s, "unknown");
return s;
}
s = format (s, "%s", t);
return s;
}
u8 *
format_nat_addr_and_port_alloc_alg (u8 * s, va_list * args)
{
@@ -72,25 +39,6 @@ format_nat_addr_and_port_alloc_alg (u8 * s, va_list * args)
return s;
}
u8 *
format_snat_key (u8 * s, va_list * args)
{
u64 key = va_arg (*args, u64);
ip4_address_t addr;
u16 port;
nat_protocol_t protocol;
u32 fib_index;
split_nat_key (key, &addr, &port, &fib_index, &protocol);
s = format (s, "%U proto %U port %d fib %d",
format_ip4_address, &addr,
format_nat_protocol, protocol,
clib_net_to_host_u16 (port), fib_index);
return s;
}
u8 *
format_snat_session_state (u8 * s, va_list * args)
{
@@ -116,7 +64,7 @@ format_snat_session (u8 * s, va_list * args)
va_arg (*args, snat_main_per_thread_data_t *);
snat_session_t *sess = va_arg (*args, snat_session_t *);
if (snat_is_unk_proto_session (sess))
if (nat44_ed_is_unk_proto (sess->proto))
{
s = format (s, " i2o %U proto %u fib %u\n",
format_ip4_address, &sess->in2out.addr,
@@ -127,14 +75,13 @@ format_snat_session (u8 * s, va_list * args)
}
else
{
s = format (s, " i2o %U proto %U port %d fib %d\n",
format_ip4_address, &sess->in2out.addr,
format_nat_protocol, sess->nat_proto,
s = format (s, " i2o %U proto %U port %d fib %d\n", format_ip4_address,
&sess->in2out.addr, format_ip_protocol, sess->proto,
clib_net_to_host_u16 (sess->in2out.port),
sess->in2out.fib_index);
s = format (s, " o2i %U proto %U port %d fib %d\n",
format_ip4_address, &sess->out2in.addr, format_nat_protocol,
sess->nat_proto, clib_net_to_host_u16 (sess->out2in.port),
format_ip4_address, &sess->out2in.addr, format_ip_protocol,
sess->proto, clib_net_to_host_u16 (sess->out2in.port),
sess->out2in.fib_index);
}
if (nat44_ed_is_twice_nat_session (sess))
@@ -183,9 +130,8 @@ format_snat_static_mapping (u8 * s, va_list * args)
s = format (s, "identity mapping %U",
format_ip4_address, &m->local_addr);
else
s = format (s, "identity mapping %U %U:%d",
format_nat_protocol, m->proto,
format_ip4_address, &m->local_addr,
s = format (s, "identity mapping %U %U:%d", format_ip_protocol,
m->proto, format_ip4_address, &m->local_addr,
clib_net_to_host_u16 (m->local_port));
pool_foreach (local, m->locals)
@@ -209,8 +155,8 @@ format_snat_static_mapping (u8 * s, va_list * args)
if (is_sm_lb (m->flags))
{
s =
format (s, "%U external %U:%d %s %s", format_nat_protocol,
m->proto, format_ip4_address, &m->external_addr,
format (s, "%U external %U:%d %s %s", format_ip_protocol, m->proto,
format_ip4_address, &m->external_addr,
clib_net_to_host_u16 (m->external_port),
is_sm_twice_nat (m->flags) ?
"twice-nat" :
@@ -227,7 +173,7 @@ format_snat_static_mapping (u8 * s, va_list * args)
}
else
s = format (s, "%U local %U:%d external %U:%d vrf %d %s %s",
format_nat_protocol, m->proto, format_ip4_address,
format_ip_protocol, m->proto, format_ip4_address,
&m->local_addr, clib_net_to_host_u16 (m->local_port),
format_ip4_address, &m->external_addr,
clib_net_to_host_u16 (m->external_port), m->vrf_id,
@@ -250,12 +196,11 @@ format_snat_static_map_to_resolve (u8 * s, va_list * args)
format_ip4_address, &m->l_addr,
format_vnet_sw_if_index_name, vnm, m->sw_if_index, m->vrf_id);
else
s = format (s, "%U local %U:%d external %U:%d vrf %d",
format_nat_protocol, m->proto,
format_ip4_address, &m->l_addr,
clib_net_to_host_u16 (m->l_port),
format_vnet_sw_if_index_name, vnm, m->sw_if_index,
clib_net_to_host_u16 (m->e_port), m->vrf_id);
s = format (s, "%U local %U:%d external %U:%d vrf %d", format_ip_protocol,
m->proto, format_ip4_address, &m->l_addr,
clib_net_to_host_u16 (m->l_port), format_vnet_sw_if_index_name,
vnm, m->sw_if_index, clib_net_to_host_u16 (m->e_port),
m->vrf_id);
return s;
}
File diff suppressed because it is too large Load Diff
+69 -109
View File
@@ -26,116 +26,52 @@
#include <nat/lib/log.h>
#include <nat/nat44-ed/nat44_ed.h>
always_inline u64
calc_nat_key (ip4_address_t addr, u16 port, u32 fib_index, u8 proto)
{
ASSERT (fib_index <= (1 << 14) - 1);
ASSERT (proto <= (1 << 3) - 1);
return (u64) addr.as_u32 << 32 | (u64) port << 16 | fib_index << 3 |
(proto & 0x7);
}
always_inline void
split_nat_key (u64 key, ip4_address_t *addr, u16 *port, u32 *fib_index,
nat_protocol_t *proto)
init_ed_k (clib_bihash_kv_16_8_t *kv, u32 l_addr, u16 l_port, u32 r_addr,
u16 r_port, u32 fib_index, ip_protocol_t proto)
{
if (addr)
{
addr->as_u32 = key >> 32;
}
if (port)
{
*port = (key >> 16) & (u16) ~0;
}
if (fib_index)
{
*fib_index = key >> 3 & ((1 << 13) - 1);
}
if (proto)
{
*proto = key & 0x7;
}
}
always_inline void
init_nat_k (clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port,
u32 fib_index, nat_protocol_t proto)
{
kv->key = calc_nat_key (addr, port, fib_index, proto);
kv->value = ~0ULL;
}
always_inline void
init_nat_kv (clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port,
u32 fib_index, nat_protocol_t proto, u32 thread_index,
u32 session_index)
{
init_nat_k (kv, addr, port, fib_index, proto);
kv->value = (u64) thread_index << 32 | session_index;
}
always_inline void
init_nat_i2o_k (clib_bihash_kv_8_8_t *kv, snat_session_t *s)
{
return init_nat_k (kv, s->in2out.addr, s->in2out.port, s->in2out.fib_index,
s->nat_proto);
}
always_inline void
init_nat_i2o_kv (clib_bihash_kv_8_8_t *kv, snat_session_t *s, u32 thread_index,
u32 session_index)
{
init_nat_k (kv, s->in2out.addr, s->in2out.port, s->in2out.fib_index,
s->nat_proto);
kv->value = (u64) thread_index << 32 | session_index;
}
always_inline void
init_nat_o2i_k (clib_bihash_kv_8_8_t *kv, snat_session_t *s)
{
return init_nat_k (kv, s->out2in.addr, s->out2in.port, s->out2in.fib_index,
s->nat_proto);
}
always_inline void
init_nat_o2i_kv (clib_bihash_kv_8_8_t *kv, snat_session_t *s, u32 thread_index,
u32 session_index)
{
init_nat_k (kv, s->out2in.addr, s->out2in.port, s->out2in.fib_index,
s->nat_proto);
kv->value = (u64) thread_index << 32 | session_index;
}
always_inline u32
nat_value_get_thread_index (clib_bihash_kv_8_8_t *value)
{
return value->value >> 32;
}
always_inline u32
nat_value_get_session_index (clib_bihash_kv_8_8_t *value)
{
return value->value & ~(u32) 0;
}
always_inline void
init_ed_k (clib_bihash_kv_16_8_t *kv, ip4_address_t l_addr, u16 l_port,
ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto)
{
kv->key[0] = (u64) r_addr.as_u32 << 32 | l_addr.as_u32;
kv->key[0] = (u64) r_addr << 32 | l_addr;
kv->key[1] =
(u64) r_port << 48 | (u64) l_port << 32 | fib_index << 8 | proto;
}
always_inline void
init_ed_kv (clib_bihash_kv_16_8_t *kv, ip4_address_t l_addr, u16 l_port,
ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto,
u32 thread_index, u32 session_index)
init_ed_kv (clib_bihash_kv_16_8_t *kv, u32 l_addr, u16 l_port, u32 r_addr,
u16 r_port, u32 fib_index, u8 proto, u32 thread_index,
u32 session_index)
{
init_ed_k (kv, l_addr, l_port, r_addr, r_port, fib_index, proto);
kv->value = (u64) thread_index << 32 | session_index;
}
always_inline void
nat44_ed_sm_init_i2o_kv (clib_bihash_kv_16_8_t *kv, u32 addr, u16 port,
u32 fib_index, u8 proto, u32 sm_index)
{
return init_ed_kv (kv, addr, port, 0, 0, fib_index, proto, 0, sm_index);
}
always_inline void
nat44_ed_sm_init_o2i_kv (clib_bihash_kv_16_8_t *kv, u32 e_addr, u16 e_port,
u32 fib_index, u8 proto, u32 sm_index)
{
return init_ed_kv (kv, 0, 0, e_addr, e_port, fib_index, proto, 0, sm_index);
}
always_inline void
nat44_ed_sm_init_i2o_k (clib_bihash_kv_16_8_t *kv, u32 addr, u16 port,
u32 fib_index, u8 proto)
{
return nat44_ed_sm_init_i2o_kv (kv, addr, port, fib_index, proto, 0);
}
always_inline void
nat44_ed_sm_init_o2i_k (clib_bihash_kv_16_8_t *kv, u32 e_addr, u16 e_port,
u32 fib_index, u8 proto)
{
return nat44_ed_sm_init_o2i_kv (kv, e_addr, e_port, fib_index, proto, 0);
}
always_inline u32
ed_value_get_thread_index (clib_bihash_kv_16_8_t *value)
{
@@ -215,16 +151,16 @@ nat_get_icmp_session_lookup_values (vlib_buffer_t *b, ip4_header_t *ip0,
*lookup_protocol = inner_ip0->protocol;
lookup_saddr->as_u32 = inner_ip0->dst_address.as_u32;
lookup_daddr->as_u32 = inner_ip0->src_address.as_u32;
switch (ip_proto_to_nat_proto (inner_ip0->protocol))
switch (inner_ip0->protocol)
{
case NAT_PROTOCOL_ICMP:
case IP_PROTOCOL_ICMP:
inner_icmp0 = (icmp46_header_t *) l4_header;
inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
*lookup_sport = inner_echo0->identifier;
*lookup_dport = inner_echo0->identifier;
break;
case NAT_PROTOCOL_UDP:
case NAT_PROTOCOL_TCP:
case IP_PROTOCOL_UDP:
case IP_PROTOCOL_TCP:
*lookup_sport = ((tcp_udp_header_t *) l4_header)->dst_port;
*lookup_dport = ((tcp_udp_header_t *) l4_header)->src_port;
break;
@@ -238,13 +174,15 @@ nat_get_icmp_session_lookup_values (vlib_buffer_t *b, ip4_header_t *ip0,
always_inline u32
nat44_session_get_timeout (snat_main_t *sm, snat_session_t *s)
{
switch (s->nat_proto)
switch (s->proto)
{
case NAT_PROTOCOL_ICMP:
case IP_PROTOCOL_ICMP:
/* fallthrough */
case IP_PROTOCOL_ICMP6:
return sm->timeouts.icmp;
case NAT_PROTOCOL_UDP:
case IP_PROTOCOL_UDP:
return sm->timeouts.udp;
case NAT_PROTOCOL_TCP:
case IP_PROTOCOL_TCP:
{
if (s->state)
return sm->timeouts.tcp.transitory;
@@ -300,7 +238,7 @@ nat_ed_lru_insert (snat_main_per_thread_data_t *tsm, snat_session_t *s,
static_always_inline void
nat_6t_flow_to_ed_k (clib_bihash_kv_16_8_t *kv, nat_6t_flow_t *f)
{
init_ed_k (kv, f->match.saddr, f->match.sport, f->match.daddr,
init_ed_k (kv, f->match.saddr.as_u32, f->match.sport, f->match.daddr.as_u32,
f->match.dport, f->match.fib_index, f->match.proto);
}
@@ -308,7 +246,7 @@ static_always_inline void
nat_6t_flow_to_ed_kv (clib_bihash_kv_16_8_t *kv, nat_6t_flow_t *f,
u32 thread_idx, u32 session_idx)
{
init_ed_kv (kv, f->match.saddr, f->match.sport, f->match.daddr,
init_ed_kv (kv, f->match.saddr.as_u32, f->match.sport, f->match.daddr.as_u32,
f->match.dport, f->match.fib_index, f->match.proto, thread_idx,
session_idx);
}
@@ -348,6 +286,15 @@ nat_ed_ses_o2i_flow_hash_add_del (snat_main_t *sm, u32 thread_idx,
else
{
nat_6t_flow_to_ed_kv (&kv, &s->o2i, thread_idx, s - tsm->sessions);
if (!(s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING))
{
if (nat44_ed_sm_o2i_lookup (sm, s->o2i.match.daddr,
s->o2i.match.dport, 0,
s->o2i.match.proto))
{
return -1;
}
}
nat_6t_l3_l4_csum_calc (&s->o2i);
}
ASSERT (thread_idx == s->thread_index);
@@ -396,7 +343,7 @@ nat_lru_free_one_with_head (snat_main_t *sm, int thread_index, f64 now,
if (now >= sess_timeout_time ||
(s->tcp_closed_timestamp && now >= s->tcp_closed_timestamp))
{
nat_free_session_data (sm, s, thread_index, 0);
nat44_ed_free_session_data (sm, s, thread_index, 0);
nat_ed_session_delete (sm, s, thread_index, 0);
return 1;
}
@@ -868,6 +815,19 @@ nat44_session_update_lru (snat_main_t *sm, snat_session_t *s, u32 thread_index)
}
}
static_always_inline int
nat44_ed_is_unk_proto (u8 proto)
{
static const int lookup_table[256] = {
[IP_PROTOCOL_TCP] = 1,
[IP_PROTOCOL_UDP] = 1,
[IP_PROTOCOL_ICMP] = 1,
[IP_PROTOCOL_ICMP6] = 1,
};
return 1 - lookup_table[proto];
}
#endif /* __included_nat44_ed_inlines_h__ */
/*
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -1102,7 +1102,8 @@ nat44_ei_free_session_data_v2 (nat44_ei_main_t *nm, nat44_ei_session_t *s,
/* log NAT event */
nat_ipfix_logging_nat44_ses_delete (
thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
s->nat_proto, s->in2out.port, s->out2in.port, s->in2out.fib_index);
nat_proto_to_ip_proto (s->nat_proto), s->in2out.port, s->out2in.port,
s->in2out.fib_index);
nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
s->ext_host_port, s->nat_proto, s->out2in.fib_index,
@@ -1270,7 +1271,8 @@ nat44_ei_free_session_data (nat44_ei_main_t *nm, nat44_ei_session_t *s,
nat_ipfix_logging_nat44_ses_delete (
thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
s->nat_proto, s->in2out.port, s->out2in.port, s->in2out.fib_index);
nat_proto_to_ip_proto (s->nat_proto), s->in2out.port, s->out2in.port,
s->in2out.fib_index);
nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
s->ext_host_port, s->nat_proto, s->out2in.fib_index,
+1
View File
@@ -36,6 +36,7 @@
#include <nat/lib/lib.h>
#include <nat/lib/inlines.h>
#include <nat/lib/nat_proto.h>
/* default number of worker handoff frame queue elements */
#define NAT_FQ_NELTS_DEFAULT 64
+7 -9
View File
@@ -271,13 +271,10 @@ nat44_i2o_is_idle_session_cb (clib_bihash_kv_8_8_t * kv, void *arg)
if (clib_bihash_add_del_8_8 (&nm->out2in, &s_kv, 0))
nat_elog_warn (nm, "out2in key del failed");
nat_ipfix_logging_nat44_ses_delete (ctx->thread_index,
s->in2out.addr.as_u32,
s->out2in.addr.as_u32,
s->nat_proto,
s->in2out.port,
s->out2in.port,
s->in2out.fib_index);
nat_ipfix_logging_nat44_ses_delete (
ctx->thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
nat_proto_to_ip_proto (s->nat_proto), s->in2out.port, s->out2in.port,
s->in2out.fib_index);
nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
&s->in2out.addr, s->in2out.port,
@@ -430,8 +427,9 @@ slow_path (nat44_ei_main_t *nm, vlib_buffer_t *b0, ip4_header_t *ip0,
/* log NAT event */
nat_ipfix_logging_nat44_ses_create (
thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32, s->nat_proto,
s->in2out.port, s->out2in.port, s->in2out.fib_index);
thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
nat_proto_to_ip_proto (s->nat_proto), s->in2out.port, s->out2in.port,
s->in2out.fib_index);
nat_syslog_nat44_apmadd (s->user_index, s->in2out.fib_index, &s->in2out.addr,
s->in2out.port, &s->out2in.addr, s->out2in.port,
@@ -20,6 +20,7 @@
#include <nat/nat44-ei/nat44_ei.h>
#include <nat/nat44-ei/nat44_ei_ha.h>
#include <nat/lib/nat_proto.h>
always_inline u64
calc_nat_key (ip4_address_t addr, u16 port, u32 fib_index, u8 proto)
@@ -220,6 +221,29 @@ nat44_ei_session_update_counters (nat44_ei_session_t *s, f64 now, uword bytes,
&s->ha_last_refreshed, now);
}
static_always_inline u32
nat_session_get_timeout (nat_timeouts_t *timeouts, nat_protocol_t proto,
u8 state)
{
switch (proto)
{
case NAT_PROTOCOL_ICMP:
return timeouts->icmp;
case NAT_PROTOCOL_UDP:
return timeouts->udp;
case NAT_PROTOCOL_TCP:
{
if (state)
return timeouts->tcp.transitory;
else
return timeouts->tcp.established;
}
default:
return timeouts->udp;
}
return 0;
}
#endif /* __included_nat44_ei_inlines_h__ */
/*
+8 -13
View File
@@ -124,13 +124,10 @@ nat44_o2i_is_idle_session_cb (clib_bihash_kv_8_8_t * kv, void *arg)
if (clib_bihash_add_del_8_8 (&nm->in2out, &s_kv, 0))
nat_elog_warn (nm, "out2in key del failed");
nat_ipfix_logging_nat44_ses_delete (ctx->thread_index,
s->in2out.addr.as_u32,
s->out2in.addr.as_u32,
s->nat_proto,
s->in2out.port,
s->out2in.port,
s->in2out.fib_index);
nat_ipfix_logging_nat44_ses_delete (
ctx->thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
nat_proto_to_ip_proto (s->nat_proto), s->in2out.port, s->out2in.port,
s->in2out.fib_index);
nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
&s->in2out.addr, s->in2out.port,
@@ -233,12 +230,10 @@ create_session_for_static_mapping (
nat_elog_notice (nm, "out2in key add failed");
/* log NAT event */
nat_ipfix_logging_nat44_ses_create (thread_index,
s->in2out.addr.as_u32,
s->out2in.addr.as_u32,
s->nat_proto,
s->in2out.port,
s->out2in.port, s->in2out.fib_index);
nat_ipfix_logging_nat44_ses_create (
thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32,
nat_proto_to_ip_proto (s->nat_proto), s->in2out.port, s->out2in.port,
s->in2out.fib_index);
nat_syslog_nat44_apmadd (s->user_index, s->in2out.fib_index,
&s->in2out.addr, s->in2out.port, &s->out2in.addr,
+1
View File
@@ -18,6 +18,7 @@
#include <vnet/vnet.h>
#include <vnet/ip/ip.h>
#include <vnet/fib/fib_source.h>
#include <nat/lib/nat_proto.h>
#include <vppinfra/bihash_24_8.h>
#include <vppinfra/bihash_48_8.h>
+2
View File
@@ -1304,6 +1304,8 @@ class VppTestCase(CPUInterface, unittest.TestCase):
n_rx = len(pkts)
self.pg_send(intf, pkts, worker=worker, trace=trace)
rx = output.get_capture(n_rx)
if trace:
self.logger.debug(self.vapi.cli("show trace"))
return rx
def send_and_expect_only(self, intf, pkts, output, timeout=None):
+6 -9
View File
@@ -19,7 +19,8 @@ from vpp_ip_route import VppIpRoute, VppRoutePath
from vpp_papi import VppEnum
class NAT44EDTestCase(VppTestCase):
class TestNAT44ED(VppTestCase):
""" NAT44ED Test Case """
nat_addr = '10.0.0.3'
@@ -37,11 +38,11 @@ class NAT44EDTestCase(VppTestCase):
max_sessions = 100
def setUp(self):
super(NAT44EDTestCase, self).setUp()
super().setUp()
self.plugin_enable()
def tearDown(self):
super(NAT44EDTestCase, self).tearDown()
super().tearDown()
if not self.vpp_dead:
self.plugin_disable()
@@ -146,7 +147,7 @@ class NAT44EDTestCase(VppTestCase):
@classmethod
def setUpClass(cls):
super(NAT44EDTestCase, cls).setUpClass()
super().setUpClass()
cls.create_pg_interfaces(range(12))
cls.interfaces = list(cls.pg_interfaces[:4])
@@ -910,10 +911,6 @@ class NAT44EDTestCase(VppTestCase):
self.assertEqual(sd_params.get('XDPORT'),
"%d" % self.tcp_external_port)
class TestNAT44ED(NAT44EDTestCase):
""" NAT44ED Test Case """
def test_icmp_error(self):
""" NAT44ED test ICMP error message with inner header"""
@@ -2258,7 +2255,7 @@ class TestNAT44EDMW(TestNAT44ED):
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
capture = self.pg1.get_capture(pkt_count * 3)
capture = self.pg1.get_capture(pkt_count * 3, timeout=5)
if_idx = self.pg0.sw_if_index
tc2 = self.statistics['/nat44-ed/in2out/slowpath/tcp']
+229
View File
@@ -0,0 +1,229 @@
#!/usr/bin/env python3
"""NAT44 ED output-feature tests"""
import random
import unittest
from scapy.layers.inet import ICMP, Ether, IP, TCP
from scapy.packet import Raw
from scapy.data import IP_PROTOS
from framework import VppTestCase, VppTestRunner
from vpp_papi import VppEnum
def get_nat44_ed_in2out_worker_index(ip, vpp_worker_count):
if 0 == vpp_worker_count:
return 0
numeric = socket.inet_aton(ip)
numeric = struct.unpack("!L", numeric)[0]
numeric = socket.htonl(numeric)
h = numeric + (numeric >> 8) + (numeric >> 16) + (numeric >> 24)
return 1 + h % vpp_worker_count
class TestNAT44EDOutput(VppTestCase):
""" NAT44 ED output feature Test Case """
max_sessions = 1024
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.create_pg_interfaces(range(2))
cls.interfaces = list(cls.pg_interfaces)
@classmethod
def tearDownClass(cls):
super().tearDownClass()
def setUp(self):
super().setUp()
for i in self.interfaces:
i.admin_up()
i.config_ip4()
i.resolve_arp()
self.vapi.nat44_ed_plugin_enable_disable(sessions=self.max_sessions,
enable=1)
def tearDown(self):
if not self.vpp_dead:
self.logger.debug(self.vapi.cli("show nat44 sessions"))
super().tearDown()
if not self.vpp_dead:
for i in self.pg_interfaces:
i.unconfig_ip4()
i.admin_down()
self.vapi.nat44_ed_plugin_enable_disable(enable=0)
def test_static_dynamic(self):
""" Create static mapping which matches existing dynamic mapping """
old_timeouts = self.vapi.nat_get_timeouts()
new_transitory = 2
self.vapi.nat_set_timeouts(
udp=old_timeouts.udp,
tcp_established=old_timeouts.tcp_established,
icmp=old_timeouts.icmp,
tcp_transitory=new_transitory)
local_host = self.pg0.remote_ip4
remote_host = self.pg1.remote_ip4
nat_intf = self.pg1
outside_addr = nat_intf.local_ip4
self.vapi.nat44_add_del_address_range(first_ip_address=outside_addr,
last_ip_address=outside_addr,
vrf_id=0xffffffff,
is_add=1,
flags=0)
self.vapi.nat44_interface_add_del_feature(
sw_if_index=self.pg0.sw_if_index,
is_add=1)
self.vapi.nat44_interface_add_del_feature(
sw_if_index=self.pg0.sw_if_index,
flags=VppEnum.vl_api_nat_config_flags_t.NAT_IS_INSIDE, is_add=1)
self.vapi.nat44_interface_add_del_output_feature(
is_add=1,
sw_if_index=self.pg1.sw_if_index)
thread_index = get_nat44_ed_in2out_worker_index(
local_host, self.vpp_worker_count)
port_per_thread = int((0xffff-1024) / max(1, self.vpp_worker_count))
local_sport = 1024 + random.randint(1, port_per_thread)
if self.vpp_worker_count > 0:
local_sport += port_per_thread * (thread_index - 1)
remote_dport = 10000
pg0 = self.pg0
pg1 = self.pg1
# first setup a dynamic TCP session
# SYN packet in->out
p = (Ether(src=pg0.remote_mac, dst=pg0.local_mac) /
IP(src=local_host, dst=remote_host) /
TCP(sport=local_sport, dport=remote_dport, flags="S"))
p = self.send_and_expect(pg0, [p], pg1)[0]
self.assertEqual(p[IP].src, outside_addr)
self.assertEqual(p[TCP].sport, local_sport)
outside_port = p[TCP].sport
# SYN+ACK packet out->in
p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
IP(src=remote_host, dst=outside_addr) /
TCP(sport=remote_dport, dport=outside_port, flags="SA"))
self.send_and_expect(pg1, [p], pg0)
# ACK packet in->out
p = (Ether(src=pg0.remote_mac, dst=pg0.local_mac) /
IP(src=local_host, dst=remote_host) /
TCP(sport=local_sport, dport=remote_dport, flags="A"))
self.send_and_expect(pg0, [p], pg1)
# now we have a session up, create a conflicting static mapping
self.vapi.nat44_add_del_static_mapping(
is_add=1,
local_ip_address=local_host,
external_ip_address=outside_addr,
external_sw_if_index=0xffffffff,
local_port=local_sport,
external_port=outside_port,
protocol=IP_PROTOS.tcp,
flags=VppEnum.vl_api_nat_config_flags_t.NAT_IS_OUT2IN_ONLY)
sessions = self.vapi.nat44_user_session_dump(local_host, 0)
self.assertEqual(1, len(sessions))
# now send some more data over existing session - it should pass
# in->out
p = (Ether(src=pg0.remote_mac, dst=pg0.local_mac) /
IP(src=local_host, dst=remote_host) /
TCP(sport=local_sport, dport=remote_dport) /
Raw("zippity zap"))
self.send_and_expect(pg0, [p], pg1)
# out->in
p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
IP(src=remote_host, dst=outside_addr) /
TCP(sport=remote_dport, dport=outside_port) /
Raw("flippity flop"))
self.send_and_expect(pg1, [p], pg0)
# now close the session
# FIN packet in -> out
p = (Ether(src=pg0.remote_mac, dst=pg0.local_mac) /
IP(src=local_host, dst=remote_host) /
TCP(sport=local_sport, dport=remote_dport, flags="FA", seq=100,
ack=300))
self.send_and_expect(pg0, [p], pg1)
# FIN+ACK packet out -> in
p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
IP(src=remote_host, dst=outside_addr) /
TCP(sport=remote_dport, dport=outside_port, flags="FA", seq=300,
ack=101))
self.send_and_expect(pg1, [p], pg0)
# ACK packet in -> out
p = (Ether(src=pg0.remote_mac, dst=pg0.local_mac) /
IP(src=local_host, dst=remote_host) /
TCP(sport=local_sport, dport=remote_dport, flags="A", seq=101,
ack=301))
self.send_and_expect(pg0, [p], pg1)
# session now in transitory timeout
# try SYN packet in->out - should be dropped
p = (Ether(src=pg0.remote_mac, dst=pg0.local_mac) /
IP(src=local_host, dst=remote_host) /
TCP(sport=local_sport, dport=remote_dport, flags="S"))
pg0.add_stream(p)
self.pg_enable_capture()
self.pg_start()
self.sleep(new_transitory, "wait for transitory timeout")
pg0.assert_nothing_captured(0)
# session should still exist
sessions = self.vapi.nat44_user_session_dump(pg0.remote_ip4, 0)
self.assertEqual(1, len(sessions))
# send FIN+ACK packet in->out - will cause session to be wiped
# but won't create a new session
p = (Ether(src=pg0.remote_mac, dst=pg0.local_mac) /
IP(src=local_host, dst=remote_host) /
TCP(sport=local_sport, dport=remote_dport, flags="FA", seq=300,
ack=101))
pg1.add_stream(p)
self.pg_enable_capture()
self.pg_start()
pg0.assert_nothing_captured(0)
sessions = self.vapi.nat44_user_session_dump(pg0.remote_ip4, 0)
self.assertEqual(0, len(sessions))
# create a new session and make sure the outside port is remapped
# SYN packet in->out
p = (Ether(src=pg0.remote_mac, dst=pg0.local_mac) /
IP(src=local_host, dst=remote_host) /
TCP(sport=local_sport, dport=remote_dport, flags="S"))
p = self.send_and_expect(pg0, [p], pg1)[0]
self.assertEqual(p[IP].src, outside_addr)
self.assertNotEqual(p[TCP].sport, local_sport)
# make sure static mapping works and creates a new session
# SYN packet out->in
p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
IP(src=remote_host, dst=outside_addr) /
TCP(sport=remote_dport, dport=outside_port, flags="S"))
self.send_and_expect(pg1, [p], pg0)
sessions = self.vapi.nat44_user_session_dump(pg0.remote_ip4, 0)
self.assertEqual(2, len(sessions))
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)

Some files were not shown because too many files have changed in this diff Show More