Message ID | 20240216171914.2651243-1-pvalerio@redhat.com |
---|---|
State | Accepted |
Delegated to: | Simon Horman |
Headers | show |
Series | [ovs-dev,v3,1/2] conntrack: Handle random selection for port ranges. | expand |
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 |
Paolo Valerio <pvalerio@redhat.com> writes: > 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: Simon Horman <horms@ovn.org> > --- Acked-by: Aaron Conole <aconole@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 --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:
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: