summaryrefslogtreecommitdiff
path: root/lib/conntrack.c
diff options
context:
space:
mode:
authorwenxu <wenxu@chinatelecom.cn>2022-05-05 10:00:07 -0400
committerIlya Maximets <i.maximets@ovn.org>2022-06-07 14:50:00 +0200
commitc608ace71d23c932b9fc70364cbb82bb44ace377 (patch)
treee375e60f7f04417697a102465804c0d7f317009c /lib/conntrack.c
parent071b802c61a3bf0b9304764b4cbc10dfad972105 (diff)
downloadopenvswitch-c608ace71d23c932b9fc70364cbb82bb44ace377.tar.gz
conntrack: Remove the IP iterations in nat_get_unique_l4.
Removing the IP iterations, and just picking the IP address with the hash base on the least-used src-ip/dst-ip/proto triple. Signed-off-by: wenxu <wenxu@chinatelecom.cn> Acked-by: Paolo Valerio <pvalerio@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'lib/conntrack.c')
-rw-r--r--lib/conntrack.c86
1 files changed, 13 insertions, 73 deletions
diff --git a/lib/conntrack.c b/lib/conntrack.c
index 08da4ddf7..6b63fe6c7 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -2297,7 +2297,7 @@ set_dport_range(const struct nat_action_info_t *ni, const struct conn_key *k,
}
}
-/* Gets the initial in range address based on the hash.
+/* Gets an in range address based on the hash.
* Addresses are kept in network order. */
static void
get_addr_in_range(union ct_addr *min, union ct_addr *max,
@@ -2322,10 +2322,10 @@ get_addr_in_range(union ct_addr *min, union ct_addr *max,
}
static void
-get_initial_addr(const struct conn *conn, union ct_addr *min,
- union ct_addr *max, union ct_addr *curr,
- uint32_t hash, bool ipv4,
- const struct nat_action_info_t *nat_info)
+find_addr(const struct conn *conn, union ct_addr *min,
+ union ct_addr *max, union ct_addr *curr,
+ uint32_t hash, bool ipv4,
+ const struct nat_action_info_t *nat_info)
{
const union ct_addr zero_ip = {0};
@@ -2352,51 +2352,6 @@ store_addr_to_key(union ct_addr *addr, struct conn_key *key,
}
}
-static void
-next_addr_in_range(union ct_addr *curr, union ct_addr *min,
- union ct_addr *max, bool ipv4)
-{
- if (ipv4) {
- /* This check could be unified with IPv6, but let's avoid
- * an unneeded memcmp() in case of IPv4. */
- if (min->ipv4 == max->ipv4) {
- return;
- }
-
- curr->ipv4 = (curr->ipv4 == max->ipv4) ? min->ipv4
- : htonl(ntohl(curr->ipv4) + 1);
- } else {
- if (!memcmp(min, max, sizeof *min)) {
- return;
- }
-
- if (!memcmp(curr, max, sizeof *curr)) {
- *curr = *min;
- return;
- }
-
- nat_ipv6_addr_increment(&curr->ipv6, 1);
- }
-}
-
-static bool
-next_addr_in_range_guarded(union ct_addr *curr, union ct_addr *min,
- union ct_addr *max, union ct_addr *guard,
- bool ipv4)
-{
- bool exhausted;
-
- next_addr_in_range(curr, min, max, ipv4);
-
- if (ipv4) {
- exhausted = (curr->ipv4 == guard->ipv4);
- } else {
- exhausted = !memcmp(curr, guard, sizeof *curr);
- }
-
- return exhausted;
-}
-
static bool
nat_get_unique_l4(struct conntrack *ct, struct conn *nat_conn,
ovs_be16 *port, uint16_t curr, uint16_t min,
@@ -2422,7 +2377,7 @@ nat_get_unique_l4(struct conntrack *ct, struct conn *nat_conn,
* collide with any existing one.
*
* In case of SNAT:
- * - For each src IP address in the range (if any).
+ * - Pick a src IP address in the range.
* - Try to find a source port in range (if any).
* - If no port range exists, use the whole
* ephemeral range (after testing the port
@@ -2430,7 +2385,7 @@ nat_get_unique_l4(struct conntrack *ct, struct conn *nat_conn,
* specified range.
*
* In case of DNAT:
- * - For each dst IP address in the range (if any).
+ * - Pick a dst IP address in the range.
* - For each dport in range (if any) tries to find
* an unique tuple.
* - Eventually, if the previous attempt fails,
@@ -2443,9 +2398,8 @@ nat_get_unique_tuple(struct conntrack *ct, const struct conn *conn,
struct conn *nat_conn,
const struct nat_action_info_t *nat_info)
{
- union ct_addr min_addr = {0}, max_addr = {0}, curr_addr = {0},
- guard_addr = {0};
uint32_t hash = nat_range_hash(conn, ct->hash_basis, nat_info);
+ union ct_addr min_addr = {0}, max_addr = {0}, addr = {0};
bool pat_proto = conn->key.nw_proto == IPPROTO_TCP ||
conn->key.nw_proto == IPPROTO_UDP;
uint16_t min_dport, max_dport, curr_dport;
@@ -2454,12 +2408,8 @@ nat_get_unique_tuple(struct conntrack *ct, const struct conn *conn,
min_addr = nat_info->min_addr;
max_addr = nat_info->max_addr;
- get_initial_addr(conn, &min_addr, &max_addr, &curr_addr, hash,
- (conn->key.dl_type == htons(ETH_TYPE_IP)), nat_info);
-
- /* Save the address we started from so that
- * we can stop once we reach it. */
- guard_addr = curr_addr;
+ find_addr(conn, &min_addr, &max_addr, &addr, hash,
+ (conn->key.dl_type == htons(ETH_TYPE_IP)), nat_info);
set_sport_range(nat_info, &conn->key, hash, &curr_sport,
&min_sport, &max_sport);
@@ -2471,8 +2421,7 @@ nat_get_unique_tuple(struct conntrack *ct, const struct conn *conn,
nat_conn->rev_key.dst.port = htons(curr_sport);
}
-another_round:
- store_addr_to_key(&curr_addr, &nat_conn->rev_key,
+ store_addr_to_key(&addr, &nat_conn->rev_key,
nat_info->nat_action);
if (!pat_proto) {
@@ -2481,7 +2430,7 @@ another_round:
return true;
}
- goto next_addr;
+ return false;
}
bool found = false;
@@ -2499,16 +2448,7 @@ another_round:
return true;
}
- /* Check if next IP is in range and respin. Otherwise, notify
- * exhaustion to the caller. */
-next_addr:
- if (next_addr_in_range_guarded(&curr_addr, &min_addr,
- &max_addr, &guard_addr,
- conn->key.dl_type == htons(ETH_TYPE_IP))) {
- return false;
- }
-
- goto another_round;
+ return false;
}
static enum ct_update_res