From 69b7599e4b061a8996205f0304232ede84cb70d4 Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Wed, 26 May 2021 13:02:35 +0200 Subject: 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 Change-Id: Ieeba691d83a83887d0a0baccd5f3832f66126096 --- src/plugins/nat/det44/det44.h | 1 + src/plugins/nat/lib/alloc.h | 1 + src/plugins/nat/lib/inlines.h | 31 - src/plugins/nat/lib/ipfix_logging.c | 54 +- src/plugins/nat/lib/ipfix_logging.h | 14 +- src/plugins/nat/lib/lib.c | 1 + src/plugins/nat/lib/lib.h | 40 -- src/plugins/nat/lib/nat_proto.h | 75 +++ src/plugins/nat/lib/nat_syslog.c | 109 +--- src/plugins/nat/lib/nat_syslog.h | 13 +- src/plugins/nat/lib/nat_syslog_constants.h | 62 ++ src/plugins/nat/nat44-ed/nat44_ed.c | 824 ++++++++++++--------------- src/plugins/nat/nat44-ed/nat44_ed.h | 114 ++-- src/plugins/nat/nat44-ed/nat44_ed_affinity.c | 7 +- src/plugins/nat/nat44-ed/nat44_ed_api.c | 55 +- src/plugins/nat/nat44-ed/nat44_ed_classify.c | 42 +- src/plugins/nat/nat44-ed/nat44_ed_cli.c | 186 +++--- src/plugins/nat/nat44-ed/nat44_ed_format.c | 85 +-- src/plugins/nat/nat44-ed/nat44_ed_in2out.c | 227 +++----- src/plugins/nat/nat44-ed/nat44_ed_inlines.h | 152 ++--- src/plugins/nat/nat44-ed/nat44_ed_out2in.c | 353 +++++------- src/plugins/nat/nat44-ei/nat44_ei.c | 6 +- src/plugins/nat/nat44-ei/nat44_ei.h | 1 + src/plugins/nat/nat44-ei/nat44_ei_in2out.c | 16 +- src/plugins/nat/nat44-ei/nat44_ei_inlines.h | 24 + src/plugins/nat/nat44-ei/nat44_ei_out2in.c | 21 +- src/plugins/nat/nat64/nat64_db.h | 1 + test/framework.py | 2 + test/test_nat44_ed.py | 18 +- test/test_nat44_ed_output.py | 229 ++++++++ test/test_nat44_ei.py | 2 +- 31 files changed, 1298 insertions(+), 1468 deletions(-) create mode 100644 src/plugins/nat/lib/nat_proto.h create mode 100644 src/plugins/nat/lib/nat_syslog_constants.h create mode 100644 test/test_nat44_ed_output.py diff --git a/src/plugins/nat/det44/det44.h b/src/plugins/nat/det44/det44.h index 02b0fa7e81d..20dc8b1aec9 100644 --- a/src/plugins/nat/det44/det44.h +++ b/src/plugins/nat/det44/det44.h @@ -40,6 +40,7 @@ #include #include #include +#include /* Session state */ #define foreach_det44_session_state \ diff --git a/src/plugins/nat/lib/alloc.h b/src/plugins/nat/lib/alloc.h index a9a2c15fedc..0c302bf4cfb 100644 --- a/src/plugins/nat/lib/alloc.h +++ b/src/plugins/nat/lib/alloc.h @@ -21,6 +21,7 @@ #define included_nat_lib_alloc_h__ #include +#include typedef struct nat_ip4_pool_addr_s nat_ip4_pool_addr_t; typedef struct nat_ip4_addr_port_s nat_ip4_addr_port_t; diff --git a/src/plugins/nat/lib/inlines.h b/src/plugins/nat/lib/inlines.h index fe1f7dd27bc..46be64d36cf 100644 --- a/src/plugins/nat/lib/inlines.h +++ b/src/plugins/nat/lib/inlines.h @@ -20,37 +20,6 @@ #include -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) { diff --git a/src/plugins/nat/lib/ipfix_logging.c b/src/plugins/nat/lib/ipfix_logging.c index 6e5e4b6c750..27a0b92ae71 100644 --- a/src/plugins/nat/lib/ipfix_logging.c +++ b/src/plugins/nat/lib/ipfix_logging.c @@ -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); } /** diff --git a/src/plugins/nat/lib/ipfix_logging.h b/src/plugins/nat/lib/ipfix_logging.h index 0b2357a2604..0b8f568e1b1 100644 --- a/src/plugins/nat/lib/ipfix_logging.h +++ b/src/plugins/nat/lib/ipfix_logging.h @@ -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); diff --git a/src/plugins/nat/lib/lib.c b/src/plugins/nat/lib/lib.c index d2def2cc480..30bafac73c0 100644 --- a/src/plugins/nat/lib/lib.c +++ b/src/plugins/nat/lib/lib.c @@ -14,6 +14,7 @@ */ #include +#include uword unformat_nat_protocol (unformat_input_t *input, va_list *args) diff --git a/src/plugins/nat/lib/lib.h b/src/plugins/nat/lib/lib.h index b0b5229b337..cea9ed71c8c 100644 --- a/src/plugins/nat/lib/lib.h +++ b/src/plugins/nat/lib/lib.h @@ -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 diff --git a/src/plugins/nat/lib/nat_proto.h b/src/plugins/nat/lib/nat_proto.h new file mode 100644 index 00000000000..9b20d9a71d1 --- /dev/null +++ b/src/plugins/nat/lib/nat_proto.h @@ -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 + +#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: + */ diff --git a/src/plugins/nat/lib/nat_syslog.c b/src/plugins/nat/lib/nat_syslog.c index 2c395bf7fd8..98777ebf280 100644 --- a/src/plugins/nat/lib/nat_syslog.c +++ b/src/plugins/nat/lib/nat_syslog.c @@ -23,38 +23,7 @@ #include #include -#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 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, diff --git a/src/plugins/nat/lib/nat_syslog.h b/src/plugins/nat/lib/nat_syslog.h index 9721664cf54..f929bf310b4 100644 --- a/src/plugins/nat/lib/nat_syslog.h +++ b/src/plugins/nat/lib/nat_syslog.h @@ -20,6 +20,7 @@ #define __included_nat_syslog_h__ #include +#include 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, diff --git a/src/plugins/nat/lib/nat_syslog_constants.h b/src/plugins/nat/lib/nat_syslog_constants.h new file mode 100644 index 00000000000..eeea7d2654e --- /dev/null +++ b/src/plugins/nat/lib/nat_syslog_constants.h @@ -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: + */ diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c index a11043682b9..d639392019b 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.c +++ b/src/plugins/nat/nat44-ed/nat44_ed.c @@ -28,9 +28,11 @@ #include #include -#include #include #include +#include +#include +#include #include #include @@ -182,29 +184,6 @@ static void nat44_ed_db_free (); u32 nat_calc_bihash_buckets (u32 n_elts); -u8 * -format_session_kvp (u8 * s, va_list * args) -{ - clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *); - - s = format (s, "%U thread-index %llu session-index %llu", format_snat_key, - v->key, nat_value_get_thread_index (v), - nat_value_get_session_index (v)); - - return s; -} - -u8 * -format_static_mapping_kvp (u8 * s, va_list * args) -{ - clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *); - - s = format (s, "%U static-mapping-index %llu", - format_snat_key, v->key, v->value); - - return s; -} - u8 * format_ed_session_kvp (u8 * s, va_list * args) { @@ -227,59 +206,81 @@ format_ed_session_kvp (u8 * s, va_list * args) return s; } -void -nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index, - u8 is_ha) +static_always_inline int +nat44_ed_sm_i2o_add (snat_main_t *sm, snat_static_mapping_t *m, + ip4_address_t addr, u16 port, u32 fib_index, u8 proto) { - per_vrf_sessions_unregister_session (s, thread_index); + ASSERT (!pool_is_free (sm->static_mappings, m)); + clib_bihash_kv_16_8_t kv; + nat44_ed_sm_init_i2o_kv (&kv, addr.as_u32, port, fib_index, proto, + m - sm->static_mappings); + return clib_bihash_add_del_16_8 (&sm->flow_hash, &kv, 1 /*is_add*/); +} - if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 0)) - nat_elog_warn (sm, "flow hash del failed"); +static_always_inline int +nat44_ed_sm_i2o_del (snat_main_t *sm, ip4_address_t addr, u16 port, + u32 fib_index, u8 proto) +{ + clib_bihash_kv_16_8_t kv; + nat44_ed_sm_init_i2o_k (&kv, addr.as_u32, port, fib_index, proto); + return clib_bihash_add_del_16_8 (&sm->flow_hash, &kv, 0 /*is_add*/); +} - if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 0)) - nat_elog_warn (sm, "flow hash del failed"); +static_always_inline int +nat44_ed_sm_o2i_add (snat_main_t *sm, snat_static_mapping_t *m, + ip4_address_t addr, u16 port, u32 fib_index, u8 proto) +{ + ASSERT (!pool_is_free (sm->static_mappings, m)); + clib_bihash_kv_16_8_t kv; + nat44_ed_sm_init_o2i_kv (&kv, addr.as_u32, port, fib_index, proto, + m - sm->static_mappings); + return clib_bihash_add_del_16_8 (&sm->flow_hash, &kv, 1 /*is_add*/); +} - if (na44_ed_is_fwd_bypass_session (s)) - { - return; - } +static_always_inline int +nat44_ed_sm_o2i_del (snat_main_t *sm, ip4_address_t addr, u16 port, + u32 fib_index, u8 proto) +{ + clib_bihash_kv_16_8_t kv; + nat44_ed_sm_init_o2i_k (&kv, addr.as_u32, port, fib_index, proto); + return clib_bihash_add_del_16_8 (&sm->flow_hash, &kv, 0 /*is_add*/); +} - if (nat44_ed_is_affinity_session (s)) - nat_affinity_unlock (s->ext_host_addr, s->out2in.addr, s->nat_proto, - s->out2in.port); +void +nat44_ed_free_session_data (snat_main_t *sm, snat_session_t *s, + u32 thread_index, u8 is_ha) +{ + per_vrf_sessions_unregister_session (s, thread_index); - if (!is_ha) - nat_syslog_nat44_sdel ( - 0, s->in2out.fib_index, &s->in2out.addr, s->in2out.port, - &s->ext_host_nat_addr, s->ext_host_nat_port, &s->out2in.addr, - s->out2in.port, &s->ext_host_addr, s->ext_host_port, s->nat_proto, - nat44_ed_is_twice_nat_session (s)); + if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 0)) + nat_elog_warn (sm, "flow hash del failed"); - if (snat_is_unk_proto_session (s)) - return; + if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 0)) + nat_elog_warn (sm, "flow hash del failed"); - if (!is_ha) - { - /* 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); - } + if (na44_ed_is_fwd_bypass_session (s)) + { + return; + } - /* Twice NAT address and port for external host */ - if (nat44_ed_is_twice_nat_session (s)) - { - snat_free_outside_address_and_port ( - sm->twice_nat_addresses, thread_index, &s->ext_host_nat_addr, - s->ext_host_nat_port, s->nat_proto); - } + if (nat44_ed_is_affinity_session (s)) + nat_affinity_unlock (s->ext_host_addr, s->out2in.addr, s->proto, + s->out2in.port); - if (nat44_ed_is_session_static (s)) - return; + if (!is_ha) + nat_syslog_nat44_sdel (0, s->in2out.fib_index, &s->in2out.addr, + s->in2out.port, &s->ext_host_nat_addr, + s->ext_host_nat_port, &s->out2in.addr, + s->out2in.port, &s->ext_host_addr, s->ext_host_port, + s->proto, nat44_ed_is_twice_nat_session (s)); - snat_free_outside_address_and_port (sm->addresses, thread_index, - &s->out2in.addr, s->out2in.port, - s->nat_proto); + if (!is_ha) + { + /* log NAT event */ + nat_ipfix_logging_nat44_ses_delete ( + thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32, s->proto, + s->in2out.port, s->out2in.port, s->in2out.fib_index); + } } static int @@ -388,7 +389,6 @@ int nat44_ed_add_address (ip4_address_t *addr, u32 vrf_id, u8 twice_nat) { snat_main_t *sm = &snat_main; - vlib_thread_main_t *tm = vlib_get_thread_main (); snat_address_t *ap, *addresses; addresses = twice_nat ? sm->twice_nat_addresses : sm->addresses; @@ -426,16 +426,6 @@ nat44_ed_add_address (ip4_address_t *addr, u32 vrf_id, u8 twice_nat) FIB_PROTOCOL_IP4, vrf_id, sm->fib_src_low); } -#define _(N, i, n, s) \ - clib_memset (ap->busy_##n##_port_refcounts, 0, \ - sizeof (ap->busy_##n##_port_refcounts)); \ - ap->busy_##n##_ports = 0; \ - ap->busy_##n##_ports_per_thread = 0; \ - vec_validate_init_empty (ap->busy_##n##_ports_per_thread, \ - tm->n_vlib_mains - 1, 0); - foreach_nat_protocol -#undef _ - if (!twice_nat) { // if we don't have enabled interface we don't add address @@ -480,7 +470,8 @@ nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat) { nat44_ed_del_static_mapping (m->local_addr, m->external_addr, m->local_port, m->external_port, - m->proto, m->vrf_id, ~0, m->flags); + ip_proto_to_nat_proto (m->proto), + m->vrf_id, ~0, m->flags); } } } @@ -501,32 +492,25 @@ nat44_ed_del_address (ip4_address_t addr, u8 delete_sm, u8 twice_nat) } // delete sessions using address - if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports) + vec_foreach (tsm, sm->per_thread_data) { - vec_foreach (tsm, sm->per_thread_data) + pool_foreach (ses, tsm->sessions) { - pool_foreach (ses, tsm->sessions) - { - if (ses->out2in.addr.as_u32 == addr.as_u32) - { - nat_free_session_data (sm, ses, tsm - sm->per_thread_data, - 0); - vec_add1 (ses_to_be_removed, ses - tsm->sessions); - } - } - vec_foreach (ses_index, ses_to_be_removed) + if (ses->out2in.addr.as_u32 == addr.as_u32) { - ses = pool_elt_at_index (tsm->sessions, ses_index[0]); - nat_ed_session_delete (sm, ses, tsm - sm->per_thread_data, 1); + nat44_ed_free_session_data (sm, ses, tsm - sm->per_thread_data, + 0); + vec_add1 (ses_to_be_removed, ses - tsm->sessions); } - vec_free (ses_to_be_removed); } + vec_foreach (ses_index, ses_to_be_removed) + { + ses = pool_elt_at_index (tsm->sessions, ses_index[0]); + nat_ed_session_delete (sm, ses, tsm - sm->per_thread_data, 1); + } + vec_free (ses_to_be_removed); } -#define _(N, i, n, s) vec_free (a->busy_##n##_ports_per_thread); - foreach_nat_protocol -#undef _ - if (!twice_nat) { vec_del1 (sm->addresses, j); @@ -569,18 +553,17 @@ nat_ed_static_mapping_del_sessions (snat_main_t * sm, } if (!addr_only) { - if ((s->out2in.addr.as_u32 != e_addr.as_u32) || - s->out2in.port != e_port || - s->in2out.port != l_port || - s->nat_proto != protocol) - continue; + if ((s->out2in.addr.as_u32 != e_addr.as_u32) || + s->out2in.port != e_port || s->in2out.port != l_port || + s->proto != protocol) + continue; } if (nat44_ed_is_lb_session (s)) continue; if (!nat44_ed_is_session_static (s)) continue; - nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + nat44_ed_free_session_data (sm, s, tsm - sm->per_thread_data, 0); vec_add1 (indexes_to_free, s - tsm->sessions); if (!addr_only) break; @@ -594,89 +577,41 @@ nat_ed_static_mapping_del_sessions (snat_main_t * sm, vec_free (indexes_to_free); } -int -nat44_ed_reserve_port (ip4_address_t addr, u16 port, nat_protocol_t proto) +static_always_inline snat_static_mapping_t * +nat44_ed_sm_lookup (snat_main_t *sm, clib_bihash_kv_16_8_t *kv) { - u32 ti = get_thread_idx_by_port (port); - snat_main_t *sm = &snat_main; - snat_address_t *a = 0; - int i; - - for (i = 0; i < vec_len (sm->addresses); i++) + clib_bihash_kv_16_8_t v; + int rc = clib_bihash_search_16_8 (&sm->flow_hash, kv, &v); + if (!rc) { - a = sm->addresses + i; - - if (a->addr.as_u32 != addr.as_u32) - continue; - - switch (proto) - { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - if (a->busy_##n##_port_refcounts[port]) \ - goto done; \ - ++a->busy_##n##_port_refcounts[port]; \ - if (port > 1024) \ - { \ - a->busy_##n##_ports++; \ - a->busy_##n##_ports_per_thread[ti]++; \ - } \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (sm, "unknown protocol"); - goto done; - } - - return 0; + ASSERT (0 == ed_value_get_thread_index (&v)); + return pool_elt_at_index (sm->static_mappings, + ed_value_get_session_index (&v)); } - -done: - return 1; + return NULL; } -int -nat44_ed_free_port (ip4_address_t addr, u16 port, nat_protocol_t 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) { - u32 ti = get_thread_idx_by_port (port); - snat_main_t *sm = &snat_main; - snat_address_t *a = 0; - int i; - - for (i = 0; i < vec_len (sm->addresses); i++) - { - a = sm->addresses + i; - - if (a->addr.as_u32 != addr.as_u32) - continue; - - switch (proto) - { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - --a->busy_##n##_port_refcounts[port]; \ - if (port > 1024) \ - { \ - a->busy_##n##_ports--; \ - a->busy_##n##_ports_per_thread[ti]--; \ - } \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (sm, "unknown protocol"); - goto done; - } - - return 0; - } + clib_bihash_kv_16_8_t kv; + nat44_ed_sm_init_o2i_k (&kv, addr.as_u32, port, fib_index, proto); + return nat44_ed_sm_lookup (sm, &kv); +} -done: - return 1; +snat_static_mapping_t * +nat44_ed_sm_i2o_lookup (snat_main_t *sm, ip4_address_t addr, u16 port, + u32 fib_index, u8 proto) +{ + clib_bihash_kv_16_8_t kv; + nat44_ed_sm_init_i2o_k (&kv, addr.as_u32, port, fib_index, proto); + return nat44_ed_sm_lookup (sm, &kv); } void nat44_ed_add_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, - nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, + ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags, ip4_address_t pool_addr, u8 *tag) { snat_static_map_resolve_t *rp; @@ -696,7 +631,7 @@ nat44_ed_add_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, int nat44_ed_get_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, - nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, + ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags, int *out) { snat_static_map_resolve_t *rp; @@ -746,7 +681,7 @@ nat44_ed_get_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, int nat44_ed_del_resolve_record (ip4_address_t l_addr, u16 l_port, u16 e_port, - nat_protocol_t proto, u32 vrf_id, u32 sw_if_index, + ip_protocol_t proto, u32 vrf_id, u32 sw_if_index, u32 flags) { snat_main_t *sm = &snat_main; @@ -779,14 +714,24 @@ nat44_ed_validate_sm_input (u32 flags) return 0; } +snat_address_t * +nat44_ed_addr_lookup (snat_main_t *sm, u32 addr) +{ + for (int i = 0; i < vec_len (sm->addresses); ++i) + { + if (sm->addresses[i].addr.as_u32 == addr) + return &sm->addresses[i]; + } + return NULL; +} + 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) { snat_main_t *sm = &snat_main; - clib_bihash_kv_8_8_t kv, value; nat44_lb_addr_port_t *local; snat_static_mapping_t *m; u32 fib_index = ~0; @@ -840,12 +785,9 @@ nat44_ed_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, l_addr.as_u32 = e_addr.as_u32; } - // fib index 0 - init_nat_k (&kv, e_addr, e_port, 0, proto); - - if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value)) + m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto); + if (m) { - m = pool_elt_at_index (sm->static_mappings, value.value); if (!is_sm_identity_nat (m->flags)) { return VNET_API_ERROR_VALUE_EXIST; @@ -867,9 +809,8 @@ nat44_ed_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, local->fib_index = fib_table_find_or_create_and_lock ( FIB_PROTOCOL_IP4, vrf_id, sm->fib_src_low); - init_nat_kv (&kv, m->local_addr, m->local_port, local->fib_index, - m->proto, 0, m - sm->static_mappings); - clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1); + nat44_ed_sm_i2o_add (sm, m, m->local_addr, m->local_port, + local->fib_index, m->proto); return 0; } @@ -891,8 +832,7 @@ nat44_ed_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, // identity nat supports multiple records in local mapping if (!(is_sm_out2in_only (flags) || is_sm_identity_nat (flags))) { - init_nat_k (&kv, l_addr, l_port, fib_index, proto); - if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value)) + if (nat44_ed_sm_i2o_lookup (sm, l_addr, l_port, fib_index, proto)) { return VNET_API_ERROR_VALUE_EXIST; } @@ -901,7 +841,7 @@ nat44_ed_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, if (!(is_sm_out2in_only (flags) || is_sm_addr_only (flags) || sm->static_mapping_only)) { - if (nat44_ed_reserve_port (e_addr, e_port, proto)) + if (!nat44_ed_addr_lookup (sm, e_addr.as_u32)) { // remove resolve record if (is_sm_switch_address (flags) && !is_sm_identity_nat (flags)) @@ -955,14 +895,11 @@ nat44_ed_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, if (!is_sm_out2in_only (flags)) { - init_nat_kv (&kv, m->local_addr, m->local_port, fib_index, m->proto, 0, - m - sm->static_mappings); - clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1); + nat44_ed_sm_i2o_add (sm, m, m->local_addr, m->local_port, fib_index, + m->proto); } - init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto, 0, - m - sm->static_mappings); - clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1); + nat44_ed_sm_o2i_add (sm, m, m->external_addr, m->external_port, 0, m->proto); if (sm->num_workers > 1) { @@ -981,13 +918,12 @@ nat44_ed_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, 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) { snat_main_per_thread_data_t *tsm; snat_main_t *sm = &snat_main; - clib_bihash_kv_8_8_t kv, value; nat44_lb_addr_port_t *local; snat_static_mapping_t *m; u32 fib_index = ~0; @@ -1039,9 +975,9 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, } // fib index 0 - init_nat_k (&kv, e_addr, e_port, 0, proto); + m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto); - if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value)) + if (!m) { if (is_sm_switch_address (flags)) { @@ -1050,8 +986,6 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, return VNET_API_ERROR_NO_SUCH_ENTRY; } - m = pool_elt_at_index (sm->static_mappings, value.value); - if (is_sm_identity_nat (flags)) { u8 failure = 1; @@ -1085,7 +1019,7 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, if (!(is_sm_out2in_only (flags) || is_sm_addr_only (flags) || sm->static_mapping_only)) { - if (nat44_ed_free_port (e_addr, e_port, proto)) + if (!nat44_ed_addr_lookup (sm, e_addr.as_u32)) { return VNET_API_ERROR_INVALID_VALUE; } @@ -1093,8 +1027,7 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, if (!is_sm_out2in_only (flags)) { - init_nat_k (&kv, l_addr, l_port, fib_index, proto); - clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0); + nat44_ed_sm_i2o_del (sm, l_addr, l_port, fib_index, proto); } if (!sm->static_mapping_only || sm->static_mapping_connection_tracking) @@ -1116,8 +1049,7 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, { // this is last record remove all required stuff // fib_index 0 - init_nat_k (&kv, e_addr, e_port, 0, proto); - clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0); + nat44_ed_sm_o2i_del (sm, e_addr, e_port, 0, proto); vec_free (m->tag); vec_free (m->workers); @@ -1134,17 +1066,17 @@ nat44_ed_del_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, 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) { snat_main_t *sm = &snat_main; snat_static_mapping_t *m; - clib_bihash_kv_8_8_t kv, value; snat_address_t *a = 0; nat44_lb_addr_port_t *local; uword *bitmap = 0; + int rc = 0; int i; @@ -1153,15 +1085,7 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, return VNET_API_ERROR_UNSUPPORTED; } - init_nat_k (&kv, e_addr, e_port, 0, proto); - if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value)) - { - m = 0; - } - else - { - m = pool_elt_at_index (sm->static_mappings, value.value); - } + m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto); if (m) { @@ -1181,25 +1105,11 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, { if (sm->addresses[i].addr.as_u32 == e_addr.as_u32) { - a = sm->addresses + i; /* External port must be unused */ - switch (proto) + a = sm->addresses + i; + if (nat44_ed_sm_o2i_lookup (sm, a->addr, e_port, 0, proto)) { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - if (a->busy_##n##_port_refcounts[e_port]) \ - return VNET_API_ERROR_INVALID_VALUE; \ - ++a->busy_##n##_port_refcounts[e_port]; \ - if (e_port > 1024) \ - { \ - a->busy_##n##_ports++; \ - a->busy_##n##_ports_per_thread[get_thread_idx_by_port (e_port)]++; \ - } \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (sm, "unknown protocol"); - return VNET_API_ERROR_INVALID_VALUE_2; + return VNET_API_ERROR_VALUE_EXIST; } break; } @@ -1228,11 +1138,10 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, else m->affinity_per_service_list_head_index = ~0; - init_nat_kv (&kv, m->external_addr, m->external_port, 0, m->proto, 0, - m - sm->static_mappings); - if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 1)) + if (nat44_ed_sm_o2i_add (sm, m, m->external_addr, m->external_port, 0, + m->proto)) { - nat_elog_err (sm, "static_mapping_by_external key add failed"); + nat_elog_err (sm, "sm o2i key add failed"); return VNET_API_ERROR_UNSPECIFIED; } @@ -1242,10 +1151,16 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, FIB_PROTOCOL_IP4, locals[i].vrf_id, sm->fib_src_low); if (!is_sm_out2in_only (flags)) { - init_nat_kv (&kv, locals[i].addr, locals[i].port, - locals[i].fib_index, m->proto, 0, - m - sm->static_mappings); - clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1); + if (nat44_ed_sm_o2i_add (sm, m, e_addr, e_port, 0, proto)) + { + nat_elog_err (sm, "sm o2i key add failed"); + rc = VNET_API_ERROR_UNSPECIFIED; + // here we continue with add operation so that it can be safely + // reversed in delete path - otherwise we'd have to track what + // we've done and deal with partial cleanups and since bihash + // adds are (extremely improbable) the only points of failure, + // it's easier to just do it this way + } } locals[i].prefix = (i == 0) ? locals[i].probability : @@ -1272,72 +1187,36 @@ nat44_ed_add_lb_static_mapping (ip4_address_t e_addr, u16 e_port, } } - return 0; + return rc; } 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) { snat_main_t *sm = &snat_main; snat_static_mapping_t *m; - clib_bihash_kv_8_8_t kv, value; - snat_address_t *a = 0; nat44_lb_addr_port_t *local; snat_main_per_thread_data_t *tsm; snat_session_t *s; - int i; if (!sm->enabled) { return VNET_API_ERROR_UNSUPPORTED; } - init_nat_k (&kv, e_addr, e_port, 0, proto); - if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value)) - m = 0; - else - m = pool_elt_at_index (sm->static_mappings, value.value); - + m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto); if (!m) return VNET_API_ERROR_NO_SUCH_ENTRY; if (!is_sm_lb (m->flags)) return VNET_API_ERROR_INVALID_VALUE; - if (!(sm->static_mapping_only || is_sm_out2in_only (flags))) + if (nat44_ed_sm_o2i_del (sm, m->external_addr, m->external_port, 0, + m->proto)) { - for (i = 0; i < vec_len (sm->addresses); i++) - { - if (sm->addresses[i].addr.as_u32 == e_addr.as_u32) - { - a = sm->addresses + i; - switch (proto) - { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - --a->busy_##n##_port_refcounts[e_port]; \ - if (e_port > 1024) \ - { \ - a->busy_##n##_ports--; \ - a->busy_##n##_ports_per_thread[get_thread_idx_by_port (e_port)]--; \ - } \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (sm, "unknown protocol"); - return VNET_API_ERROR_INVALID_VALUE_2; - } - break; - } - } - } - - init_nat_k (&kv, m->external_addr, m->external_port, 0, m->proto); - if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_external, &kv, 0)) - { - nat_elog_err (sm, "static_mapping_by_external key del failed"); + nat_elog_err (sm, "sm o2i key del failed"); return VNET_API_ERROR_UNSPECIFIED; } @@ -1346,11 +1225,10 @@ nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, fib_table_unlock (local->fib_index, FIB_PROTOCOL_IP4, sm->fib_src_low); if (!is_sm_out2in_only (flags)) { - init_nat_k (&kv, local->addr, local->port, local->fib_index, - m->proto); - if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0)) + if (nat44_ed_sm_i2o_del (sm, local->addr, local->port, + local->fib_index, m->proto)) { - nat_elog_err (sm, "static_mapping_by_local key del failed"); + nat_elog_err (sm, "sm i2o key del failed"); return VNET_API_ERROR_UNSPECIFIED; } } @@ -1377,7 +1255,7 @@ nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, s->in2out.port != local->port) continue; - nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + nat44_ed_free_session_data (sm, s, tsm - sm->per_thread_data, 0); nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1); } } @@ -1398,12 +1276,11 @@ nat44_ed_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, 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) { snat_main_t *sm = &snat_main; snat_static_mapping_t *m = 0; - clib_bihash_kv_8_8_t kv, value; nat44_lb_addr_port_t *local, *prev_local, *match_local = 0; snat_main_per_thread_data_t *tsm; snat_session_t *s; @@ -1416,9 +1293,7 @@ nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port, return VNET_API_ERROR_UNSUPPORTED; } - init_nat_k (&kv, e_addr, e_port, 0, proto); - if (!clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value)) - m = pool_elt_at_index (sm->static_mappings, value.value); + m = nat44_ed_sm_o2i_lookup (sm, e_addr, e_port, 0, proto); if (!m) { @@ -1459,10 +1334,13 @@ nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port, if (!is_sm_out2in_only (m->flags)) { - init_nat_kv (&kv, l_addr, l_port, local->fib_index, proto, 0, - m - sm->static_mappings); - if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 1)) - nat_elog_err (sm, "static_mapping_by_local key add failed"); + if (nat44_ed_sm_i2o_add (sm, m, l_addr, l_port, local->fib_index, + proto)) + { + nat_elog_err (sm, "sm i2o key add failed"); + pool_put (m->locals, local); + return VNET_API_ERROR_UNSPECIFIED; + } } } else @@ -1478,9 +1356,9 @@ nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port, if (!is_sm_out2in_only (m->flags)) { - init_nat_k (&kv, l_addr, l_port, match_local->fib_index, proto); - if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, 0)) - nat_elog_err (sm, "static_mapping_by_local key del failed"); + if (nat44_ed_sm_i2o_del (sm, l_addr, l_port, match_local->fib_index, + proto)) + nat_elog_err (sm, "sm i2o key del failed"); } if (sm->num_workers > 1) @@ -1504,7 +1382,7 @@ nat44_ed_add_del_lb_static_mapping_local (ip4_address_t e_addr, u16 e_port, s->in2out.port != match_local->port) continue; - nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + nat44_ed_free_session_data (sm, s, tsm - sm->per_thread_data, 0); nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1); } @@ -2163,8 +2041,8 @@ test_key_calc_split () u32 thread_index = 3000000001; u32 session_index = 3000000221; clib_bihash_kv_16_8_t kv; - init_ed_kv (&kv, l_addr, l_port, r_addr, r_port, fib_index, proto, - thread_index, session_index); + init_ed_kv (&kv, l_addr.as_u32, l_port, r_addr.as_u32, r_port, fib_index, + proto, thread_index, session_index); ip4_address_t l_addr2; ip4_address_t r_addr2; clib_memset (&l_addr2, 0, sizeof (l_addr2)); @@ -2183,16 +2061,6 @@ test_key_calc_split () ASSERT (fib_index == fib_index2); ASSERT (thread_index == ed_value_get_thread_index (&kv)); ASSERT (session_index == ed_value_get_session_index (&kv)); - - fib_index = 7001; - proto = 5; - nat_protocol_t proto3 = ~0; - u64 key = calc_nat_key (l_addr, l_port, fib_index, proto); - split_nat_key (key, &l_addr2, &l_port2, &fib_index2, &proto3); - ASSERT (l_addr.as_u32 == l_addr2.as_u32); - ASSERT (l_port == l_port2); - ASSERT (proto == proto3); - ASSERT (fib_index == fib_index2); } static clib_error_t * @@ -2441,14 +2309,6 @@ nat44_plugin_enable (nat44_config_t c) void nat44_addresses_free (snat_address_t ** addresses) { - snat_address_t *ap; - vec_foreach (ap, *addresses) - { - #define _(N, i, n, s) \ - vec_free (ap->busy_##n##_ports_per_thread); - foreach_nat_protocol - #undef _ - } vec_free (*addresses); *addresses = 0; } @@ -2548,7 +2408,7 @@ nat44_ed_forwarding_enable_disable (u8 is_enable) vec_foreach (ses_index, ses_to_be_removed) { s = pool_elt_at_index (tsm->sessions, ses_index[0]); - nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + nat44_ed_free_session_data (sm, s, tsm - sm->per_thread_data, 0); nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1); } @@ -2556,88 +2416,88 @@ nat44_ed_forwarding_enable_disable (u8 is_enable) } } -void -snat_free_outside_address_and_port (snat_address_t *addresses, - u32 thread_index, ip4_address_t *addr, - u16 port, nat_protocol_t protocol) +static_always_inline snat_static_mapping_t * +nat44_ed_sm_match (snat_main_t *sm, ip4_address_t match_addr, u16 match_port, + u32 match_fib_index, ip_protocol_t match_protocol, + int by_external) { - snat_main_t *sm = &snat_main; - snat_address_t *a; - u32 address_index; - u16 port_host_byte_order = clib_net_to_host_u16 (port); - - for (address_index = 0; address_index < vec_len (addresses); - address_index++) + snat_static_mapping_t *m; + if (!by_external) { - if (addresses[address_index].addr.as_u32 == addr->as_u32) - break; - } + m = nat44_ed_sm_i2o_lookup (sm, match_addr, match_port, match_fib_index, + match_protocol); + if (m) + return m; - ASSERT (address_index < vec_len (addresses)); + /* Try address only mapping */ + m = nat44_ed_sm_i2o_lookup (sm, match_addr, 0, match_fib_index, 0); + if (m) + return m; + + if (sm->inside_fib_index != match_fib_index) + { + m = nat44_ed_sm_i2o_lookup (sm, match_addr, match_port, + sm->inside_fib_index, match_protocol); + if (m) + return m; - a = addresses + address_index; + /* Try address only mapping */ + m = nat44_ed_sm_i2o_lookup (sm, match_addr, 0, sm->inside_fib_index, + 0); + if (m) + return m; + } + if (sm->outside_fib_index != match_fib_index) + { + m = nat44_ed_sm_i2o_lookup (sm, match_addr, match_port, + sm->outside_fib_index, match_protocol); + if (m) + return m; - switch (protocol) + /* Try address only mapping */ + m = nat44_ed_sm_i2o_lookup (sm, match_addr, 0, sm->outside_fib_index, + 0); + if (m) + return m; + } + } + else { -#define _(N, i, n, s) \ - case NAT_PROTOCOL_##N: \ - ASSERT (a->busy_##n##_port_refcounts[port_host_byte_order] >= 1); \ - --a->busy_##n##_port_refcounts[port_host_byte_order]; \ - a->busy_##n##_ports--; \ - a->busy_##n##_ports_per_thread[thread_index]--; \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (sm, "unknown protocol"); - return; + m = + nat44_ed_sm_o2i_lookup (sm, match_addr, match_port, 0, match_protocol); + if (m) + return m; + + /* Try address only mapping */ + m = nat44_ed_sm_o2i_lookup (sm, match_addr, 0, 0, 0); + if (m) + return m; } + return 0; } 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, + u32 *mapping_fib_index, 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) { - clib_bihash_kv_8_8_t kv, value; - clib_bihash_8_8_t *mapping_hash; snat_static_mapping_t *m; u32 rand, lo = 0, hi, mid, *tmp = 0, i; nat44_lb_addr_port_t *local; u8 backend_index; - if (!by_external) - { - mapping_hash = &sm->static_mapping_by_local; - init_nat_k (&kv, match_addr, match_port, match_fib_index, - match_protocol); - if (clib_bihash_search_8_8 (mapping_hash, &kv, &value)) - { - /* Try address only mapping */ - init_nat_k (&kv, match_addr, 0, match_fib_index, 0); - if (clib_bihash_search_8_8 (mapping_hash, &kv, &value)) - return 1; - } - } - else + m = nat44_ed_sm_match (sm, match_addr, match_port, match_fib_index, + match_protocol, by_external); + if (!m) { - mapping_hash = &sm->static_mapping_by_external; - init_nat_k (&kv, match_addr, match_port, 0, match_protocol); - if (clib_bihash_search_8_8 (mapping_hash, &kv, &value)) - { - /* Try address only mapping */ - init_nat_k (&kv, match_addr, 0, 0, 0); - if (clib_bihash_search_8_8 (mapping_hash, &kv, &value)) - return 1; - } + return 1; } - m = pool_elt_at_index (sm->static_mappings, value.value); - if (by_external) { if (is_sm_lb (m->flags)) @@ -2814,8 +2674,9 @@ nat44_ed_get_in2out_worker_index (vlib_buffer_t *b, ip4_header_t *ip, b, ip, &lookup_saddr, &lookup_sport, &lookup_daddr, &lookup_dport, &lookup_protocol)) { - init_ed_k (&kv16, lookup_saddr, lookup_sport, lookup_daddr, - lookup_dport, rx_fib_index, lookup_protocol); + init_ed_k (&kv16, lookup_saddr.as_u32, lookup_sport, + lookup_daddr.as_u32, lookup_dport, rx_fib_index, + lookup_protocol); if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16)) { next_worker_index = ed_value_get_thread_index (&value16); @@ -2826,9 +2687,10 @@ nat44_ed_get_in2out_worker_index (vlib_buffer_t *b, ip4_header_t *ip, } } - init_ed_k (&kv16, ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port, - ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, - fib_index, ip->protocol); + init_ed_k (&kv16, ip->src_address.as_u32, + vnet_buffer (b)->ip.reass.l4_src_port, ip->dst_address.as_u32, + vnet_buffer (b)->ip.reass.l4_dst_port, fib_index, + ip->protocol); if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16)) { @@ -2839,9 +2701,10 @@ nat44_ed_get_in2out_worker_index (vlib_buffer_t *b, ip4_header_t *ip, } // dst NAT - init_ed_k (&kv16, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, - ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port, - rx_fib_index, ip->protocol); + init_ed_k (&kv16, ip->dst_address.as_u32, + vnet_buffer (b)->ip.reass.l4_dst_port, ip->src_address.as_u32, + vnet_buffer (b)->ip.reass.l4_src_port, rx_fib_index, + ip->protocol); if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16)) { next_worker_index = ed_value_get_thread_index (&value16); @@ -2883,17 +2746,16 @@ nat44_ed_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index, u8 is_output) { snat_main_t *sm = &snat_main; - clib_bihash_kv_8_8_t kv, value; clib_bihash_kv_16_8_t kv16, value16; - u32 proto, next_worker_index = 0; + u8 proto, next_worker_index = 0; u16 port; snat_static_mapping_t *m; u32 hash; - proto = ip_proto_to_nat_proto (ip->protocol); + proto = ip->protocol; - if (PREDICT_FALSE (proto == NAT_PROTOCOL_ICMP)) + if (PREDICT_FALSE (IP_PROTOCOL_ICMP == proto)) { ip4_address_t lookup_saddr, lookup_daddr; u16 lookup_sport, lookup_dport; @@ -2902,8 +2764,9 @@ nat44_ed_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip, b, ip, &lookup_saddr, &lookup_sport, &lookup_daddr, &lookup_dport, &lookup_protocol)) { - init_ed_k (&kv16, lookup_saddr, lookup_sport, lookup_daddr, - lookup_dport, rx_fib_index, lookup_protocol); + init_ed_k (&kv16, lookup_saddr.as_u32, lookup_sport, + lookup_daddr.as_u32, lookup_dport, rx_fib_index, + lookup_protocol); if (PREDICT_TRUE ( !clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16))) { @@ -2917,9 +2780,10 @@ nat44_ed_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip, } } - init_ed_k (&kv16, ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port, - ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, - rx_fib_index, ip->protocol); + init_ed_k (&kv16, ip->src_address.as_u32, + vnet_buffer (b)->ip.reass.l4_src_port, ip->dst_address.as_u32, + vnet_buffer (b)->ip.reass.l4_dst_port, rx_fib_index, + ip->protocol); if (PREDICT_TRUE ( !clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16))) @@ -2937,18 +2801,18 @@ nat44_ed_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip, /* first try static mappings without port */ if (PREDICT_FALSE (pool_elts (sm->static_mappings))) { - init_nat_k (&kv, ip->dst_address, 0, 0, 0); - if (!clib_bihash_search_8_8 - (&sm->static_mapping_by_external, &kv, &value)) + m = nat44_ed_sm_o2i_lookup (sm, ip->dst_address, 0, 0, proto); + if (m) { - m = pool_elt_at_index (sm->static_mappings, value.value); - next_worker_index = m->workers[0]; - goto done; + { + next_worker_index = m->workers[0]; + goto done; + } } } /* unknown protocol */ - if (PREDICT_FALSE (proto == NAT_PROTOCOL_OTHER)) + if (PREDICT_FALSE (nat44_ed_is_unk_proto (proto))) { /* use current thread */ next_worker_index = vlib_get_thread_index (); @@ -2969,17 +2833,18 @@ nat44_ed_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip, { /* if error message, then it's not fragmented and we can access it */ ip4_header_t *inner_ip = (ip4_header_t *) (echo + 1); - proto = ip_proto_to_nat_proto (inner_ip->protocol); + proto = inner_ip->protocol; void *l4_header = ip4_next_header (inner_ip); switch (proto) { - case NAT_PROTOCOL_ICMP: + case IP_PROTOCOL_ICMP: icmp = (icmp46_header_t *) l4_header; echo = (icmp_echo_header_t *) (icmp + 1); port = echo->identifier; break; - case NAT_PROTOCOL_UDP: - case NAT_PROTOCOL_TCP: + case IP_PROTOCOL_UDP: + /* breakthrough */ + case IP_PROTOCOL_TCP: port = ((tcp_udp_header_t *) l4_header)->src_port; break; default: @@ -2992,11 +2857,9 @@ nat44_ed_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip, /* try static mappings with port */ if (PREDICT_FALSE (pool_elts (sm->static_mappings))) { - init_nat_k (&kv, ip->dst_address, port, 0, proto); - if (!clib_bihash_search_8_8 - (&sm->static_mapping_by_external, &kv, &value)) + m = nat44_ed_sm_o2i_lookup (sm, ip->dst_address, port, 0, proto); + if (m) { - m = pool_elt_at_index (sm->static_mappings, value.value); if (!is_sm_lb (m->flags)) { next_worker_index = m->workers[0]; @@ -3126,23 +2989,9 @@ nat44_ed_db_init (u32 translations, u32 translation_buckets) { snat_main_t *sm = &snat_main; snat_main_per_thread_data_t *tsm; - u32 static_mapping_buckets = 1024; - u32 static_mapping_memory_size = 64 << 20; reinit_ed_flow_hash (); - clib_bihash_init_8_8 (&sm->static_mapping_by_local, - "static_mapping_by_local", static_mapping_buckets, - static_mapping_memory_size); - clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local, - format_static_mapping_kvp); - - clib_bihash_init_8_8 (&sm->static_mapping_by_external, - "static_mapping_by_external", static_mapping_buckets, - static_mapping_memory_size); - clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external, - format_static_mapping_kvp); - if (sm->pat) { vec_foreach (tsm, sm->per_thread_data) @@ -3169,8 +3018,6 @@ nat44_ed_db_free () pool_free (sm->static_mappings); clib_bihash_free_16_8 (&sm->flow_hash); - clib_bihash_free_8_8 (&sm->static_mapping_by_local); - clib_bihash_free_8_8 (&sm->static_mapping_by_external); if (sm->pat) { @@ -3207,7 +3054,6 @@ nat44_ed_add_del_static_mapping_addr_only_cb ( ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete) { - clib_bihash_kv_8_8_t kv, value; snat_static_map_resolve_t *rp; snat_main_t *sm = &snat_main; snat_static_mapping_t *m; @@ -3233,17 +3079,8 @@ nat44_ed_add_del_static_mapping_addr_only_cb ( return; } - init_nat_k (&kv, *address, rp->addr_only ? 0 : rp->e_port, - sm->outside_fib_index, rp->addr_only ? 0 : rp->proto); - - if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value)) - { - m = 0; - } - else - { - m = pool_elt_at_index (sm->static_mappings, value.value); - } + m = nat44_ed_sm_o2i_lookup (sm, *address, rp->addr_only ? 0 : rp->e_port, 0, + rp->proto); if (is_delete) { @@ -3486,7 +3323,8 @@ nat44_ed_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port, else tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); - init_ed_k (&kv, *addr, port, *eh_addr, eh_port, fib_index, proto); + init_ed_k (&kv, addr->as_u32, port, eh_addr->as_u32, eh_port, fib_index, + proto); if (clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value)) { return VNET_API_ERROR_NO_SUCH_ENTRY; @@ -3495,7 +3333,7 @@ nat44_ed_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port, if (pool_is_free_index (tsm->sessions, ed_value_get_session_index (&value))) return VNET_API_ERROR_UNSPECIFIED; s = pool_elt_at_index (tsm->sessions, ed_value_get_session_index (&value)); - nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + nat44_ed_free_session_data (sm, s, tsm - sm->per_thread_data, 0); nat_ed_session_delete (sm, s, tsm - sm->per_thread_data, 1); return 0; } @@ -3601,13 +3439,13 @@ nat_6t_flow_icmp_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, static_always_inline void nat_6t_flow_ip4_translate (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, - nat_6t_flow_t *f, nat_protocol_t proto, + nat_6t_flow_t *f, ip_protocol_t proto, int is_icmp_inner_ip4, int skip_saddr_rewrite) { udp_header_t *udp = ip4_next_header (ip); tcp_header_t *tcp = (tcp_header_t *) udp; - if ((NAT_PROTOCOL_TCP == proto || NAT_PROTOCOL_UDP == proto) && + if ((IP_PROTOCOL_TCP == proto || IP_PROTOCOL_UDP == proto) && !vnet_buffer (b)->ip.reass.is_non_first_fragment) { if (!is_icmp_inner_ip4) @@ -3625,7 +3463,7 @@ nat_6t_flow_ip4_translate (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, udp->dst_port = f->rewrite.sport; } - if (NAT_PROTOCOL_TCP == proto) + if (IP_PROTOCOL_TCP == proto) { ip_csum_t tcp_sum = tcp->checksum; tcp_sum = ip_csum_sub_even (tcp_sum, f->l3_csum_delta); @@ -3633,7 +3471,7 @@ nat_6t_flow_ip4_translate (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, mss_clamping (sm->mss_clamping, tcp, &tcp_sum); tcp->checksum = ip_csum_fold (tcp_sum); } - else if (proto == NAT_PROTOCOL_UDP && udp->checksum) + else if (IP_PROTOCOL_UDP == proto && udp->checksum) { ip_csum_t udp_sum = udp->checksum; udp_sum = ip_csum_sub_even (udp_sum, f->l3_csum_delta); @@ -3731,8 +3569,7 @@ nat_6t_flow_icmp_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, return NAT_ED_TRNSL_ERR_INNER_IP_CORRUPT; } - nat_protocol_t inner_proto = - ip_proto_to_nat_proto (inner_ip->protocol); + ip_protocol_t inner_proto = inner_ip->protocol; ip_csum_t old_icmp_sum = icmp->checksum; ip_csum_t old_inner_ip_sum = inner_ip->checksum; @@ -3744,7 +3581,7 @@ nat_6t_flow_icmp_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, switch (inner_proto) { - case NAT_PROTOCOL_UDP: + case IP_PROTOCOL_UDP: udp = (udp_header_t *) (inner_ip + 1); if (!it_fits (vm, b, udp, sizeof (*udp))) { @@ -3765,7 +3602,7 @@ nat_6t_flow_icmp_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, new_icmp_sum = ip_csum_fold (new_icmp_sum); icmp->checksum = new_icmp_sum; break; - case NAT_PROTOCOL_TCP: + case IP_PROTOCOL_TCP: tcp = (tcp_header_t *) (inner_ip + 1); if (!it_fits (vm, b, tcp, sizeof (*tcp))) { @@ -3786,7 +3623,7 @@ nat_6t_flow_icmp_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, new_icmp_sum = ip_csum_fold (new_icmp_sum); icmp->checksum = new_icmp_sum; break; - case NAT_PROTOCOL_ICMP: + case IP_PROTOCOL_ICMP: if (f->ops & NAT_FLOW_OP_ICMP_ID_REWRITE) { icmp46_header_t *inner_icmp = ip4_next_header (inner_ip); @@ -3825,7 +3662,7 @@ nat_6t_flow_icmp_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, static_always_inline nat_translation_error_e nat_6t_flow_buf_translate (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, + ip_protocol_t proto, int is_output_feature, int is_i2o) { if (!is_output_feature && f->ops & NAT_FLOW_OP_TXFIB_REWRITE) @@ -3833,7 +3670,7 @@ nat_6t_flow_buf_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, vnet_buffer (b)->sw_if_index[VLIB_TX] = f->rewrite.fib_index; } - if (NAT_PROTOCOL_ICMP == proto) + if (IP_PROTOCOL_ICMP == proto) { if (ip->src_address.as_u32 != f->rewrite.saddr.as_u32) { @@ -3861,7 +3698,7 @@ nat_6t_flow_buf_translate (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, 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, + nat_6t_flow_t *f, ip_protocol_t proto, int is_output_feature) { return nat_6t_flow_buf_translate (vm, sm, b, ip, f, proto, is_output_feature, @@ -3871,7 +3708,7 @@ nat_6t_flow_buf_translate_i2o (vlib_main_t *vm, snat_main_t *sm, 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, + nat_6t_flow_t *f, ip_protocol_t proto, int is_output_feature) { return nat_6t_flow_buf_translate (vm, sm, b, ip, f, proto, is_output_feature, @@ -3981,6 +3818,81 @@ format_nat_6t_flow (u8 *s, va_list *args) return s; } +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, u8 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", 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, u8 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, u8 proto, + u8 is_twicenat) +{ + nat_syslog_nat44_sess (ssubix, sfibix, isaddr, isport, xsaddr, xsport, + idaddr, idport, xdaddr, xdport, proto, 0, + is_twicenat); +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/plugins/nat/nat44-ed/nat44_ed.h b/src/plugins/nat/nat44-ed/nat44_ed.h index e2f5810f9b0..4665f7c0966 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.h +++ b/src/plugins/nat/nat44-ed/nat44_ed.h @@ -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 diff --git a/src/plugins/nat/nat44-ed/nat44_ed_affinity.c b/src/plugins/nat/nat44-ed/nat44_ed_affinity.c index 89f11c64ef3..178671c6b7e 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_affinity.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_affinity.c @@ -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; } diff --git a/src/plugins/nat/nat44-ed/nat44_ed_api.c b/src/plugins/nat/nat44-ed/nat44_ed_api.c index ad00d11052b..d37c2855158 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_api.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_api.c @@ -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, @@ -1225,7 +1225,7 @@ send_nat44_lb_static_mapping_details (snat_static_mapping_t *m, 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 +1740,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 = 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 (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 = 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_nat_address, &s->ext_host_nat_addr, 4); + rmp->ext_host_nat_port = s->ext_host_nat_port; } - 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); } diff --git a/src/plugins/nat/nat44-ed/nat44_ed_classify.c b/src/plugins/nat/nat44-ed/nat44_ed_classify.c index 5a9f4e42657..229cf3669e6 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_classify.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_classify.c @@ -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; } diff --git a/src/plugins/nat/nat44-ed/nat44_ed_cli.c b/src/plugins/nat/nat44-ed/nat44_ed_cli.c index 413c7959962..5ab14a6729a 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_cli.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_cli.c @@ -283,12 +283,7 @@ nat44_show_hash_command_fn (vlib_main_t * vm, unformat_input_t * input, else if (unformat (input, "verbose")) verbose = 2; - vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->static_mapping_by_local, - verbose); - vlib_cli_output (vm, "%U", - format_bihash_8_8, &sm->static_mapping_by_external, - verbose); - vlib_cli_output (vm, "%U", format_bihash_16_8, &sm->flow_hash, verbose); + vlib_cli_output (vm, "%U", format_bihash_16_8, &sm->flow_hash, verbose); vec_foreach_index (i, sm->per_thread_data) { vlib_cli_output (vm, "-------- thread %d %s --------\n", @@ -296,8 +291,7 @@ nat44_show_hash_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, "%U", format_bihash_16_8, &sm->flow_hash, verbose); } - vlib_cli_output (vm, "%U", format_bihash_16_8, &nam->affinity_hash, - verbose); + vlib_cli_output (vm, "%U", format_bihash_16_8, &nam->affinity_hash, verbose); vlib_cli_output (vm, "-------- hash table parameters --------\n"); vlib_cli_output (vm, "translation buckets: %u", sm->translation_buckets); @@ -502,6 +496,7 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input, u32 udp_sessions = 0; u32 tcp_sessions = 0; u32 icmp_sessions = 0; + u32 other_sessions = 0; u32 timed_out = 0; u32 transitory = 0; @@ -526,40 +521,42 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input, if (now >= sess_timeout_time) timed_out++; - switch (s->nat_proto) - { - case NAT_PROTOCOL_ICMP: - icmp_sessions++; - break; - case NAT_PROTOCOL_TCP: - tcp_sessions++; - if (s->state) - { - if (s->tcp_closed_timestamp) - { - if (now >= s->tcp_closed_timestamp) - { - ++transitory_closed; - } - else - { - ++transitory_wait_closed; - } - } - transitory++; - } - else - established++; - break; - case NAT_PROTOCOL_UDP: - default: - udp_sessions++; - break; - } - } - nat44_show_lru_summary (vm, tsm, now, sess_timeout_time); - count += pool_elts (tsm->sessions); - } + switch (s->proto) + { + case IP_PROTOCOL_ICMP: + icmp_sessions++; + break; + case IP_PROTOCOL_TCP: + tcp_sessions++; + if (s->state) + { + if (s->tcp_closed_timestamp) + { + if (now >= s->tcp_closed_timestamp) + { + ++transitory_closed; + } + else + { + ++transitory_wait_closed; + } + } + transitory++; + } + else + established++; + break; + case IP_PROTOCOL_UDP: + udp_sessions++; + break; + default: + ++other_sessions; + break; + } + } + nat44_show_lru_summary (vm, tsm, now, sess_timeout_time); + count += pool_elts (tsm->sessions); + } } else { @@ -571,36 +568,38 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input, if (now >= sess_timeout_time) timed_out++; - switch (s->nat_proto) - { - case NAT_PROTOCOL_ICMP: - icmp_sessions++; - break; - case NAT_PROTOCOL_TCP: - tcp_sessions++; - if (s->state) - { - if (s->tcp_closed_timestamp) - { - if (now >= s->tcp_closed_timestamp) - { - ++transitory_closed; - } - else - { - ++transitory_wait_closed; - } - } - transitory++; - } - else - established++; - break; - case NAT_PROTOCOL_UDP: - default: - udp_sessions++; - break; - } + switch (s->proto) + { + case IP_PROTOCOL_ICMP: + icmp_sessions++; + break; + case IP_PROTOCOL_TCP: + tcp_sessions++; + if (s->state) + { + if (s->tcp_closed_timestamp) + { + if (now >= s->tcp_closed_timestamp) + { + ++transitory_closed; + } + else + { + ++transitory_wait_closed; + } + } + transitory++; + } + else + established++; + break; + case IP_PROTOCOL_UDP: + udp_sessions++; + break; + default: + ++other_sessions; + break; + } } nat44_show_lru_summary (vm, tsm, now, sess_timeout_time); count = pool_elts (tsm->sessions); @@ -617,6 +616,7 @@ nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input, transitory_closed); vlib_cli_output (vm, "total udp sessions: %u", udp_sessions); vlib_cli_output (vm, "total icmp sessions: %u", icmp_sessions); + vlib_cli_output (vm, "total other sessions: %u", other_sessions); return 0; } @@ -636,10 +636,6 @@ nat44_show_addresses_command_fn (vlib_main_t * vm, unformat_input_t * input, fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id); else vlib_cli_output (vm, " tenant VRF independent"); - #define _(N, i, n, s) \ - vlib_cli_output (vm, " %d busy %s ports", ap->busy_##n##_ports, s); - foreach_nat_protocol - #undef _ } vlib_cli_output (vm, "NAT44 twice-nat pool addresses:"); vec_foreach (ap, sm->twice_nat_addresses) @@ -650,10 +646,6 @@ nat44_show_addresses_command_fn (vlib_main_t * vm, unformat_input_t * input, fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id); else vlib_cli_output (vm, " tenant VRF independent"); - #define _(N, i, n, s) \ - vlib_cli_output (vm, " %d busy %s ports", ap->busy_##n##_ports, s); - foreach_nat_protocol - #undef _ } return 0; } @@ -837,14 +829,13 @@ add_static_mapping_command_fn (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; vnet_main_t *vnm = vnet_get_main (); clib_error_t *error = 0; - int rv; - - nat_protocol_t proto = NAT_PROTOCOL_OTHER; ip4_address_t l_addr, e_addr, pool_addr; u32 l_port = 0, e_port = 0, vrf_id = ~0; u8 l_port_set = 0, e_port_set = 0; - u32 sw_if_index, flags = 0; - int is_add = 1; + int is_add = 1, rv; + u32 flags = 0; + u32 sw_if_index = ~0; + ip_protocol_t proto = 0; if (!unformat_user (input, unformat_line_input, line_input)) return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT); @@ -886,7 +877,7 @@ add_static_mapping_command_fn (vlib_main_t * vm, } else if (unformat (line_input, "vrf %u", &vrf_id)) ; - else if (unformat (line_input, "%U", unformat_nat_protocol, &proto)) + else if (unformat (line_input, "%U", unformat_ip_protocol, &proto)) ; else if (unformat (line_input, "self-twice-nat")) { @@ -983,7 +974,7 @@ add_identity_mapping_command_fn (vlib_main_t * vm, int rv, is_add = 1, port_set = 0; u32 sw_if_index, port, flags, vrf_id = ~0; - nat_protocol_t proto; + ip_protocol_t proto; ip4_address_t addr; flags = NAT_SM_FLAG_IDENTITY_NAT; @@ -1003,7 +994,7 @@ add_identity_mapping_command_fn (vlib_main_t * vm, } else if (unformat (line_input, "vrf %u", &vrf_id)) ; - else if (unformat (line_input, "%U %u", unformat_nat_protocol, &proto, + else if (unformat (line_input, "%U %u", unformat_ip_protocol, &proto, &port)) { port_set = 1; @@ -1080,7 +1071,7 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm, ip4_address_t l_addr, e_addr; u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0, affinity = 0; u8 proto_set = 0; - nat_protocol_t proto; + ip_protocol_t proto; nat44_lb_addr_port_t *locals = 0, local; int rv, is_add = 1; u32 flags = 0; @@ -1114,7 +1105,7 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm, else if (unformat (line_input, "external %U:%u", unformat_ip4_address, &e_addr, &e_port)) ; - else if (unformat (line_input, "protocol %U", unformat_nat_protocol, + else if (unformat (line_input, "protocol %U", unformat_ip_protocol, &proto)) { proto_set = 1; @@ -1202,7 +1193,7 @@ add_lb_backend_command_fn (vlib_main_t * vm, u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0; int is_add = 1; int rv; - nat_protocol_t proto; + ip_protocol_t proto; u8 proto_set = 0; /* Get a line of input. */ @@ -1221,7 +1212,7 @@ add_lb_backend_command_fn (vlib_main_t * vm, else if (unformat (line_input, "external %U:%u", unformat_ip4_address, &e_addr, &e_port)) ; - else if (unformat (line_input, "protocol %U", unformat_nat_protocol, + else if (unformat (line_input, "protocol %U", unformat_ip_protocol, &proto)) proto_set = 1; else if (unformat (line_input, "del")) @@ -1547,7 +1538,7 @@ nat44_del_session_command_fn (vlib_main_t * vm, u32 port = 0, eh_port = 0, vrf_id = sm->outside_vrf_id; clib_error_t *error = 0; ip4_address_t addr, eh_addr; - nat_protocol_t proto; + ip_protocol_t proto; int is_in = 0; int rv; @@ -1556,9 +1547,8 @@ nat44_del_session_command_fn (vlib_main_t * vm, while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { - if (unformat - (line_input, "%U:%u %U", unformat_ip4_address, &addr, &port, - unformat_nat_protocol, &proto)) + if (unformat (line_input, "%U:%u %U", unformat_ip4_address, &addr, &port, + unformat_ip_protocol, &proto)) ; else if (unformat (line_input, "in")) { @@ -1584,8 +1574,8 @@ nat44_del_session_command_fn (vlib_main_t * vm, } rv = nat44_ed_del_session (sm, &addr, clib_host_to_net_u16 (port), &eh_addr, - clib_host_to_net_u16 (eh_port), - nat_proto_to_ip_proto (proto), vrf_id, is_in); + clib_host_to_net_u16 (eh_port), proto, vrf_id, + is_in); switch (rv) { diff --git a/src/plugins/nat/nat44-ed/nat44_ed_format.c b/src/plugins/nat/nat44-ed/nat44_ed_format.c index 442f6ad3d7a..5eb683d888e 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_format.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_format.c @@ -20,39 +20,6 @@ #include #include -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; } diff --git a/src/plugins/nat/nat44-ed/nat44_ed_in2out.c b/src/plugins/nat/nat44-ed/nat44_ed_in2out.c index 0e330e17b36..73dacce57e6 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_in2out.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_in2out.c @@ -25,18 +25,12 @@ #include #include -#include #include #include #include #include -/* 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) - static char *nat_in2out_ed_error_strings[] = { #define _(sym,string) string, foreach_nat_in2out_ed_error @@ -166,7 +160,7 @@ snat_not_translate_fast (snat_main_t *sm, vlib_node_runtime_t *node, static int nat_ed_alloc_addr_and_port_with_snat_address ( - snat_main_t *sm, u32 nat_proto, u32 thread_index, snat_address_t *a, + snat_main_t *sm, u8 proto, u32 thread_index, snat_address_t *a, u16 port_per_thread, u32 snat_thread_index, snat_session_t *s, ip4_address_t *outside_addr, u16 *outside_port) { @@ -187,27 +181,13 @@ nat_ed_alloc_addr_and_port_with_snat_address ( u16 attempts = ED_PORT_ALLOC_ATTEMPTS; do { - if (NAT_PROTOCOL_ICMP == nat_proto) + if (IP_PROTOCOL_ICMP == proto) { s->o2i.match.sport = clib_host_to_net_u16 (port); } s->o2i.match.dport = clib_host_to_net_u16 (port); if (0 == nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 2)) { -#define _(N, i, n, s) \ - case NAT_PROTOCOL_##N: \ - ++a->busy_##n##_port_refcounts[port]; \ - a->busy_##n##_ports_per_thread[thread_index]++; \ - a->busy_##n##_ports++; \ - break; - switch (nat_proto) - { - foreach_nat_protocol; - default: - nat_elog_info (sm, "unknown protocol"); - return 1; - } -#undef _ *outside_addr = a->addr; *outside_port = clib_host_to_net_u16 (port); return 0; @@ -223,9 +203,8 @@ nat_ed_alloc_addr_and_port_with_snat_address ( static int nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index, u32 nat_proto, u32 thread_index, ip4_address_t s_addr, - u16 port_per_thread, u32 snat_thread_index, - snat_session_t *s, ip4_address_t *outside_addr, - u16 *outside_port) + u32 snat_thread_index, snat_session_t *s, + ip4_address_t *outside_addr, u16 *outside_port) { int i; snat_address_t *a, *ga = 0; @@ -240,7 +219,7 @@ nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index, u32 nat_proto, if (a->fib_index == rx_fib_index) { return nat_ed_alloc_addr_and_port_with_snat_address ( - sm, nat_proto, thread_index, a, port_per_thread, + sm, nat_proto, thread_index, a, sm->port_per_thread, snat_thread_index, s, outside_addr, outside_port); } else if (a->fib_index == ~0) @@ -255,7 +234,7 @@ nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index, u32 nat_proto, if (a->fib_index == rx_fib_index) { return nat_ed_alloc_addr_and_port_with_snat_address ( - sm, nat_proto, thread_index, a, port_per_thread, + sm, nat_proto, thread_index, a, sm->port_per_thread, snat_thread_index, s, outside_addr, outside_port); } else if (a->fib_index == ~0) @@ -267,8 +246,8 @@ nat_ed_alloc_addr_and_port (snat_main_t *sm, u32 rx_fib_index, u32 nat_proto, if (ga) { return nat_ed_alloc_addr_and_port_with_snat_address ( - sm, nat_proto, thread_index, a, port_per_thread, snat_thread_index, - s, outside_addr, outside_port); + sm, nat_proto, thread_index, a, sm->port_per_thread, + snat_thread_index, s, outside_addr, outside_port); } } /* Totally out of translations to use... */ @@ -304,23 +283,18 @@ nat_outside_fib_index_lookup (snat_main_t * sm, ip4_address_t addr) static_always_inline int nat44_ed_external_sm_lookup (snat_main_t *sm, ip4_address_t match_addr, - u16 match_port, nat_protocol_t match_protocol, - u32 match_fib_index, ip4_address_t *daddr, - u16 *dport) + u16 match_port, ip_protocol_t match_protocol, + ip4_address_t *daddr, u16 *dport) { - clib_bihash_kv_8_8_t kv, value; - init_nat_k (&kv, match_addr, match_port, match_fib_index, match_protocol); - if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value)) + snat_static_mapping_t *m = + nat44_ed_sm_o2i_lookup (sm, match_addr, match_port, 0, match_protocol); + if (!m) { /* Try address only mapping */ - init_nat_k (&kv, match_addr, 0, 0, 0); - if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, - &value)) + m = nat44_ed_sm_o2i_lookup (sm, match_addr, 0, 0, 0); + if (!m) return 0; } - - snat_static_mapping_t *m = - pool_elt_at_index (sm->static_mappings, value.value); *daddr = m->local_addr; if (dport) { @@ -343,7 +317,6 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, u32 outside_fib_index; u8 is_identity_nat = 0; - u32 nat_proto = ip_proto_to_nat_proto (proto); snat_session_t *s = NULL; lb_nat_type_t lb = 0; ip4_address_t daddr = r_addr; @@ -382,9 +355,9 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, u32 sm_fib_index; /* First try to match static mapping by local address and port */ int is_sm; - if (snat_static_mapping_match (vm, sm, l_addr, l_port, rx_fib_index, - nat_proto, &sm_addr, &sm_port, &sm_fib_index, - 0, 0, 0, &lb, 0, &is_identity_nat, 0)) + if (snat_static_mapping_match (vm, sm, l_addr, l_port, rx_fib_index, proto, + &sm_addr, &sm_port, &sm_fib_index, 0, 0, 0, + &lb, 0, &is_identity_nat, 0)) { is_sm = 0; } @@ -398,7 +371,7 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, is_sm = 1; } - if (PREDICT_TRUE (nat_proto == NAT_PROTOCOL_TCP)) + if (PREDICT_TRUE (proto == IP_PROTOCOL_TCP)) { if (PREDICT_FALSE (!tcp_flags_is_init ( vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))) @@ -415,7 +388,7 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, { s->in2out.addr = l_addr; s->in2out.port = l_port; - s->nat_proto = nat_proto; + s->proto = proto; s->in2out.fib_index = rx_fib_index; s->out2in.fib_index = outside_fib_index; @@ -423,8 +396,8 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, outside_port = l_port; // hairpinning? - int is_hairpinning = nat44_ed_external_sm_lookup ( - sm, r_addr, r_port, nat_proto, outside_fib_index, &daddr, &dport); + int is_hairpinning = nat44_ed_external_sm_lookup (sm, r_addr, r_port, + proto, &daddr, &dport); s->flags |= is_hairpinning * SNAT_SESSION_FLAG_HAIRPINNING; // destination addr/port updated with real values in @@ -432,7 +405,7 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, nat_6t_o2i_flow_init (sm, thread_index, s, daddr, dport, daddr, 0, s->out2in.fib_index, proto); nat_6t_flow_daddr_rewrite_set (&s->o2i, l_addr.as_u32); - if (NAT_PROTOCOL_ICMP == nat_proto) + if (IP_PROTOCOL_ICMP == proto) { nat_6t_flow_icmp_id_rewrite_set (&s->o2i, l_port); } @@ -442,10 +415,9 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, } nat_6t_flow_txfib_rewrite_set (&s->o2i, rx_fib_index); - if (nat_ed_alloc_addr_and_port ( - sm, rx_fib_index, nat_proto, thread_index, l_addr, - sm->port_per_thread, tsm->snat_thread_index, s, &outside_addr, - &outside_port)) + if (nat_ed_alloc_addr_and_port (sm, rx_fib_index, proto, thread_index, + l_addr, tsm->snat_thread_index, s, + &outside_addr, &outside_port)) { nat_elog_notice (sm, "addresses exhausted"); b->error = node->errors[NAT_IN2OUT_ED_ERROR_OUT_OF_PORTS]; @@ -462,17 +434,17 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, s->out2in.port = outside_port = sm_port; s->in2out.addr = l_addr; s->in2out.port = l_port; - s->nat_proto = nat_proto; + s->proto = proto; s->in2out.fib_index = rx_fib_index; s->out2in.fib_index = outside_fib_index; s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; // hairpinning? - int is_hairpinning = nat44_ed_external_sm_lookup ( - sm, r_addr, r_port, nat_proto, outside_fib_index, &daddr, &dport); + int is_hairpinning = nat44_ed_external_sm_lookup (sm, r_addr, r_port, + proto, &daddr, &dport); s->flags |= is_hairpinning * SNAT_SESSION_FLAG_HAIRPINNING; - if (NAT_PROTOCOL_ICMP == nat_proto) + if (IP_PROTOCOL_ICMP == proto) { nat_6t_o2i_flow_init (sm, thread_index, s, daddr, sm_port, sm_addr, sm_port, s->out2in.fib_index, proto); @@ -503,7 +475,7 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, nat_6t_flow_saddr_rewrite_set (&s->i2o, outside_addr.as_u32); nat_6t_flow_daddr_rewrite_set (&s->i2o, daddr.as_u32); - if (NAT_PROTOCOL_ICMP == nat_proto) + if (IP_PROTOCOL_ICMP == proto) { nat_6t_flow_icmp_id_rewrite_set (&s->i2o, outside_port); } @@ -521,17 +493,14 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, } /* 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, s->proto, + s->in2out.port, s->out2in.port, s->in2out.fib_index); nat_syslog_nat44_sadd (0, s->in2out.fib_index, &s->in2out.addr, s->in2out.port, &s->ext_host_nat_addr, s->ext_host_nat_port, &s->out2in.addr, s->out2in.port, - &s->ext_host_addr, s->ext_host_port, s->nat_proto, 0); + &s->ext_host_addr, s->ext_host_port, s->proto, 0); per_vrf_sessions_register_session (s, thread_index); @@ -540,12 +509,6 @@ slow_path_ed (vlib_main_t *vm, snat_main_t *sm, vlib_buffer_t *b, error: if (s) { - if (!is_sm) - { - snat_free_outside_address_and_port (sm->addresses, thread_index, - &outside_addr, outside_port, - nat_proto); - } nat_ed_session_delete (sm, s, thread_index, 1); } *sessionp = s = NULL; @@ -560,9 +523,10 @@ nat44_ed_not_translate (vlib_main_t *vm, snat_main_t *sm, { clib_bihash_kv_16_8_t kv, value; - init_ed_k (&kv, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, - ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port, - sm->outside_fib_index, ip->protocol); + init_ed_k (&kv, ip->dst_address.as_u32, + vnet_buffer (b)->ip.reass.l4_dst_port, ip->src_address.as_u32, + vnet_buffer (b)->ip.reass.l4_src_port, sm->outside_fib_index, + ip->protocol); /* NAT packet aimed at external address if has active sessions */ if (clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value)) @@ -607,18 +571,18 @@ nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip, &lookup_sport, &lookup_daddr, &lookup_dport, &lookup_protocol)) return 0; - init_ed_k (&kv, lookup_saddr, lookup_sport, lookup_daddr, lookup_dport, - 0, lookup_protocol); + init_ed_k (&kv, lookup_saddr.as_u32, lookup_sport, lookup_daddr.as_u32, + lookup_dport, 0, lookup_protocol); } else if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP) { - init_ed_k (&kv, ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port, - ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, 0, - ip->protocol); + init_ed_k (&kv, ip->src_address.as_u32, + vnet_buffer (b)->ip.reass.l4_src_port, ip->dst_address.as_u32, + vnet_buffer (b)->ip.reass.l4_dst_port, 0, ip->protocol); } else { - init_ed_k (&kv, ip->src_address, 0, ip->dst_address, 0, 0, + init_ed_k (&kv, ip->src_address.as_u32, 0, ip->dst_address.as_u32, 0, 0, ip->protocol); } @@ -665,8 +629,8 @@ nat44_ed_not_translate_output_feature (snat_main_t *sm, vlib_buffer_t *b, u32 tx_fib_index = ip4_fib_table_get_index_for_sw_if_index (tx_sw_if_index); /* src NAT check */ - init_ed_k (&kv, ip->src_address, src_port, ip->dst_address, dst_port, - tx_fib_index, ip->protocol); + init_ed_k (&kv, ip->src_address.as_u32, src_port, ip->dst_address.as_u32, + dst_port, tx_fib_index, ip->protocol); if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value)) { ASSERT (thread_index == ed_value_get_thread_index (&value)); @@ -676,7 +640,7 @@ nat44_ed_not_translate_output_feature (snat_main_t *sm, vlib_buffer_t *b, if (nat44_is_ses_closed (s) && (!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, 1); } return 1; @@ -703,8 +667,8 @@ nat44_ed_not_translate_output_feature (snat_main_t *sm, vlib_buffer_t *b, s = NULL; } - init_ed_k (&kv, ip->dst_address, dst_port, ip->src_address, src_port, - rx_fib_index, ip->protocol); + init_ed_k (&kv, ip->dst_address.as_u32, dst_port, ip->src_address.as_u32, + src_port, rx_fib_index, ip->protocol); if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value)) { ASSERT (thread_index == ed_value_get_thread_index (&value)); @@ -764,9 +728,8 @@ icmp_in2out_ed_slow_path (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, } else { - if (PREDICT_FALSE (nat44_ed_not_translate (vm, sm, node, sw_if_index, b, - ip, NAT_PROTOCOL_ICMP, - rx_fib_index))) + if (PREDICT_FALSE (nat44_ed_not_translate ( + vm, sm, node, sw_if_index, b, ip, IP_PROTOCOL_ICMP, rx_fib_index))) { return next; } @@ -819,7 +782,6 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b, vlib_main_t *vm, vlib_node_runtime_t *node) { - clib_bihash_kv_8_8_t kv, value; clib_bihash_kv_16_8_t s_kv, s_value; snat_static_mapping_t *m = NULL; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; @@ -852,12 +814,11 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b, break; } - init_nat_k (&kv, ip->src_address, 0, rx_fib_index, 0); - /* Try to find static mapping first */ - if (!clib_bihash_search_8_8 (&sm->static_mapping_by_local, &kv, &value)) + m = nat44_ed_sm_i2o_lookup (sm, ip->src_address, 0, rx_fib_index, + ip->protocol); + if (m) { - m = pool_elt_at_index (sm->static_mappings, value.value); new_src_addr = m->external_addr; } else @@ -866,8 +827,9 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b, { if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32) { - init_ed_k (&s_kv, s->out2in.addr, 0, ip->dst_address, 0, - outside_fib_index, ip->protocol); + init_ed_k (&s_kv, s->out2in.addr.as_u32, 0, + ip->dst_address.as_u32, 0, outside_fib_index, + ip->protocol); if (clib_bihash_search_16_8 (&sm->flow_hash, &s_kv, &s_value)) { new_src_addr = s->out2in.addr; @@ -880,8 +842,9 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b, { for (i = 0; i < vec_len (sm->addresses); i++) { - init_ed_k (&s_kv, sm->addresses[i].addr, 0, ip->dst_address, 0, - outside_fib_index, ip->protocol); + init_ed_k (&s_kv, sm->addresses[i].addr.as_u32, 0, + ip->dst_address.as_u32, 0, outside_fib_index, + ip->protocol); if (clib_bihash_search_16_8 (&sm->flow_hash, &s_kv, &s_value)) { new_src_addr = sm->addresses[i].addr; @@ -910,9 +873,8 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b, nat_6t_flow_txfib_rewrite_set (&s->i2o, outside_fib_index); // hairpinning? - int is_hairpinning = - nat44_ed_external_sm_lookup (sm, ip->dst_address, 0, NAT_PROTOCOL_OTHER, - outside_fib_index, &new_dst_addr, NULL); + int is_hairpinning = nat44_ed_external_sm_lookup ( + sm, ip->dst_address, 0, ip->protocol, &new_dst_addr, NULL); s->flags |= is_hairpinning * SNAT_SESSION_FLAG_HAIRPINNING; nat_6t_flow_daddr_rewrite_set (&s->i2o, new_dst_addr.as_u32); @@ -925,7 +887,6 @@ nat44_ed_in2out_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b, nat_6t_flow_txfib_rewrite_set (&s->o2i, rx_fib_index); s->ext_host_addr.as_u32 = ip->dst_address.as_u32; - s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO; s->out2in.addr.as_u32 = new_src_addr.as_u32; s->out2in.fib_index = outside_fib_index; s->in2out.addr.as_u32 = ip->src_address.as_u32; @@ -987,7 +948,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm, u32 rx_sw_if_index0, rx_fib_index0, iph_offset0 = 0; u32 tx_sw_if_index0; u32 cntr_sw_if_index0; - nat_protocol_t proto0; + ip_protocol_t proto0; ip4_header_t *ip0; snat_session_t *s0 = 0; clib_bihash_kv_16_8_t kv0, value0; @@ -1039,7 +1000,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm, goto trace0; } - proto0 = ip_proto_to_nat_proto (ip0->protocol); + proto0 = ip0->protocol; if (is_output_feature) { @@ -1049,7 +1010,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm, goto trace0; } - if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP)) + if (PREDICT_FALSE (proto0 == IP_PROTOCOL_ICMP)) { if (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags != ICMP4_echo_request && @@ -1103,8 +1064,8 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm, s0 = NULL; } - init_ed_k (&kv0, lookup.saddr, lookup.sport, lookup.daddr, lookup.dport, - lookup.fib_index, lookup.proto); + init_ed_k (&kv0, lookup.saddr.as_u32, lookup.sport, lookup.daddr.as_u32, + lookup.dport, lookup.fib_index, lookup.proto); // lookup flow if (clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0)) @@ -1126,7 +1087,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm, if (PREDICT_FALSE (per_vrf_sessions_is_expired (s0, thread_index))) { // session is closed, go slow path - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH; goto trace0; @@ -1154,7 +1115,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm, s0->last_heard + (f64) nat44_session_get_timeout (sm, s0); if (now >= sess_timeout_time) { - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); // session is closed, go slow path next[0] = def_slow; @@ -1175,7 +1136,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm, else { translation_error = NAT_ED_TRNSL_ERR_FLOW_MISMATCH; - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); next[0] = NAT_NEXT_DROP; b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED]; @@ -1186,7 +1147,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm, (translation_error = nat_6t_flow_buf_translate_i2o ( vm, sm, b0, ip0, f, proto0, is_output_feature))) { - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); next[0] = NAT_NEXT_DROP; b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED]; @@ -1195,20 +1156,20 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t *vm, switch (proto0) { - case NAT_PROTOCOL_TCP: + case IP_PROTOCOL_TCP: vlib_increment_simple_counter (&sm->counters.fastpath.in2out.tcp, thread_index, cntr_sw_if_index0, 1); nat44_set_tcp_session_state_i2o (sm, now, s0, b0, thread_index); break; - case NAT_PROTOCOL_UDP: + case IP_PROTOCOL_UDP: vlib_increment_simple_counter (&sm->counters.fastpath.in2out.udp, thread_index, cntr_sw_if_index0, 1); break; - case NAT_PROTOCOL_ICMP: + case IP_PROTOCOL_ICMP: vlib_increment_simple_counter (&sm->counters.fastpath.in2out.icmp, thread_index, cntr_sw_if_index0, 1); break; - case NAT_PROTOCOL_OTHER: + default: vlib_increment_simple_counter (&sm->counters.fastpath.in2out.other, thread_index, cntr_sw_if_index0, 1); break; @@ -1289,7 +1250,7 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm, u32 rx_sw_if_index0, rx_fib_index0, iph_offset0 = 0; u32 tx_sw_if_index0; u32 cntr_sw_if_index0; - nat_protocol_t proto0; + ip_protocol_t proto0; ip4_header_t *ip0; udp_header_t *udp0; icmp46_header_t *icmp0; @@ -1326,9 +1287,9 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm, udp0 = ip4_next_header (ip0); icmp0 = (icmp46_header_t *) udp0; - proto0 = ip_proto_to_nat_proto (ip0->protocol); + proto0 = ip0->protocol; - if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER)) + if (PREDICT_FALSE (nat44_ed_is_unk_proto (proto0))) { s0 = nat44_ed_in2out_slowpath_unknown_proto ( sm, b0, ip0, rx_fib_index0, thread_index, now, vm, node); @@ -1340,7 +1301,7 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm, (translation_error = nat_6t_flow_buf_translate_i2o ( vm, sm, b0, ip0, &s0->i2o, proto0, is_output_feature))) { - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); next[0] = NAT_NEXT_DROP; b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED]; @@ -1352,7 +1313,7 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm, goto trace0; } - if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP)) + if (PREDICT_FALSE (proto0 == IP_PROTOCOL_ICMP)) { next[0] = icmp_in2out_ed_slow_path ( sm, b0, ip0, icmp0, rx_sw_if_index0, rx_fib_index0, node, next[0], @@ -1362,7 +1323,7 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm, (translation_error = nat_6t_flow_buf_translate_i2o ( vm, sm, b0, ip0, &s0->i2o, proto0, is_output_feature))) { - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); next[0] = NAT_NEXT_DROP; b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED]; @@ -1374,10 +1335,10 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm, goto trace0; } - init_ed_k (&kv0, ip0->src_address, - vnet_buffer (b0)->ip.reass.l4_src_port, ip0->dst_address, - vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0, - ip0->protocol); + init_ed_k ( + &kv0, ip0->src_address.as_u32, vnet_buffer (b0)->ip.reass.l4_src_port, + ip0->dst_address.as_u32, vnet_buffer (b0)->ip.reass.l4_dst_port, + rx_fib_index0, ip0->protocol); if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0)) { ASSERT (thread_index == ed_value_get_thread_index (&value0)); @@ -1387,7 +1348,7 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm, if (s0->tcp_closed_timestamp && now >= s0->tcp_closed_timestamp) { - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); s0 = NULL; } @@ -1407,11 +1368,11 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm, * Send DHCP packets to the ipv4 stack, or we won't * be able to use dhcp client on the outside interface */ - if (PREDICT_FALSE - (proto0 == NAT_PROTOCOL_UDP - && (vnet_buffer (b0)->ip.reass.l4_dst_port == - clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_server)) - && ip0->dst_address.as_u32 == 0xffffffff)) + if (PREDICT_FALSE ( + proto0 == IP_PROTOCOL_UDP && + (vnet_buffer (b0)->ip.reass.l4_dst_port == + clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_server)) && + ip0->dst_address.as_u32 == 0xffffffff)) goto trace0; } else @@ -1442,14 +1403,14 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t *vm, (translation_error = nat_6t_flow_buf_translate_i2o ( vm, sm, b0, ip0, &s0->i2o, proto0, is_output_feature))) { - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); next[0] = NAT_NEXT_DROP; b0->error = node->errors[NAT_IN2OUT_ED_ERROR_TRNSL_FAILED]; goto trace0; } - if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP)) + if (PREDICT_TRUE (proto0 == IP_PROTOCOL_TCP)) { vlib_increment_simple_counter (&sm->counters.slowpath.in2out.tcp, thread_index, cntr_sw_if_index0, 1); diff --git a/src/plugins/nat/nat44-ed/nat44_ed_inlines.h b/src/plugins/nat/nat44-ed/nat44_ed_inlines.h index 0d75e736849..cb418960249 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_inlines.h +++ b/src/plugins/nat/nat44-ed/nat44_ed_inlines.h @@ -26,114 +26,50 @@ #include #include -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) -{ - 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_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) { - 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); + 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_nat_i2o_kv (clib_bihash_kv_8_8_t *kv, snat_session_t *s, 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_nat_k (kv, s->in2out.addr, s->in2out.port, s->in2out.fib_index, - s->nat_proto); + 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 -init_nat_o2i_k (clib_bihash_kv_8_8_t *kv, snat_session_t *s) +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_nat_k (kv, s->out2in.addr, s->out2in.port, s->out2in.fib_index, - s->nat_proto); + return init_ed_kv (kv, addr, port, 0, 0, fib_index, proto, 0, sm_index); } 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) +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 value->value & ~(u32) 0; + return init_ed_kv (kv, 0, 0, e_addr, e_port, fib_index, proto, 0, sm_index); } 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) +nat44_ed_sm_init_i2o_k (clib_bihash_kv_16_8_t *kv, u32 addr, u16 port, + u32 fib_index, u8 proto) { - kv->key[0] = (u64) r_addr.as_u32 << 32 | l_addr.as_u32; - kv->key[1] = - (u64) r_port << 48 | (u64) l_port << 32 | fib_index << 8 | proto; + return nat44_ed_sm_init_i2o_kv (kv, addr, port, fib_index, proto, 0); } 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) +nat44_ed_sm_init_o2i_k (clib_bihash_kv_16_8_t *kv, u32 e_addr, u16 e_port, + u32 fib_index, u8 proto) { - init_ed_k (kv, l_addr, l_port, r_addr, r_port, fib_index, proto); - kv->value = (u64) thread_index << 32 | session_index; + return nat44_ed_sm_init_o2i_kv (kv, e_addr, e_port, fib_index, proto, 0); } always_inline u32 @@ -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__ */ /* diff --git a/src/plugins/nat/nat44-ed/nat44_ed_out2in.c b/src/plugins/nat/nat44-ed/nat44_ed_out2in.c index cb21b0f62c5..5ad57a17098 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_out2in.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_out2in.c @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -127,8 +126,8 @@ next_src_nat (snat_main_t *sm, ip4_header_t *ip, u16 src_port, u16 dst_port, { clib_bihash_kv_16_8_t kv, value; - init_ed_k (&kv, ip->src_address, src_port, ip->dst_address, dst_port, - rx_fib_index, ip->protocol); + init_ed_k (&kv, ip->src_address.as_u32, src_port, ip->dst_address.as_u32, + dst_port, rx_fib_index, ip->protocol); if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value)) return 1; @@ -142,8 +141,8 @@ static void create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, static snat_session_t *create_session_for_static_mapping_ed ( snat_main_t *sm, vlib_buffer_t *b, ip4_address_t i2o_addr, u16 i2o_port, u32 i2o_fib_index, ip4_address_t o2i_addr, u16 o2i_port, u32 o2i_fib_index, - nat_protocol_t nat_proto, vlib_node_runtime_t *node, u32 rx_fib_index, - u32 thread_index, twice_nat_type_t twice_nat, lb_nat_type_t lb_nat, f64 now, + ip_protocol_t proto, vlib_node_runtime_t *node, u32 thread_index, + twice_nat_type_t twice_nat, lb_nat_type_t lb_nat, f64 now, snat_static_mapping_t *mapping); static inline u32 @@ -180,10 +179,10 @@ icmp_out2in_ed_slow_path (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, goto out; } - if (snat_static_mapping_match ( - vm, sm, ip->dst_address, lookup_sport, rx_fib_index, - ip_proto_to_nat_proto (ip->protocol), &sm_addr, &sm_port, - &sm_fib_index, 1, &is_addr_only, 0, 0, 0, &identity_nat, &m)) + if (snat_static_mapping_match (vm, sm, ip->dst_address, lookup_sport, + rx_fib_index, ip->protocol, &sm_addr, + &sm_port, &sm_fib_index, 1, &is_addr_only, 0, + 0, 0, &identity_nat, &m)) { // static mapping not matched if (!sm->forwarding_enabled) @@ -229,8 +228,8 @@ icmp_out2in_ed_slow_path (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, /* Create session initiated by host from external network */ s = create_session_for_static_mapping_ed ( sm, b, sm_addr, sm_port, sm_fib_index, ip->dst_address, lookup_sport, - rx_fib_index, ip_proto_to_nat_proto (lookup_protocol), node, rx_fib_index, - thread_index, 0, 0, vlib_time_now (vm), m); + rx_fib_index, lookup_protocol, node, thread_index, 0, 0, + vlib_time_now (vm), m); if (!s) next = NAT_NEXT_DROP; @@ -265,44 +264,29 @@ out: return next; } -// allocate exact address based on preference static_always_inline int -nat_alloc_addr_and_port_exact (snat_address_t * a, - u32 thread_index, - nat_protocol_t proto, - ip4_address_t * addr, - u16 * port, - u16 port_per_thread, u32 snat_thread_index) +nat44_ed_alloc_i2o_port (snat_main_t *sm, snat_address_t *a, snat_session_t *s, + ip4_address_t i2o_addr, u16 i2o_port, + u32 i2o_fib_index, ip_protocol_t proto, + u32 thread_index, u32 snat_thread_index, + ip4_address_t *outside_addr, u16 *outside_port) { - snat_main_t *sm = &snat_main; u32 portnum; - switch (proto) + for (int i = 0; i < ED_PORT_ALLOC_ATTEMPTS; ++i) { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \ - { \ - while (1) \ - { \ - portnum = (port_per_thread * \ - snat_thread_index) + \ - snat_random_port(0, port_per_thread - 1) + 1024; \ - if (a->busy_##n##_port_refcounts[portnum]) \ - continue; \ - --a->busy_##n##_port_refcounts[portnum]; \ - a->busy_##n##_ports_per_thread[thread_index]++; \ - a->busy_##n##_ports++; \ - *addr = a->addr; \ - *port = clib_host_to_net_u16(portnum); \ - return 0; \ - } \ - } \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (sm, "unknown protocol"); - return 1; + portnum = (sm->port_per_thread * snat_thread_index) + + snat_random_port (0, sm->port_per_thread - 1) + 1024; + portnum = clib_host_to_net_u16 (portnum); + nat_6t_i2o_flow_init (sm, thread_index, s, i2o_addr, i2o_port, a->addr, + portnum, i2o_fib_index, proto); + if (!nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, + 1 /* is_add */)) + { + *outside_addr = a->addr; + *outside_port = portnum; + return 0; + } } /* Totally out of translations to use... */ @@ -311,80 +295,56 @@ nat_alloc_addr_and_port_exact (snat_address_t * a, } static_always_inline int -nat44_ed_alloc_outside_addr_and_port (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) +nat44_ed_alloc_i2o_addr_and_port (snat_main_t *sm, snat_address_t *addresses, + snat_session_t *s, ip4_address_t i2o_addr, + u16 i2o_port, u32 i2o_fib_index, + ip_protocol_t proto, u32 thread_index, + u32 snat_thread_index, + ip4_address_t *outside_addr, + u16 *outside_port) { - snat_main_t *sm = &snat_main; snat_address_t *a, *ga = 0; - u32 portnum; int i; - for (i = 0; i < vec_len (addresses); i++) + if (vec_len (addresses) > 0) { - a = addresses + i; - switch (proto) + int s_addr_offset = i2o_addr.as_u32 % vec_len (addresses); + + for (i = s_addr_offset; i < vec_len (addresses); ++i) { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - if (a->busy_##n##_ports_per_thread[thread_index] < port_per_thread) \ - { \ - if (a->fib_index == fib_index) \ - { \ - while (1) \ - { \ - portnum = (port_per_thread * snat_thread_index) + \ - snat_random_port (0, port_per_thread - 1) + 1024; \ - if (a->busy_##n##_port_refcounts[portnum]) \ - continue; \ - --a->busy_##n##_port_refcounts[portnum]; \ - a->busy_##n##_ports_per_thread[thread_index]++; \ - a->busy_##n##_ports++; \ - *addr = a->addr; \ - *port = clib_host_to_net_u16 (portnum); \ - return 0; \ - } \ - } \ - else if (a->fib_index == ~0) \ - { \ - ga = a; \ - } \ - } \ - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (sm, "unknown protocol"); - return 1; + a = addresses + i; + if (a->fib_index == i2o_fib_index) + { + return nat44_ed_alloc_i2o_port ( + sm, a, s, i2o_addr, i2o_port, i2o_fib_index, proto, + thread_index, snat_thread_index, outside_addr, outside_port); + } + else if (a->fib_index == ~0) + { + ga = a; + } } - } - if (ga) - { - a = ga; - switch (proto) + for (i = 0; i < s_addr_offset; ++i) { -#define _(N, j, n, s) \ - case NAT_PROTOCOL_##N: \ - while (1) \ - { \ - portnum = (port_per_thread * snat_thread_index) + \ - snat_random_port (0, port_per_thread - 1) + 1024; \ - if (a->busy_##n##_port_refcounts[portnum]) \ - continue; \ - ++a->busy_##n##_port_refcounts[portnum]; \ - a->busy_##n##_ports_per_thread[thread_index]++; \ - a->busy_##n##_ports++; \ - *addr = a->addr; \ - *port = clib_host_to_net_u16 (portnum); \ - return 0; \ - } - break; - foreach_nat_protocol -#undef _ - default : nat_elog_info (sm, "unknown protocol"); - return 1; + a = addresses + i; + if (a->fib_index == i2o_fib_index) + { + return nat44_ed_alloc_i2o_port ( + sm, a, s, i2o_addr, i2o_port, i2o_fib_index, proto, + thread_index, snat_thread_index, outside_addr, outside_port); + } + else if (a->fib_index == ~0) + { + ga = a; + } + } + + if (ga) + { + return nat44_ed_alloc_i2o_port ( + sm, a, s, i2o_addr, i2o_port, i2o_fib_index, proto, thread_index, + snat_thread_index, outside_addr, outside_port); } } @@ -397,23 +357,23 @@ static snat_session_t * create_session_for_static_mapping_ed ( snat_main_t *sm, vlib_buffer_t *b, ip4_address_t i2o_addr, u16 i2o_port, u32 i2o_fib_index, ip4_address_t o2i_addr, u16 o2i_port, u32 o2i_fib_index, - nat_protocol_t nat_proto, vlib_node_runtime_t *node, u32 rx_fib_index, - u32 thread_index, twice_nat_type_t twice_nat, lb_nat_type_t lb_nat, f64 now, + ip_protocol_t proto, vlib_node_runtime_t *node, u32 thread_index, + twice_nat_type_t twice_nat, lb_nat_type_t lb_nat, f64 now, snat_static_mapping_t *mapping) { snat_session_t *s; ip4_header_t *ip; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; - if (PREDICT_FALSE - (nat44_ed_maximum_sessions_exceeded (sm, rx_fib_index, thread_index))) + if (PREDICT_FALSE ( + nat44_ed_maximum_sessions_exceeded (sm, o2i_fib_index, thread_index))) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED]; nat_elog_notice (sm, "maximum sessions exceeded"); return 0; } - s = nat_ed_session_alloc (sm, thread_index, now, nat_proto); + s = nat_ed_session_alloc (sm, thread_index, now, proto); if (!s) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED]; @@ -425,7 +385,7 @@ create_session_for_static_mapping_ed ( s->ext_host_addr.as_u32 = ip->src_address.as_u32; s->ext_host_port = - nat_proto == NAT_PROTOCOL_ICMP ? 0 : vnet_buffer (b)->ip.reass.l4_src_port; + proto == IP_PROTOCOL_ICMP ? 0 : vnet_buffer (b)->ip.reass.l4_src_port; s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; if (lb_nat) s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING; @@ -437,9 +397,9 @@ create_session_for_static_mapping_ed ( s->in2out.addr = i2o_addr; s->in2out.port = i2o_port; s->in2out.fib_index = i2o_fib_index; - s->nat_proto = nat_proto; + s->proto = proto; - if (NAT_PROTOCOL_ICMP == nat_proto) + if (IP_PROTOCOL_ICMP == proto) { nat_6t_o2i_flow_init (sm, thread_index, s, s->ext_host_addr, o2i_port, o2i_addr, o2i_port, o2i_fib_index, ip->protocol); @@ -485,33 +445,23 @@ create_session_for_static_mapping_ed ( if (filter) { - rc = nat_alloc_addr_and_port_exact (filter, - thread_index, - nat_proto, - &s->ext_host_nat_addr, - &s->ext_host_nat_port, - sm->port_per_thread, - tsm->snat_thread_index); + rc = nat44_ed_alloc_i2o_port ( + sm, filter, s, i2o_addr, i2o_port, i2o_fib_index, proto, + thread_index, tsm->snat_thread_index, &s->ext_host_nat_addr, + &s->ext_host_nat_port); s->flags |= SNAT_SESSION_FLAG_EXACT_ADDRESS; } else { - rc = nat44_ed_alloc_outside_addr_and_port ( - sm->twice_nat_addresses, 0, thread_index, nat_proto, - &s->ext_host_nat_addr, &s->ext_host_nat_port, sm->port_per_thread, - tsm->snat_thread_index); + rc = nat44_ed_alloc_i2o_addr_and_port ( + sm, sm->twice_nat_addresses, s, i2o_addr, i2o_port, i2o_fib_index, + proto, thread_index, tsm->snat_thread_index, &s->ext_host_nat_addr, + &s->ext_host_nat_port); } if (rc) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_OUT_OF_PORTS]; - if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 0)) - { - nat_elog_warn (sm, "out2in flow hash del failed"); - } - snat_free_outside_address_and_port ( - sm->twice_nat_addresses, thread_index, &s->ext_host_nat_addr, - s->ext_host_nat_port, s->nat_proto); nat_ed_session_delete (sm, s, thread_index, 1); return 0; } @@ -519,7 +469,7 @@ create_session_for_static_mapping_ed ( s->flags |= SNAT_SESSION_FLAG_TWICE_NAT; nat_6t_flow_saddr_rewrite_set (&s->o2i, s->ext_host_nat_addr.as_u32); - if (NAT_PROTOCOL_ICMP == nat_proto) + if (IP_PROTOCOL_ICMP == proto) { nat_6t_flow_icmp_id_rewrite_set (&s->o2i, s->ext_host_nat_port); } @@ -530,11 +480,8 @@ create_session_for_static_mapping_ed ( nat_6t_l3_l4_csum_calc (&s->o2i); - nat_6t_i2o_flow_init (sm, thread_index, s, i2o_addr, i2o_port, - s->ext_host_nat_addr, s->ext_host_nat_port, - i2o_fib_index, ip->protocol); nat_6t_flow_daddr_rewrite_set (&s->i2o, s->ext_host_addr.as_u32); - if (NAT_PROTOCOL_ICMP == nat_proto) + if (IP_PROTOCOL_ICMP == proto) { nat_6t_flow_icmp_id_rewrite_set (&s->i2o, s->ext_host_port); } @@ -542,10 +489,21 @@ create_session_for_static_mapping_ed ( { nat_6t_flow_dport_rewrite_set (&s->i2o, s->ext_host_port); } + + nat_6t_flow_saddr_rewrite_set (&s->i2o, o2i_addr.as_u32); + if (IP_PROTOCOL_ICMP == proto) + { + nat_6t_flow_icmp_id_rewrite_set (&s->i2o, o2i_port); + } + else + { + nat_6t_flow_sport_rewrite_set (&s->i2o, o2i_port); + } + nat_6t_l3_l4_csum_calc (&s->i2o); } else { - if (NAT_PROTOCOL_ICMP == nat_proto) + if (IP_PROTOCOL_ICMP == proto) { nat_6t_i2o_flow_init (sm, thread_index, s, i2o_addr, i2o_port, s->ext_host_addr, i2o_port, i2o_fib_index, @@ -557,10 +515,9 @@ create_session_for_static_mapping_ed ( s->ext_host_addr, s->ext_host_port, i2o_fib_index, ip->protocol); } - } nat_6t_flow_saddr_rewrite_set (&s->i2o, o2i_addr.as_u32); - if (NAT_PROTOCOL_ICMP == nat_proto) + if (IP_PROTOCOL_ICMP == proto) { nat_6t_flow_icmp_id_rewrite_set (&s->i2o, o2i_port); } @@ -579,18 +536,15 @@ create_session_for_static_mapping_ed ( nat_ed_session_delete (sm, s, thread_index, 1); return 0; } - - 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, s->proto, + s->in2out.port, s->out2in.port, s->in2out.fib_index); nat_syslog_nat44_sadd (0, s->in2out.fib_index, &s->in2out.addr, s->in2out.port, &s->ext_host_nat_addr, s->ext_host_nat_port, &s->out2in.addr, s->out2in.port, - &s->ext_host_addr, s->ext_host_port, s->nat_proto, + &s->ext_host_addr, s->ext_host_port, s->proto, nat44_ed_is_twice_nat_session (s)); per_vrf_sessions_register_session (s, thread_index); @@ -634,8 +588,8 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s, lookup_protocol = ip->protocol; } - init_ed_k (&kv, lookup_saddr, lookup_sport, lookup_daddr, lookup_dport, - rx_fib_index, lookup_protocol); + init_ed_k (&kv, lookup_saddr.as_u32, lookup_sport, lookup_daddr.as_u32, + lookup_dport, rx_fib_index, lookup_protocol); if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value)) { @@ -652,8 +606,6 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s, } else { - u32 proto; - if (PREDICT_FALSE (nat44_ed_maximum_sessions_exceeded (sm, rx_fib_index, thread_index))) @@ -666,19 +618,12 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s, return; } - proto = ip_proto_to_nat_proto (ip->protocol); - s->ext_host_addr = ip->src_address; s->ext_host_port = lookup_dport; s->flags |= SNAT_SESSION_FLAG_FWD_BYPASS; s->out2in.addr = ip->dst_address; s->out2in.port = lookup_sport; - s->nat_proto = proto; - if (proto == NAT_PROTOCOL_OTHER) - { - s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO; - s->out2in.port = ip->protocol; - } + s->proto = ip->protocol; s->out2in.fib_index = rx_fib_index; s->in2out.addr = s->out2in.addr; s->in2out.port = s->out2in.port; @@ -719,7 +664,6 @@ nat44_ed_out2in_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b, vlib_main_t *vm, vlib_node_runtime_t *node) { - clib_bihash_kv_8_8_t kv, value; snat_static_mapping_t *m; snat_session_t *s; @@ -731,15 +675,13 @@ nat44_ed_out2in_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b, return 0; } - init_nat_k (&kv, ip->dst_address, 0, 0, 0); - if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value)) + m = nat44_ed_sm_o2i_lookup (sm, ip->dst_address, 0, 0, ip->protocol); + if (!m) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_NO_TRANSLATION]; return 0; } - m = pool_elt_at_index (sm->static_mappings, value.value); - /* Create a new session */ s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol); if (!s) @@ -750,7 +692,6 @@ nat44_ed_out2in_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b, } s->ext_host_addr.as_u32 = ip->src_address.as_u32; - s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO; s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; s->out2in.addr.as_u32 = ip->dst_address.as_u32; s->out2in.fib_index = rx_fib_index; @@ -813,7 +754,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, { vlib_buffer_t *b0; u32 sw_if_index0, rx_fib_index0; - nat_protocol_t proto0; + ip_protocol_t proto0; ip4_header_t *ip0; snat_session_t *s0 = 0; clib_bihash_kv_16_8_t kv0, value0; @@ -862,9 +803,9 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, goto trace0; } - proto0 = ip_proto_to_nat_proto (ip0->protocol); + proto0 = ip0->protocol; - if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP)) + if (PREDICT_FALSE (proto0 == IP_PROTOCOL_ICMP)) { if (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags != ICMP4_echo_request && @@ -913,8 +854,8 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, s0 = NULL; } - init_ed_k (&kv0, lookup.saddr, lookup.sport, lookup.daddr, lookup.dport, - lookup.fib_index, lookup.proto); + init_ed_k (&kv0, lookup.saddr.as_u32, lookup.sport, lookup.daddr.as_u32, + lookup.dport, lookup.fib_index, lookup.proto); // lookup flow if (clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0)) @@ -935,7 +876,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, if (PREDICT_FALSE (per_vrf_sessions_is_expired (s0, thread_index))) { // session is closed, go slow path - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); slow_path_reason = NAT_ED_SP_REASON_VRF_EXPIRED; next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH; @@ -966,7 +907,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, if (now >= sess_timeout_time) { // session is closed, go slow path - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); slow_path_reason = NAT_ED_SP_SESS_EXPIRED; next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH; @@ -989,7 +930,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, * be able to use dhcp client on the outside interface */ if (PREDICT_FALSE ( - proto0 == NAT_PROTOCOL_UDP && + proto0 == IP_PROTOCOL_UDP && (vnet_buffer (b0)->ip.reass.l4_dst_port == clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client)))) { @@ -1014,7 +955,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, // create_bypass_for_fwd (sm, b0, s0, ip0, rx_fib_index0, // thread_index); translation_error = NAT_ED_TRNSL_ERR_FLOW_MISMATCH; - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); next[0] = NAT_NEXT_DROP; b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED]; @@ -1034,7 +975,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, switch (proto0) { - case NAT_PROTOCOL_TCP: + case IP_PROTOCOL_TCP: vlib_increment_simple_counter (&sm->counters.fastpath.out2in.tcp, thread_index, sw_if_index0, 1); nat44_set_tcp_session_state_o2i (sm, now, s0, @@ -1046,15 +987,15 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, reass.tcp_seq_number, thread_index); break; - case NAT_PROTOCOL_UDP: + case IP_PROTOCOL_UDP: vlib_increment_simple_counter (&sm->counters.fastpath.out2in.udp, thread_index, sw_if_index0, 1); break; - case NAT_PROTOCOL_ICMP: + case IP_PROTOCOL_ICMP: vlib_increment_simple_counter (&sm->counters.fastpath.out2in.icmp, thread_index, sw_if_index0, 1); break; - case NAT_PROTOCOL_OTHER: + default: vlib_increment_simple_counter (&sm->counters.fastpath.out2in.other, thread_index, sw_if_index0, 1); break; @@ -1132,7 +1073,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, { vlib_buffer_t *b0; u32 sw_if_index0, rx_fib_index0; - nat_protocol_t proto0; + ip_protocol_t proto0; ip4_header_t *ip0; udp_header_t *udp0; icmp46_header_t *icmp0; @@ -1168,9 +1109,9 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, udp0 = ip4_next_header (ip0); icmp0 = (icmp46_header_t *) udp0; - proto0 = ip_proto_to_nat_proto (ip0->protocol); + proto0 = ip0->protocol; - if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER)) + if (PREDICT_FALSE (nat44_ed_is_unk_proto (proto0))) { s0 = nat44_ed_out2in_slowpath_unknown_proto ( sm, b0, ip0, rx_fib_index0, thread_index, now, vm, node); @@ -1195,7 +1136,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, goto trace0; } - if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP)) + if (PREDICT_FALSE (proto0 == IP_PROTOCOL_ICMP)) { next[0] = icmp_out2in_ed_slow_path (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, @@ -1217,10 +1158,10 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, goto trace0; } - init_ed_k (&kv0, ip0->src_address, - vnet_buffer (b0)->ip.reass.l4_src_port, ip0->dst_address, - vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0, - ip0->protocol); + init_ed_k ( + &kv0, ip0->src_address.as_u32, vnet_buffer (b0)->ip.reass.l4_src_port, + ip0->dst_address.as_u32, vnet_buffer (b0)->ip.reass.l4_dst_port, + rx_fib_index0, ip0->protocol); s0 = NULL; if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0)) @@ -1232,7 +1173,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, if (s0->tcp_closed_timestamp && now >= s0->tcp_closed_timestamp) { - nat_free_session_data (sm, s0, thread_index, 0); + nat44_ed_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); s0 = NULL; } @@ -1253,10 +1194,10 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, * Send DHCP packets to the ipv4 stack, or we won't * be able to use dhcp client on the outside interface */ - if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_UDP - && (vnet_buffer (b0)->ip.reass.l4_dst_port == - clib_host_to_net_u16 - (UDP_DST_PORT_dhcp_to_client)))) + if (PREDICT_FALSE ( + proto0 == IP_PROTOCOL_UDP && + (vnet_buffer (b0)->ip.reass.l4_dst_port == + clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client)))) { goto trace0; } @@ -1287,9 +1228,9 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, if (PREDICT_FALSE (identity_nat0)) goto trace0; - if ((proto0 == NAT_PROTOCOL_TCP) - && !tcp_flags_is_init (vnet_buffer (b0)->ip. - reass.icmp_type_or_tcp_flags)) + if ((proto0 == IP_PROTOCOL_TCP) && + !tcp_flags_is_init ( + vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags)) { b0->error = node->errors[NAT_OUT2IN_ED_ERROR_NON_SYN]; next[0] = NAT_NEXT_DROP; @@ -1297,16 +1238,10 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, } /* Create session initiated by host from external network */ - s0 = create_session_for_static_mapping_ed (sm, b0, - sm_addr, sm_port, - sm_fib_index, - ip0->dst_address, - vnet_buffer (b0)-> - ip.reass.l4_dst_port, - rx_fib_index0, proto0, - node, rx_fib_index0, - thread_index, twice_nat0, - lb_nat0, now, m); + s0 = create_session_for_static_mapping_ed ( + sm, b0, sm_addr, sm_port, sm_fib_index, ip0->dst_address, + vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0, proto0, + node, thread_index, twice_nat0, lb_nat0, now, m); if (!s0) { next[0] = NAT_NEXT_DROP; @@ -1322,7 +1257,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, goto trace0; } - if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP)) + if (PREDICT_TRUE (proto0 == IP_PROTOCOL_TCP)) { vlib_increment_simple_counter (&sm->counters.slowpath.out2in.tcp, thread_index, sw_if_index0, 1); diff --git a/src/plugins/nat/nat44-ei/nat44_ei.c b/src/plugins/nat/nat44-ei/nat44_ei.c index 2dbef8e34df..3691af3a53e 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei.c +++ b/src/plugins/nat/nat44-ei/nat44_ei.c @@ -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, diff --git a/src/plugins/nat/nat44-ei/nat44_ei.h b/src/plugins/nat/nat44-ei/nat44_ei.h index 2e5d85f071a..2e95b1413ca 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei.h +++ b/src/plugins/nat/nat44-ei/nat44_ei.h @@ -36,6 +36,7 @@ #include #include +#include /* default number of worker handoff frame queue elements */ #define NAT_FQ_NELTS_DEFAULT 64 diff --git a/src/plugins/nat/nat44-ei/nat44_ei_in2out.c b/src/plugins/nat/nat44-ei/nat44_ei_in2out.c index 1e28ed6b635..a2fc5910584 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei_in2out.c +++ b/src/plugins/nat/nat44-ei/nat44_ei_in2out.c @@ -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, diff --git a/src/plugins/nat/nat44-ei/nat44_ei_inlines.h b/src/plugins/nat/nat44-ei/nat44_ei_inlines.h index 672927256d1..399486c77dc 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei_inlines.h +++ b/src/plugins/nat/nat44-ei/nat44_ei_inlines.h @@ -20,6 +20,7 @@ #include #include +#include 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__ */ /* diff --git a/src/plugins/nat/nat44-ei/nat44_ei_out2in.c b/src/plugins/nat/nat44-ei/nat44_ei_out2in.c index 7796b11cfd7..7858811fde5 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei_out2in.c +++ b/src/plugins/nat/nat44-ei/nat44_ei_out2in.c @@ -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, diff --git a/src/plugins/nat/nat64/nat64_db.h b/src/plugins/nat/nat64/nat64_db.h index 711b6bf6b03..c34b671999a 100644 --- a/src/plugins/nat/nat64/nat64_db.h +++ b/src/plugins/nat/nat64/nat64_db.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/test/framework.py b/test/framework.py index aa533f7b641..486553befa1 100755 --- a/test/framework.py +++ b/test/framework.py @@ -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): diff --git a/test/test_nat44_ed.py b/test/test_nat44_ed.py index ec8d7c8d159..2fb955afa74 100644 --- a/test/test_nat44_ed.py +++ b/test/test_nat44_ed.py @@ -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,17 +38,18 @@ 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() def plugin_enable(self): self.vapi.nat44_ed_plugin_enable_disable( - sessions=self.max_sessions, enable=1) + sessions=self.max_sessions, enable=1, + inside_vrf=0, outside_vrf=1) def plugin_disable(self): self.vapi.nat44_ed_plugin_enable_disable(enable=0) @@ -146,7 +148,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 +912,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 +2256,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'] diff --git a/test/test_nat44_ed_output.py b/test/test_nat44_ed_output.py new file mode 100644 index 00000000000..ea5c14e7064 --- /dev/null +++ b/test/test_nat44_ed_output.py @@ -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) diff --git a/test/test_nat44_ei.py b/test/test_nat44_ei.py index 74a082eee0a..5fdcf3fa3c7 100644 --- a/test/test_nat44_ei.py +++ b/test/test_nat44_ei.py @@ -605,7 +605,7 @@ class MethodHolder(VppTestCase): self.assertEqual(struct.pack("!H", self.udp_port_out), record[227]) else: - self.fail("Invalid protocol") + self.fail(f"Invalid protocol {scapy.compat.orb(record[4])}") self.assertEqual(3, nat44_ses_create_num) self.assertEqual(3, nat44_ses_delete_num) -- cgit 1.2.3-korg