diff options
author | Filip Varga <fivarga@cisco.com> | 2021-02-17 14:34:54 +0100 |
---|---|---|
committer | Ole Tr�an <otroan@employees.org> | 2021-02-24 19:25:25 +0000 |
commit | 0eaf4e6784efb2d058fe2f031578251b6bcc0aa8 (patch) | |
tree | cc0c2b485bfee51068fa4970acc9f95ec595e8e5 /src/plugins/nat/lib | |
parent | 5db2f4a4312112ab57043ce88f10edc4acc141ec (diff) |
nat: Final NAT44 EI/ED split patch
This patch achieves complete separation of
endpoint-dependent and endpoint-independent IPv4 NAT
features. Some common stuff is also moved to NAT
library.
Type: refactor
Change-Id: I52468b7e2b5ac28958a2baf8e2ea01787322e801
Signed-off-by: Filip Varga <fivarga@cisco.com>
Diffstat (limited to 'src/plugins/nat/lib')
-rw-r--r-- | src/plugins/nat/lib/lib.c | 59 | ||||
-rw-r--r-- | src/plugins/nat/lib/lib.h | 47 | ||||
-rw-r--r-- | src/plugins/nat/lib/log.h | 214 | ||||
-rw-r--r-- | src/plugins/nat/lib/nat_inlines.h | 14 | ||||
-rw-r--r-- | src/plugins/nat/lib/nat_types.api | 47 |
5 files changed, 380 insertions, 1 deletions
diff --git a/src/plugins/nat/lib/lib.c b/src/plugins/nat/lib/lib.c new file mode 100644 index 00000000000..d2def2cc480 --- /dev/null +++ b/src/plugins/nat/lib/lib.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <nat/lib/lib.h> + +uword +unformat_nat_protocol (unformat_input_t *input, va_list *args) +{ + u32 *r = va_arg (*args, u32 *); + + if (0) + ; +#define _(N, i, n, s) else if (unformat (input, s)) *r = NAT_PROTOCOL_##N; + foreach_nat_protocol +#undef _ + else return 0; + return 1; +} + +u8 * +format_nat_protocol (u8 *s, va_list *args) +{ + u32 i = va_arg (*args, u32); + u8 *t = 0; + + switch (i) + { +#define _(N, j, n, str) \ + case NAT_PROTOCOL_##N: \ + t = (u8 *) str; \ + break; + foreach_nat_protocol +#undef _ + default : s = format (s, "unknown"); + return s; + } + s = format (s, "%s", t); + return s; +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/nat/lib/lib.h b/src/plugins/nat/lib/lib.h index 04bad5c74f7..b0b5229b337 100644 --- a/src/plugins/nat/lib/lib.h +++ b/src/plugins/nat/lib/lib.h @@ -95,7 +95,52 @@ nat_reset_timeouts (nat_timeouts_t * timeouts) timeouts->icmp = NAT_ICMP_TIMEOUT; } -// TODO: move common formating definitions here +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) +{ + n_elts = n_elts / 2.5; + u64 lower_pow2 = 1; + while (lower_pow2 * 2 < n_elts) + { + lower_pow2 = 2 * lower_pow2; + } + u64 upper_pow2 = 2 * lower_pow2; + if ((upper_pow2 - n_elts) < (n_elts - lower_pow2)) + { + if (upper_pow2 <= UINT32_MAX) + { + return upper_pow2; + } + } + 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__ */ /* diff --git a/src/plugins/nat/lib/log.h b/src/plugins/nat/lib/log.h new file mode 100644 index 00000000000..26bd93f2589 --- /dev/null +++ b/src/plugins/nat/lib/log.h @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2020 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file + * @brief NAT port/address allocation lib + */ +#ifndef included_nat_log_h__ +#define included_nat_log_h__ + +#include <vppinfra/elog.h> + +#define foreach_nat_log_level \ + _ (0x00, LOG_NONE) \ + _ (0x01, LOG_ERROR) \ + _ (0x02, LOG_WARNING) \ + _ (0x03, LOG_NOTICE) \ + _ (0x04, LOG_INFO) \ + _ (0x05, LOG_DEBUG) + +typedef enum nat_log_level_t_ +{ +#define _(n, f) NAT_##f = n, + foreach_nat_log_level +#undef _ +} nat_log_level_t; + +#define nat_elog(_pm, _level, _str) \ + do \ + { \ + if (PREDICT_FALSE (_pm->log_level >= _level)) \ + { \ + ELOG_TYPE_DECLARE (e) = { \ + .format = "nat-msg " _str, \ + .format_args = "", \ + }; \ + ELOG_DATA (&vlib_global_main.elog_main, e); \ + } \ + } \ + while (0); + +#define nat_elog_addr(_pm, _level, _str, _addr) \ + do \ + { \ + if (PREDICT_FALSE (_pm->log_level >= _level)) \ + { \ + ELOG_TYPE_DECLARE (e) = { \ + .format = "nat-msg " _str " %d.%d.%d.%d", \ + .format_args = "i1i1i1i1", \ + }; \ + CLIB_PACKED (struct { \ + u8 oct1; \ + u8 oct2; \ + u8 oct3; \ + u8 oct4; \ + }) * \ + ed; \ + ed = ELOG_DATA (&vlib_global_main.elog_main, e); \ + ed->oct4 = _addr >> 24; \ + ed->oct3 = _addr >> 16; \ + ed->oct2 = _addr >> 8; \ + ed->oct1 = _addr; \ + } \ + } \ + while (0); + +#define nat_elog_debug_handoff(_pm, _str, _tid, _fib, _src, _dst) \ + do \ + { \ + if (PREDICT_FALSE (_pm->log_level >= NAT_LOG_DEBUG)) \ + { \ + ELOG_TYPE_DECLARE (e) = { \ + .format = "nat-msg " _str " ip src: %d.%d.%d.%d dst: %d.%d.%d.%d" \ + " tid from: %d to: %d fib: %d", \ + .format_args = "i1i1i1i1i1i1i1i1i4i4i4", \ + }; \ + CLIB_PACKED (struct { \ + u8 src_oct1; \ + u8 src_oct2; \ + u8 src_oct3; \ + u8 src_oct4; \ + u8 dst_oct1; \ + u8 dst_oct2; \ + u8 dst_oct3; \ + u8 dst_oct4; \ + u32 ftid; \ + u32 ttid; \ + u32 fib; \ + }) * \ + ed; \ + ed = ELOG_DATA (&vlib_global_main.elog_main, e); \ + ed->src_oct1 = _src >> 24; \ + ed->src_oct2 = _src >> 16; \ + ed->src_oct3 = _src >> 8; \ + ed->src_oct4 = _src; \ + ed->dst_oct1 = _dst >> 24; \ + ed->dst_oct2 = _dst >> 16; \ + ed->dst_oct3 = _dst >> 8; \ + ed->dst_oct4 = _dst; \ + ed->ftid = vlib_get_thread_index (); \ + ed->ttid = _tid; \ + ed->fib = _fib; \ + } \ + } \ + while (0); + +#define nat_elog_debug_handoff_v2(_pm, _str, _prt, _fib, _src, _dst) \ + do \ + { \ + if (PREDICT_FALSE (_pm->log_level >= NAT_LOG_DEBUG)) \ + { \ + ELOG_TYPE_DECLARE (e) = { \ + .format = \ + "nat-msg " _str " ip_src:%d.%d.%d.%d ip_dst:%d.%d.%d.%d" \ + " tid:%d prt:%d fib:%d", \ + .format_args = "i1i1i1i1i1i1i1i1i4i4i4", \ + }; \ + CLIB_PACKED (struct { \ + u8 src_oct1; \ + u8 src_oct2; \ + u8 src_oct3; \ + u8 src_oct4; \ + u8 dst_oct1; \ + u8 dst_oct2; \ + u8 dst_oct3; \ + u8 dst_oct4; \ + u32 tid; \ + u32 prt; \ + u32 fib; \ + }) * \ + ed; \ + ed = ELOG_DATA (&vlib_global_main.elog_main, e); \ + ed->src_oct1 = _src >> 24; \ + ed->src_oct2 = _src >> 16; \ + ed->src_oct3 = _src >> 8; \ + ed->src_oct4 = _src; \ + ed->dst_oct1 = _dst >> 24; \ + ed->dst_oct2 = _dst >> 16; \ + ed->dst_oct3 = _dst >> 8; \ + ed->dst_oct4 = _dst; \ + ed->tid = vlib_get_thread_index (); \ + ed->prt = _prt; \ + ed->fib = _fib; \ + } \ + } \ + while (0); + +#define nat_elog_X1(_pm, _level, _fmt, _arg, _val1) \ + do \ + { \ + if (PREDICT_FALSE (_pm->log_level >= _level)) \ + { \ + ELOG_TYPE_DECLARE (e) = { \ + .format = "nat-msg " _fmt, \ + .format_args = _arg, \ + }; \ + CLIB_PACKED (struct { typeof (_val1) val1; }) * ed; \ + ed = ELOG_DATA (&vlib_global_main.elog_main, e); \ + ed->val1 = _val1; \ + } \ + } \ + while (0); + +#define nat_elog_notice(_pm, nat_elog_str) \ + nat_elog (_pm, NAT_LOG_INFO, "[notice] " nat_elog_str) +#define nat_elog_warn(_pm, nat_elog_str) \ + nat_elog (_pm, NAT_LOG_WARNING, "[warning] " nat_elog_str) +#define nat_elog_err(_pm, nat_elog_str) \ + nat_elog (_pm, NAT_LOG_ERROR, "[error] " nat_elog_str) +#define nat_elog_debug(_pm, nat_elog_str) \ + nat_elog (_pm, NAT_LOG_DEBUG, "[debug] " nat_elog_str) +#define nat_elog_info(_pm, nat_elog_str) \ + nat_elog (_pm, NAT_LOG_INFO, "[info] " nat_elog_str) + +#define nat_elog_notice_X1(_pm, nat_elog_fmt_str, nat_elog_fmt_arg, \ + nat_elog_val1) \ + nat_elog_X1 (_pm, NAT_LOG_NOTICE, "[notice] " nat_elog_fmt_str, \ + nat_elog_fmt_arg, nat_elog_val1) +#define nat_elog_warn_X1(_pm, nat_elog_fmt_str, nat_elog_fmt_arg, \ + nat_elog_val1) \ + nat_elog_X1 (_pm, NAT_LOG_WARNING, "[warning] " nat_elog_fmt_str, \ + nat_elog_fmt_arg, nat_elog_val1) +#define nat_elog_err_X1(_pm, nat_elog_fmt_str, nat_elog_fmt_arg, \ + nat_elog_val1) \ + nat_elog_X1 (_pm, NAT_LOG_ERROR, "[error] " nat_elog_fmt_str, \ + nat_elog_fmt_arg, nat_elog_val1) +#define nat_elog_debug_X1(_pm, nat_elog_fmt_str, nat_elog_fmt_arg, \ + nat_elog_val1) \ + nat_elog_X1 (_pm, NAT_LOG_DEBUG, "[debug] " nat_elog_fmt_str, \ + nat_elog_fmt_arg, nat_elog_val1) +#define nat_elog_info_X1(_pm, nat_elog_fmt_str, nat_elog_fmt_arg, \ + nat_elog_val1) \ + nat_elog_X1 (_pm, NAT_LOG_INFO, "[info] " nat_elog_fmt_str, \ + nat_elog_fmt_arg, nat_elog_val1) + +#endif /* included_nat_lib_h__ */ +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/nat/lib/nat_inlines.h b/src/plugins/nat/lib/nat_inlines.h index c75b8043cc1..0bd7993ac04 100644 --- a/src/plugins/nat/lib/nat_inlines.h +++ b/src/plugins/nat/lib/nat_inlines.h @@ -77,6 +77,20 @@ mss_clamping (u16 mss_clamping, tcp_header_t * tcp, ip_csum_t * sum) } } +static_always_inline u16 +nat_random_port (u32 *random_seed, u16 min, u16 max) +{ + u32 rwide; + u16 r; + + rwide = random_u32 (random_seed); + r = rwide & 0xFFFF; + if (r >= min && r <= max) + return r; + + return min + (rwide % (max - min + 1)); +} + #endif /* __included_lib_nat_inlines_h__ */ /* diff --git a/src/plugins/nat/lib/nat_types.api b/src/plugins/nat/lib/nat_types.api new file mode 100644 index 00000000000..ad4ee9faba0 --- /dev/null +++ b/src/plugins/nat/lib/nat_types.api @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +option version = "0.0.1"; + +typedef nat_timeouts +{ + u32 udp; + u32 tcp_established; + u32 tcp_transitory; + u32 icmp; +}; + +enum nat_log_level : u8 +{ + NAT_LOG_NONE = 0x00, + NAT_LOG_ERROR = 0x01, + NAT_LOG_WARNING = 0x02, + NAT_LOG_NOTICE = 0x03, + NAT_LOG_INFO = 0x04, + NAT_LOG_DEBUG = 0x05, +}; + +enum nat_config_flags : u8 +{ + NAT_IS_NONE = 0x00, + NAT_IS_TWICE_NAT = 0x01, + NAT_IS_SELF_TWICE_NAT = 0x02, + NAT_IS_OUT2IN_ONLY = 0x04, + NAT_IS_ADDR_ONLY = 0x08, + NAT_IS_OUTSIDE = 0x10, + NAT_IS_INSIDE = 0x20, + NAT_IS_STATIC = 0x40, + NAT_IS_EXT_HOST_VALID = 0x80, +}; |