From patchwork Sat Oct 9 15:28:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: wenxu X-Patchwork-Id: 1538801 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HRTVg6ccGz9t0J for ; Sun, 10 Oct 2021 02:28:59 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 84E5383886; Sat, 9 Oct 2021 15:28:52 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ops96MY2NNEt; Sat, 9 Oct 2021 15:28:51 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id DEE8A83883; Sat, 9 Oct 2021 15:28:50 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id AEF99C000F; Sat, 9 Oct 2021 15:28:50 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) by lists.linuxfoundation.org (Postfix) with ESMTP id CC495C000D for ; Sat, 9 Oct 2021 15:28:48 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id BFC2560BB0 for ; Sat, 9 Oct 2021 15:28:48 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ZsZRfaw20ADX for ; Sat, 9 Oct 2021 15:28:48 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from mail-m2456.qiye.163.com (mail-m2456.qiye.163.com [220.194.24.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id 0108160BAD for ; Sat, 9 Oct 2021 15:28:47 +0000 (UTC) Received: from localhost.localdomain (unknown [117.50.0.204]) by mail-m2456.qiye.163.com (Hmail) with ESMTPA id 1D9A370017F; Sat, 9 Oct 2021 23:28:41 +0800 (CST) From: wenxu@ucloud.cn To: i.maximets@ovn.org, pvalerio@redhat.com Date: Sat, 9 Oct 2021 23:28:38 +0800 Message-Id: <1633793320-26048-1-git-send-email-wenxu@ucloud.cn> X-Mailer: git-send-email 1.8.3.1 X-HM-Spam-Status: e1kfGhgUHx5ZQUtXWQgPGg8OCBgUHx5ZQUlOS1dZCBgUCR5ZQVlLVUtZV1 kWDxoPAgseWUFZKDYvK1lXWShZQUlCN1dZLVlBSVdZDwkaFQgSH1lBWRpLTE1WT00fTUhLS0hLGB 4dVRkRExYaEhckFA4PWVdZFhoPEhUdFFlBWVVLWQY+ X-HM-Sender-Digest: e1kMHhlZQR0aFwgeV1kSHx4VD1lBWUc6MRw6Gjo4LDI0OioXCUtDPxci HEMKCjRVSlVKTUhITEJISElKSU9PVTMWGhIXVQweFQMOOw4YFxQOH1UYFUVZV1kSC1lBWUpKTFVO S1VLVUlLT1lXWQgBWUFKTE1PNwY+ X-HM-Tid: 0a7c65aba8ac8c15kuqt1d9a370017f Cc: dev@openvswitch.org Subject: [ovs-dev] [PATCH v6 1/3] conntrack: select correct sport range for well-known origin sport X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: wenxu Like the kernel datapath. The sport nat range for well-konwn origin sport should limit in the well-known ports. Signed-off-by: wenxu Acked-by: Paolo Valerio --- lib/conntrack.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/conntrack.c b/lib/conntrack.c index 33a1a92..44f99f3 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -2265,8 +2265,16 @@ set_sport_range(const struct nat_action_info_t *ni, const struct conn_key *k, if (((ni->nat_action & NAT_ACTION_SNAT_ALL) == NAT_ACTION_SRC) || ((ni->nat_action & NAT_ACTION_DST))) { *curr = ntohs(k->src.port); - *min = MIN_NAT_EPHEMERAL_PORT; - *max = MAX_NAT_EPHEMERAL_PORT; + if (*curr < 512) { + *min = 1; + *max = 511; + } else if (*curr < 1024) { + *min = 600; + *max = 1023; + } else { + *min = MIN_NAT_EPHEMERAL_PORT; + *max = MAX_NAT_EPHEMERAL_PORT; + } } else { *min = ni->min_port; *max = ni->max_port; From patchwork Sat Oct 9 15:28:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: wenxu X-Patchwork-Id: 1538802 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HRTVj4q4Fz9sf8 for ; Sun, 10 Oct 2021 02:29:01 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 687F44065F; Sat, 9 Oct 2021 15:28:56 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id fNcemH-3nFiE; Sat, 9 Oct 2021 15:28:55 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 6A2F24044D; Sat, 9 Oct 2021 15:28:54 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 264CFC0027; Sat, 9 Oct 2021 15:28:53 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 22307C000D for ; Sat, 9 Oct 2021 15:28:49 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 044D8405C9 for ; Sat, 9 Oct 2021 15:28:49 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id vVQcXfkqMpj0 for ; Sat, 9 Oct 2021 15:28:46 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from mail-m2456.qiye.163.com (mail-m2456.qiye.163.com [220.194.24.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id 9AB354058B for ; Sat, 9 Oct 2021 15:28:46 +0000 (UTC) Received: from localhost.localdomain (unknown [117.50.0.204]) by mail-m2456.qiye.163.com (Hmail) with ESMTPA id 40F477001BE; Sat, 9 Oct 2021 23:28:41 +0800 (CST) From: wenxu@ucloud.cn To: i.maximets@ovn.org, pvalerio@redhat.com Date: Sat, 9 Oct 2021 23:28:39 +0800 Message-Id: <1633793320-26048-2-git-send-email-wenxu@ucloud.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1633793320-26048-1-git-send-email-wenxu@ucloud.cn> References: <1633793320-26048-1-git-send-email-wenxu@ucloud.cn> X-HM-Spam-Status: e1kfGhgUHx5ZQUtXWQgPGg8OCBgUHx5ZQUlOS1dZCBgUCR5ZQVlLVUtZV1 kWDxoPAgseWUFZKDYvK1lXWShZQUlCN1dZLVlBSVdZDwkaFQgSH1lBWUJCT05WGUpNS0JKQk5MQ0 kZVRkRExYaEhckFA4PWVdZFhoPEhUdFFlBWVVLWQY+ X-HM-Sender-Digest: e1kMHhlZQR0aFwgeV1kSHx4VD1lBWUc6N006Eww*MDIwDCofTlEjPw4U EzUwCx5VSlVKTUhITEJISElKT0JKVTMWGhIXVQweFQMOOw4YFxQOH1UYFUVZV1kSC1lBWUpKTFVO S1VLVUlLT1lXWQgBWUFNSklJNwY+ X-HM-Tid: 0a7c65aba93e8c15kuqt40f477001be Cc: dev@openvswitch.org Subject: [ovs-dev] [PATCH v6 2/3] conntrack: split the dst and src port range iterations X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: wenxu Splitting the two port range iterations instead of keeping it nested. And the dst port (in case of DNAT) range would have precedence over the src manipulation in the resolution. Signed-off-by: wenxu --- lib/conntrack.c | 65 +++++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/lib/conntrack.c b/lib/conntrack.c index 44f99f3..a6784ba 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -1036,6 +1036,17 @@ conn_not_found(struct conntrack *ct, struct dp_packet *pkt, nat_action_info); if (!nat_res) { + if (nat_action_info->nat_action & NAT_ACTION_DST) { + struct nat_action_info_t tmp_nat_info; + + memset(&tmp_nat_info, 0, sizeof tmp_nat_info); + tmp_nat_info.nat_action = NAT_ACTION_SRC; + nat_res = nat_get_unique_tuple(ct, nc, nat_conn, + &tmp_nat_info); + if (!nat_res) { + goto nat_res_exhaustion; + } + } goto nat_res_exhaustion; } @@ -2258,12 +2269,12 @@ nat_range_hash(const struct conn *conn, uint32_t basis, /* Ports are stored in host byte order for convenience. */ static void -set_sport_range(const struct nat_action_info_t *ni, const struct conn_key *k, - uint32_t hash, uint16_t *curr, uint16_t *min, - uint16_t *max) +set_port_range(const struct nat_action_info_t *ni, const struct conn_key *k, + uint32_t hash, uint16_t *curr, uint16_t *min, + uint16_t *max) { - if (((ni->nat_action & NAT_ACTION_SNAT_ALL) == NAT_ACTION_SRC) || - ((ni->nat_action & NAT_ACTION_DST))) { + if ((ni->nat_action & NAT_ACTION_SRC) && + (!(ni->nat_action & NAT_ACTION_SRC_PORT))) { *curr = ntohs(k->src.port); if (*curr < 512) { *min = 1; @@ -2275,6 +2286,10 @@ set_sport_range(const struct nat_action_info_t *ni, const struct conn_key *k, *min = MIN_NAT_EPHEMERAL_PORT; *max = MAX_NAT_EPHEMERAL_PORT; } + } else if ((ni->nat_action & NAT_ACTION_DST) && + (!(ni->nat_action & NAT_ACTION_DST_PORT))) { + *curr = ntohs(k->dst.port); + *min = *max = *curr; } else { *min = ni->min_port; *max = ni->max_port; @@ -2282,21 +2297,6 @@ set_sport_range(const struct nat_action_info_t *ni, const struct conn_key *k, } } -static void -set_dport_range(const struct nat_action_info_t *ni, const struct conn_key *k, - uint32_t hash, uint16_t *curr, uint16_t *min, - uint16_t *max) -{ - if (ni->nat_action & NAT_ACTION_DST_PORT) { - *min = ni->min_port; - *max = ni->max_port; - *curr = *min + (hash % ((*max - *min) + 1)); - } else { - *curr = ntohs(k->dst.port); - *min = *max = *curr; - } -} - /* Gets the initial in range address based on the hash. * Addresses are kept in network order. */ static void @@ -2426,8 +2426,7 @@ nat_get_unique_tuple(struct conntrack *ct, const struct conn *conn, uint32_t hash = nat_range_hash(conn, ct->hash_basis, nat_info); bool pat_proto = conn->key.nw_proto == IPPROTO_TCP || conn->key.nw_proto == IPPROTO_UDP; - uint16_t min_dport, max_dport, curr_dport; - uint16_t min_sport, max_sport, curr_sport; + uint16_t min_port, max_port, curr_port; min_addr = nat_info->min_addr; max_addr = nat_info->max_addr; @@ -2439,10 +2438,8 @@ nat_get_unique_tuple(struct conntrack *ct, const struct conn *conn, * we can stop once we reach it. */ guard_addr = curr_addr; - set_sport_range(nat_info, &conn->key, hash, &curr_sport, - &min_sport, &max_sport); - set_dport_range(nat_info, &conn->key, hash, &curr_dport, - &min_dport, &max_dport); + set_port_range(nat_info, &conn->key, hash, &curr_port, + &min_port, &max_port); another_round: store_addr_to_key(&curr_addr, &nat_conn->rev_key, @@ -2457,14 +2454,14 @@ another_round: goto next_addr; } - FOR_EACH_PORT_IN_RANGE(curr_dport, min_dport, max_dport) { - nat_conn->rev_key.src.port = htons(curr_dport); - FOR_EACH_PORT_IN_RANGE(curr_sport, min_sport, max_sport) { - nat_conn->rev_key.dst.port = htons(curr_sport); - if (!conn_lookup(ct, &nat_conn->rev_key, - time_msec(), NULL, NULL)) { - return true; - } + FOR_EACH_PORT_IN_RANGE(curr_port, min_port, max_port) { + if (nat_info->nat_action & NAT_ACTION_SRC) { + nat_conn->rev_key.dst.port = htons(curr_port); + } else { + nat_conn->rev_key.src.port = htons(curr_port); + } + if (!conn_lookup(ct, &nat_conn->rev_key, time_msec(), NULL, NULL)) { + return true; } } From patchwork Sat Oct 9 15:28:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: wenxu X-Patchwork-Id: 1538800 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4HRTVg2b22z9sf8 for ; Sun, 10 Oct 2021 02:28:57 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id F355B405DE; Sat, 9 Oct 2021 15:28:54 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id jP6NyBogFMmX; Sat, 9 Oct 2021 15:28:54 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 1E2E2403FA; Sat, 9 Oct 2021 15:28:53 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 5A2ACC0020; Sat, 9 Oct 2021 15:28:52 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id EE2E7C000D for ; Sat, 9 Oct 2021 15:28:48 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id CD6A183886 for ; Sat, 9 Oct 2021 15:28:48 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OP2eotftTXbf for ; Sat, 9 Oct 2021 15:28:48 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from mail-m2456.qiye.163.com (mail-m2456.qiye.163.com [220.194.24.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id ECA7E83883 for ; Sat, 9 Oct 2021 15:28:47 +0000 (UTC) Received: from localhost.localdomain (unknown [117.50.0.204]) by mail-m2456.qiye.163.com (Hmail) with ESMTPA id 7C46A7000FC; Sat, 9 Oct 2021 23:28:41 +0800 (CST) From: wenxu@ucloud.cn To: i.maximets@ovn.org, pvalerio@redhat.com Date: Sat, 9 Oct 2021 23:28:40 +0800 Message-Id: <1633793320-26048-3-git-send-email-wenxu@ucloud.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1633793320-26048-1-git-send-email-wenxu@ucloud.cn> References: <1633793320-26048-1-git-send-email-wenxu@ucloud.cn> X-HM-Spam-Status: e1kfGhgUHx5ZQUtXWQgPGg8OCBgUHx5ZQUlOS1dZCBgUCR5ZQVlLVUtZV1 kWDxoPAgseWUFZKDYvK1lXWShZQUlCN1dZLVlBSVdZDwkaFQgSH1lBWUNLTB9WSkJIGEJOH0tJSk JPVRkRExYaEhckFA4PWVdZFhoPEhUdFFlBWVVLWQY+ X-HM-Sender-Digest: e1kMHhlZQR0aFwgeV1kSHx4VD1lBWUc6Pzo6GRw4GjI6LiotGUo2PxMc EiIwC05VSlVKTUhITEJISElKTEhDVTMWGhIXVQweFQMOOw4YFxQOH1UYFUVZV1kSC1lBWUpKTFVO S1VLVUlLT1lXWQgBWUFPTUlNNwY+ X-HM-Tid: 0a7c65abaa308c15kuqt7c46a7000fc Cc: dev@openvswitch.org Subject: [ovs-dev] [PATCH v6 3/3] conntrack: limit port clash resolution attempts X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: wenxu In case almost or all available ports are taken, clash resolution can take a very long time, resulting in pmd hang in conntrack. 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+. And if thenumber of ip address will limit the max attempts and which will lead the total attempts under 248. Signed-off-by: wenxu --- lib/conntrack.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/lib/conntrack.c b/lib/conntrack.c index a6784ba..1b5d6c2 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -2426,7 +2426,11 @@ nat_get_unique_tuple(struct conntrack *ct, const struct conn *conn, uint32_t hash = nat_range_hash(conn, ct->hash_basis, nat_info); bool pat_proto = conn->key.nw_proto == IPPROTO_TCP || conn->key.nw_proto == IPPROTO_UDP; - uint16_t min_port, max_port, curr_port; + uint16_t min_port, max_port, curr_port, orig_port; + unsigned int attempts, max_attempts, min_attempts; + uint16_t range_port; + uint32_t range_addr; + unsigned int i; min_addr = nat_info->min_addr; max_addr = nat_info->max_addr; @@ -2438,9 +2442,25 @@ nat_get_unique_tuple(struct conntrack *ct, const struct conn *conn, * we can stop once we reach it. */ guard_addr = curr_addr; - set_port_range(nat_info, &conn->key, hash, &curr_port, + set_port_range(nat_info, &conn->key, hash, &orig_port, &min_port, &max_port); + range_port = max_port - min_port + 1; + if (conn->key.dl_type == htons(ETH_TYPE_IP)) { + range_addr = ntohl(max_addr.ipv4) - ntohl(min_addr.ipv4) + 1; + } else { + range_addr = nat_ipv6_addrs_delta(&nat_info->min_addr.ipv6, + &nat_info->max_addr.ipv6) + 1; + } + max_attempts = 128 / range_addr; + if (max_attempts < 1) { + max_attempts = 1; + } + min_attempts = 16 / range_addr; + if (min_attempts < 2) { + min_attempts = 2; + } + another_round: store_addr_to_key(&curr_addr, &nat_conn->rev_key, nat_info->nat_action); @@ -2454,17 +2474,39 @@ another_round: goto next_addr; } + curr_port = orig_port; + + attempts = range_port; + if (attempts > max_attempts) { + attempts = max_attempts; + } + +another_port_round: + i = 0; FOR_EACH_PORT_IN_RANGE(curr_port, min_port, max_port) { if (nat_info->nat_action & NAT_ACTION_SRC) { nat_conn->rev_key.dst.port = htons(curr_port); } else { nat_conn->rev_key.src.port = htons(curr_port); } - if (!conn_lookup(ct, &nat_conn->rev_key, time_msec(), NULL, NULL)) { - return true; + if (i++ < attempts) { + if (!conn_lookup(ct, &nat_conn->rev_key, + time_msec(), NULL, NULL)) { + return true; + } + } else { + goto next_attempts; } } +next_attempts: + if (attempts < range_port && attempts >= min_attempts) { + attempts /= 2; + curr_port = min_port + (random_uint32() % range_port); + + goto another_port_round; + } + /* Check if next IP is in range and respin. Otherwise, notify * exhaustion to the caller. */ next_addr: