diff mbox series

[ovs-dev] OVN SNAT external_port_range randomized source port question

Message ID b90cdfce-35d1-4111-af88-86e9f564453a@redhat.com
State Not Applicable
Headers show
Series [ovs-dev] OVN SNAT external_port_range randomized source port question | expand

Checks

Context Check Description
ovsrobot/intel-ovs-compilation fail test: fail
ovsrobot/apply-robot fail apply and check: fail

Commit Message

Dumitru Ceara Jan. 15, 2024, 1:43 p.m. UTC
Hi Ankur,

Tim (in cc) pointed me to at what I think to be a bug in the
way OVN's external_port_range option on SNAT works.  I see
you're the original author so I wanted to check whether my
understanding is correct:

https://github.com/ovn-org/ovn/commit/60bdc8ea78d

With the following configuration:

ovn-nbctl --portrange lr-nat-add rtr snat 66.66.66.66 42.42.42.0/24 10000-20000

When client initiates a connection from behind the SNAT,
e.g.:

43.43.43.2:40000 -> 42.42.42.2:8080

this get's SNATed to:

66.66.66.66:X -> 42.42.42.2:80

with X being a random value in the 10000-20000 range.  Until
here the behavior is as expected.

Now, if we change the client and initiate connections with a
source port that's already in the desired range, e.g.:

43.43.43.2:15000 -> 42.42.42.2:8080

then PAT doesn't happen anymore and only the source IP gets
translated:

66.66.66.66:15000 -> 42.42.42.2:80

Checking why that happens I see it's because of the way OVN
configures the SNAT openflow.  The openflow action is:

ct(commit,table=46,zone=NXM_NX_REG12[0..15],nat(src=66.66.66.66:10000-20000))

This leaves the nat flags set to default (0) which AFAICT,
with the kernel datapath, eventually ends up translating to
NF_NAT_RANGE_PROTO_RANDOM:

https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/netfilter/nf_nat.h#L10

With this, conntrack will not do PAT unless needed.  However,
checking the ovs-actions manual:

  "ports  The L4 port or range port1-port2 from which
          the translated port 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"

If we explicitly request random hashing then the datapath
will use NF_NAT_RANGE_PROTO_RANDOM_FULLY and always perform
PAT.

The OVN patch is trivial but I'd like to confirm with you that
this is also desired behavior in your use cases.  Something like
this works just fine for my scenario:

---

Regards,
Dumitru
diff mbox series

Patch

diff --git a/lib/actions.c b/lib/actions.c
index 38cf4642d6..d719dccdf2 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -1133,6 +1133,7 @@  encode_ct_nat(const struct ovnact_ct_nat *cn,
     if (cn->port_range.exists) {
        nat->range.proto.min = cn->port_range.port_lo;
        nat->range.proto.max = cn->port_range.port_hi;
+       nat->flags |= NX_NAT_F_PROTO_RANDOM;
     }

     ofpacts->header = ofpbuf_push_uninit(ofpacts, nat_offset);