From 5f694d1ecfbe2315e9bbcc98a83b83620e6f6b94 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Fri, 19 Aug 2022 20:42:22 +0500 Subject: nat: fix nat44-ed port range with multiple workers The number of available dynamic ports is set to (0xffff - 1024) = 64511, which is not divisable by the pow2 number of workers - the only integer divisors are 31 and 2081. So, total dynamic port range of all workers will be less than it: 1 wrk: n = (port_per_thread = 64511/1)*1 = 64511 + 1025 = 65536 2 wrk: n = (port_per_thread = 64511/2)*2 = 64510 + 1025 = 65535 4 wrk: n = (port_per_thread = 64511/4)*4 = 64508 + 1025 = 65533 8 wrk: n = (port_per_thread = 64511/8)*8 = 64504 + 1025 = 65529 ... As seen, with multiple workers there are unused trailing ports for every nat pool address and that is the reason of out-of-bound index in the worker array on out2in path due (port - 1024) / port_per_thread math. This was fixed in 5c9f9968de63fa627b4a72b344df36cdc686d18a, so packets to unused ports will go to existing worker and dropped there. Per RFC 6335 https://www.rfc-editor.org/rfc/rfc6335#section-6: 6. Port Number Ranges o the System Ports, also known as the Well Known Ports, from 0-1023 (assigned by IANA) o the User Ports, also known as the Registered Ports, from 1024- 49151 (assigned by IANA) o the Dynamic Ports, also known as the Private or Ephemeral Ports, from 49152-65535 (never assigned) According that let's allocate dynamic ports from 1024 and have full port range with a wide range of the workers number - 64 integer divisors in total, including pow2 ones: 1 wrk: n = (port_per_thread = 64512/1)*1 = 64512 + 1024 = 65536 2 wrk: n = (port_per_thread = 64512/2)*2 = 64512 + 1024 = 65536 3 wrk: n = (port_per_thread = 64512/3)*3 = 64512 + 1024 = 65536 4 wrk: n = (port_per_thread = 64512/4)*4 = 64512 + 1024 = 65536 5 wrk: n = (port_per_thread = 64512/5)*5 = 64510 + 1024 = 65534 6 wrk: n = (port_per_thread = 64512/6)*6 = 64512 + 1024 = 65536 7 wrk: n = (port_per_thread = 64512/7)*7 = 64512 + 1024 = 65536 8 wrk: n = (port_per_thread = 64512/8)*8 = 64512 + 1024 = 65536 ... Modulo from 5c9f9968de63fa627b4a72b344df36cdc686d18a is still required when the numbers of workers is not the integer divisor of 64512. Type: fix Fixes: 5c9f9968de63fa627b4a72b344df36cdc686d18a Change-Id: I9edaea07e58ff4888812b0d86cbf41a3784b189e Signed-off-by: Vladislav Grishenko --- src/plugins/nat/nat44-ed/nat44_ed.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/plugins/nat/nat44-ed/nat44_ed.c') diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c index 27c1870ccef..2e4c791ef80 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.c +++ b/src/plugins/nat/nat44-ed/nat44_ed.c @@ -762,8 +762,8 @@ get_thread_idx_by_port (u16 e_port) if (sm->num_workers > 1) { thread_idx = sm->first_worker_index + - sm->workers[(e_port - 1024) / sm->port_per_thread % - _vec_len (sm->workers)]; + sm->workers[(e_port - ED_USER_PORT_OFFSET) / + sm->port_per_thread % _vec_len (sm->workers)]; } return thread_idx; } @@ -2133,7 +2133,7 @@ snat_set_workers (uword * bitmap) j++; } - sm->port_per_thread = (0xffff - 1024) / _vec_len (sm->workers); + sm->port_per_thread = (65536 - ED_USER_PORT_OFFSET) / _vec_len (sm->workers); return 0; } @@ -2384,7 +2384,7 @@ nat_init (vlib_main_t * vm) } } num_threads = tm->n_vlib_mains - 1; - sm->port_per_thread = 0xffff - 1024; + sm->port_per_thread = 65536 - ED_USER_PORT_OFFSET; vec_validate (sm->per_thread_data, num_threads); /* Use all available workers by default */ -- cgit 1.2.3-korg