@@ -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:
@@ -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
@@ -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) {
@@ -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);
@@ -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:
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(-)