diff mbox series

[ovs-dev,1/2] conntrack: Handle random selection for port ranges.

Message ID 20240207162833.1408714-1-pvalerio@redhat.com
State Superseded
Headers show
Series [ovs-dev,1/2] conntrack: Handle random selection for port ranges. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/intel-ovs-compilation success test: success

Commit Message

Paolo Valerio Feb. 7, 2024, 4:28 p.m. UTC
The userspace conntrack only supported hash for port selection.
With the patch, both userspace and kernel datapath support the random
flag.

The default behavior remains the same, that is, if no flags are
specified, hash is selected.

Signed-off-by: Paolo Valerio <pvalerio@redhat.com>
---
 Documentation/ref/ovs-actions.7.rst |  3 +--
 NEWS                                |  3 +++
 lib/conntrack.c                     | 15 ++++++++-------
 lib/conntrack.h                     |  5 +++++
 lib/dpif-netdev.c                   |  4 +++-
 5 files changed, 20 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/Documentation/ref/ovs-actions.7.rst b/Documentation/ref/ovs-actions.7.rst
index 36adcc5db..80acd9070 100644
--- a/Documentation/ref/ovs-actions.7.rst
+++ b/Documentation/ref/ovs-actions.7.rst
@@ -1551,8 +1551,7 @@  following arguments:
         should be selected. When a port range is specified, fallback to
         ephemeral ports does not happen, else, it will.  The port number
         selection can be informed by the optional ``random`` and ``hash`` flags
-        described below.  The userspace datapath only supports the ``hash``
-        behavior.
+        described below.
 
     The optional *flags* are:
 
diff --git a/NEWS b/NEWS
index a6617546c..93046b963 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@ 
 Post-v3.3.0
 --------------------
+   - Userspace datapath:
+     * Conntrack now supports 'random' flag for selecting ports in a range
+       while natting.
 
 
 v3.3.0 - xx xxx xxxx
diff --git a/lib/conntrack.c b/lib/conntrack.c
index 013709bd6..e09ecdf33 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -2222,7 +2222,7 @@  nat_range_hash(const struct conn_key *key, 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,
+                uint32_t off, uint16_t *curr, uint16_t *min,
                 uint16_t *max)
 {
     if (((ni->nat_action & NAT_ACTION_SNAT_ALL) == NAT_ACTION_SRC) ||
@@ -2241,19 +2241,19 @@  set_sport_range(const struct nat_action_info_t *ni, const struct conn_key *k,
     } else {
         *min = ni->min_port;
         *max = ni->max_port;
-        *curr = *min + (hash % ((*max - *min) + 1));
+        *curr =  *min + (off % ((*max - *min) + 1));
     }
 }
 
 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,
+                uint32_t off, 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));
+        *curr = *min + (off % ((*max - *min) + 1));
     } else {
         *curr = ntohs(k->dst.port);
         *min = *max = *curr;
@@ -2388,18 +2388,19 @@  nat_get_unique_tuple(struct conntrack *ct, struct conn *conn,
                      fwd_key->nw_proto == IPPROTO_SCTP;
     uint16_t min_dport, max_dport, curr_dport;
     uint16_t min_sport, max_sport, curr_sport;
-    uint32_t hash;
+    uint32_t hash, port_off;
 
     hash = nat_range_hash(fwd_key, ct->hash_basis, nat_info);
+    port_off = nat_info->nat_flags & NAT_RANGE_RANDOM ? random_uint32() : hash;
     min_addr = nat_info->min_addr;
     max_addr = nat_info->max_addr;
 
     find_addr(fwd_key, &min_addr, &max_addr, &addr, hash,
               (fwd_key->dl_type == htons(ETH_TYPE_IP)), nat_info);
 
-    set_sport_range(nat_info, fwd_key, hash, &curr_sport,
+    set_sport_range(nat_info, fwd_key, port_off, &curr_sport,
                     &min_sport, &max_sport);
-    set_dport_range(nat_info, fwd_key, hash, &curr_dport,
+    set_dport_range(nat_info, fwd_key, port_off, &curr_dport,
                     &min_dport, &max_dport);
 
     if (pat_proto) {
diff --git a/lib/conntrack.h b/lib/conntrack.h
index 0a888be45..9b0c6aa88 100644
--- a/lib/conntrack.h
+++ b/lib/conntrack.h
@@ -77,12 +77,17 @@  enum nat_action_e {
     NAT_ACTION_DST_PORT = 1 << 3,
 };
 
+enum nat_flags_e {
+    NAT_RANGE_RANDOM = 1 << 0,
+};
+
 struct nat_action_info_t {
     union ct_addr min_addr;
     union ct_addr max_addr;
     uint16_t min_port;
     uint16_t max_port;
     uint16_t nat_action;
+    uint16_t nat_flags;
 };
 
 struct conntrack *conntrack_init(void);
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index c1981137f..c3334c667 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -9409,9 +9409,11 @@  dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
                             nl_attr_get_u16(b_nest);
                         proto_num_max_specified = true;
                         break;
+                    case OVS_NAT_ATTR_PROTO_RANDOM:
+                        nat_action_info.nat_flags |= NAT_RANGE_RANDOM;
+                        break;
                     case OVS_NAT_ATTR_PERSISTENT:
                     case OVS_NAT_ATTR_PROTO_HASH:
-                    case OVS_NAT_ATTR_PROTO_RANDOM:
                         break;
                     case OVS_NAT_ATTR_UNSPEC:
                     case __OVS_NAT_ATTR_MAX: