From: wenxu <[email protected]> In case almost or all available ports are taken, clash resolution can take a very long time, resulting in pmd lockup.
This can happen when many to-be-natted hosts connect to same destination:port (e.g. a proxy) and all connections pass the same SNAT. Pick a random offset in the acceptable range, then try ever smaller number of adjacent port numbers, until either the limit is reached or a useable port was found. This results in at most 248 attempts (128 + 64 + 32 + 16 + 8, i.e. 4 restarts with new search offset) instead of 64000+. Signed-off-by: wenxu <[email protected]> Acked-by: Paolo Valerio <[email protected]> --- lib/conntrack.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/conntrack.c b/lib/conntrack.c index 6b63fe6..b243370 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -2357,9 +2357,24 @@ nat_get_unique_l4(struct conntrack *ct, struct conn *nat_conn, ovs_be16 *port, uint16_t curr, uint16_t min, uint16_t max) { + static const unsigned int max_attempts = 128; + uint16_t range = max - min + 1; + unsigned int attempts; uint16_t orig = curr; + unsigned int i = 0; + attempts = range; + if (attempts > max_attempts) { + attempts = max_attempts; + } + +another_round: + i = 0; FOR_EACH_PORT_IN_RANGE (curr, min, max) { + if (i++ >= attempts) { + break; + } + *port = htons(curr); if (!conn_lookup(ct, &nat_conn->rev_key, time_msec(), NULL, NULL)) { @@ -2367,6 +2382,12 @@ nat_get_unique_l4(struct conntrack *ct, struct conn *nat_conn, } } + if (attempts < range && attempts >= 16) { + attempts /= 2; + curr = min + (random_uint32() % range); + goto another_round; + } + *port = htons(orig); return false; -- 1.8.3.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
