[email protected] writes:

> From: wenxu <[email protected]>
>
> This commit splits the nested loop used to search the unique ports for
> the reverse tuple.
> It affects only the dnat action, giving more precedence to the dnat
> range, similarly to the kernel dp, instead of searching through the
> default ephemeral source range for each destination port.
>
> Signed-off-by: wenxu <[email protected]>
> ---
>  lib/conntrack.c | 61 
> +++++++++++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 46 insertions(+), 15 deletions(-)
>

The patch LGTM.

Please, consider this small improvement on top of this,
if you think it makes sense. It simply removes some redundant
assignments.

--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -2402,6 +2402,8 @@ nat_get_unique_l4(struct conntrack *ct, struct conn 
*nat_conn,
                   ovs_be16 *port, uint16_t curr, uint16_t min,
                   uint16_t max)
 {
+    uint16_t orig = curr;
+
     FOR_EACH_PORT_IN_RANGE(curr, min, max) {
         *port = htons(curr);
         if (!conn_lookup(ct, &nat_conn->rev_key,
@@ -2410,6 +2412,8 @@ nat_get_unique_l4(struct conntrack *ct, struct conn 
*nat_conn,
         }
     }
 
+    *port = htons(orig);
+
     return false;
 }
 
@@ -2442,8 +2446,8 @@ nat_get_unique_tuple(struct conntrack *ct, const struct 
conn *conn,
     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);
-    uint16_t min_sport, max_sport, curr_sport, orig_sport;
-    uint16_t min_dport, max_dport, curr_dport, orig_dport;
+    uint16_t min_sport, max_sport, curr_sport, min_dport,
+        max_dport, curr_dport;
     bool pat_proto = conn->key.nw_proto == IPPROTO_TCP ||
                      conn->key.nw_proto == IPPROTO_UDP;
 
@@ -2457,11 +2461,16 @@ 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, &orig_sport,
+    set_sport_range(nat_info, &conn->key, hash, &curr_sport,
                     &min_sport, &max_sport);
-    set_dport_range(nat_info, &conn->key, hash, &orig_dport,
+    set_dport_range(nat_info, &conn->key, hash, &curr_dport,
                     &min_dport, &max_dport);
 
+    if (pat_proto) {
+        nat_conn->rev_key.src.port = htons(curr_dport);
+        nat_conn->rev_key.dst.port = htons(curr_sport);
+    }
+
 another_round:
     store_addr_to_key(&curr_addr, &nat_conn->rev_key,
                       nat_info->nat_action);
@@ -2475,19 +2484,10 @@ another_round:
         goto next_addr;
     }
 
-    curr_sport = orig_sport;
-    curr_dport = orig_dport;
-
-    nat_conn->rev_key.src.port = htons(curr_dport);
-    nat_conn->rev_key.dst.port = htons(curr_sport);
-
     bool found = false;
     if (nat_info->nat_action & NAT_ACTION_DST_PORT) {
         found = nat_get_unique_l4(ct, nat_conn, &nat_conn->rev_key.src.port,
                                   curr_dport, min_dport, max_dport);
-        if (!found) {
-            nat_conn->rev_key.src.port = htons(orig_dport);
-        }
     }
 
     if (!found) {

> diff --git a/lib/conntrack.c b/lib/conntrack.c
> index 44f99f3..dc29c9b 100644
> --- a/lib/conntrack.c
> +++ b/lib/conntrack.c
> @@ -2397,6 +2397,22 @@ next_addr_in_range_guarded(union ct_addr *curr, union 
> ct_addr *min,
>      return exhausted;
>  }
>  
> +static bool
> +nat_get_unique_l4(struct conntrack *ct, struct conn *nat_conn,
> +                  ovs_be16 *port, uint16_t curr, uint16_t min,
> +                  uint16_t max)
> +{
> +    FOR_EACH_PORT_IN_RANGE(curr, min, max) {
> +        *port = htons(curr);
> +        if (!conn_lookup(ct, &nat_conn->rev_key,
> +                         time_msec(), NULL, NULL)) {
> +            return true;
> +        }
> +    }
> +
> +    return false;
> +}
> +
>  /* This function tries to get a unique tuple.
>   * Every iteration checks that the reverse tuple doesn't
>   * collide with any existing one.
> @@ -2411,9 +2427,11 @@ next_addr_in_range_guarded(union ct_addr *curr, union 
> ct_addr *min,
>   *
>   * In case of DNAT:
>   *    - For each dst IP address in the range (if any).
> - *        - For each dport in range (if any).
> - *             - Try to find a source port in the ephemeral range
> - *               (after testing the port used by the sender).
> + *        - For each dport in range (if any) tries to find
> + *          an unique tuple.
> + *        - Eventually, if the previous attempt fails,
> + *          tries to find a source port in the ephemeral
> + *          range (after testing the port used by the sender).
>   *
>   * If none can be found, return exhaustion to the caller. */
>  static bool
> @@ -2424,10 +2442,10 @@ nat_get_unique_tuple(struct conntrack *ct, const 
> struct conn *conn,
>      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);
> +    uint16_t min_sport, max_sport, curr_sport, orig_sport;
> +    uint16_t min_dport, max_dport, curr_dport, orig_dport;
>      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;
>  
>      min_addr = nat_info->min_addr;
>      max_addr = nat_info->max_addr;
> @@ -2439,9 +2457,9 @@ 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,
> +    set_sport_range(nat_info, &conn->key, hash, &orig_sport,
>                      &min_sport, &max_sport);
> -    set_dport_range(nat_info, &conn->key, hash, &curr_dport,
> +    set_dport_range(nat_info, &conn->key, hash, &orig_dport,
>                      &min_dport, &max_dport);
>  
>  another_round:
> @@ -2457,17 +2475,30 @@ 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;
> -            }
> +    curr_sport = orig_sport;
> +    curr_dport = orig_dport;
> +
> +    nat_conn->rev_key.src.port = htons(curr_dport);
> +    nat_conn->rev_key.dst.port = htons(curr_sport);
> +
> +    bool found = false;
> +    if (nat_info->nat_action & NAT_ACTION_DST_PORT) {
> +        found = nat_get_unique_l4(ct, nat_conn, &nat_conn->rev_key.src.port,
> +                                  curr_dport, min_dport, max_dport);
> +        if (!found) {
> +            nat_conn->rev_key.src.port = htons(orig_dport);
>          }
>      }
>  
> +    if (!found) {
> +        found = nat_get_unique_l4(ct, nat_conn, &nat_conn->rev_key.dst.port,
> +                                  curr_sport, min_sport, max_sport);
> +    }
> +
> +    if (found) {
> +        return true;
> +    }
> +
>      /* Check if next IP is in range and respin. Otherwise, notify
>       * exhaustion to the caller. */
>  next_addr:
> -- 
> 1.8.3.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to