2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00

conntrack: Handle random selection for port ranges.

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>
Acked-by: Aaron Conole <aconole@redhat.com>
Signed-off-by: Simon Horman <horms@ovn.org>
This commit is contained in:
Paolo Valerio 2024-02-16 18:19:13 +01:00 committed by Simon Horman
parent 5f2af0b7a3
commit 99413ec261
5 changed files with 20 additions and 10 deletions

View File

@ -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:

3
NEWS
View File

@ -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 - 16 Feb 2024

View File

@ -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) {

View File

@ -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);

View File

@ -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: