diff mbox series

[ovs-dev,v2,2/2] conntrack: Skip ephemeral ports with specified port range.

Message ID 1551139158-58309-2-git-send-email-dlu998@gmail.com
State Accepted
Commit 32b2c81f266440fb46246a21506f00ede71efb27
Headers show
Series [ovs-dev,v2,1/2] conntrack: Fix wasted work for ICMP NAT. | expand

Commit Message

Darrell Ball Feb. 25, 2019, 11:59 p.m. UTC
This patch removes the fallback to ephemeral ports when a SNAT port
range is specified;  DNAT already does not fallback to ephemeral ports,
in general.  This is not restrictive to the user and makes it easier to
limit NAT L4 port selection.

The documentation is updated and a new test is added to enforce the

Fixes: 286de2729955 ("dpdk: Userspace Datapath: Introduce NAT Support.")
Signed-off-by: Darrell Ball <dlu998@gmail.com>

v2: No change to this patch.

 lib/conntrack.c         |  8 +++++---
 lib/ovs-actions.xml     | 11 ++++++-----
 tests/system-traffic.at | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 8 deletions(-)
diff mbox series


diff --git a/lib/conntrack.c b/lib/conntrack.c
index 5f143e0..0a18ca9 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -2175,9 +2175,11 @@  nat_select_range_tuple(struct conntrack *ct, const struct conn *conn,
     uint16_t port = first_port;
     bool all_ports_tried = false;
-    /* For DNAT, we don't use ephemeral ports. */
-    bool ephemeral_ports_tried = conn->nat_info->nat_action & NAT_ACTION_DST
-                                 ? true : false;
+    /* For DNAT or for specified port ranges, we don't use ephemeral ports. */
+    bool ephemeral_ports_tried
+        = conn->nat_info->nat_action & NAT_ACTION_DST ||
+              conn->nat_info->nat_action & NAT_ACTION_SRC_PORT
+          ? true : false;
     union ct_addr first_addr = ct_addr;
     bool pat_enabled = conn->key.nw_proto != IPPROTO_ICMP &&
                        conn->key.nw_proto != IPPROTO_ICMPV6;
diff --git a/lib/ovs-actions.xml b/lib/ovs-actions.xml
index fec0b95..84df842 100644
--- a/lib/ovs-actions.xml
+++ b/lib/ovs-actions.xml
@@ -1664,11 +1664,12 @@  $ ovs-ofctl -O OpenFlow10 add-flow br0 actions=mod_nw_src:
               The L4 <var>port</var> or range
               <code><var>port1</var>-<var>port2</var></code> from which the
-              translated port should be selected. In case of a mapping conflict
-              the datapath may choose any other non-conflicting port number
-              instead, even when no port range is specified.  The port number
-              selection can be informed by the optional <code>random</code> and
-              <code>hash</code> flags described below.
+              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 <code>random</code> and <code>hash</code> flags
+              described below.  The userspace datapath only supports the
+              <code>hash</code> behavior.
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index d1f8c10..b124181 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -3994,6 +3994,56 @@  tcp,orig=(src=,dst=,sport=<cleared>,dport=<cleared>),reply=(src=
+AT_SETUP([conntrack - SNAT with port range with exhaustion])
+ADD_NAMESPACES(at_ns0, at_ns1)
+ADD_VETH(p0, at_ns0, br0, "")
+NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address 80:88:88:88:88:88])
+ADD_VETH(p1, at_ns1, br0, "")
+dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0.
+AT_DATA([flows.txt], [dnl
+dnl ARP
+priority=100 arp arp_op=1 action=move:OXM_OF_ARP_TPA[[]]->NXM_NX_REG2[[]],resubmit(,8),goto_table:10
+priority=10 arp action=normal
+dnl MAC resolution table for IP in reg2, stores mac in OXM_OF_PKT_REG0
+dnl ARP responder mac filled in at OXM_OF_PKT_REG0, or 0 for normal action.
+dnl TPA IP in reg2.
+dnl Swaps the fields of the ARP message to turn a query to a response.
+table=10 priority=100 arp xreg0=0 action=normal
+table=10 priority=10,arp,arp_op=1,action=load:2->OXM_OF_ARP_OP[[]],move:OXM_OF_ARP_SHA[[]]->OXM_OF_ARP_THA[[]],move:OXM_OF_PKT_REG0[[0..47]]->OXM_OF_ARP_SHA[[]],move:OXM_OF_ARP_SPA[[]]->OXM_OF_ARP_TPA[[]],move:NXM_NX_REG2[[]]->OXM_OF_ARP_SPA[[]],move:NXM_OF_ETH_SRC[[]]->NXM_OF_ETH_DST[[]],move:OXM_OF_PKT_REG0[[0..47]]->NXM_OF_ETH_SRC[[]],move:NXM_OF_IN_PORT[[]]->NXM_NX_REG3[[0..15]],load:0->NXM_OF_IN_PORT[[]],output:NXM_NX_REG3[[0..15]]
+table=10 priority=0 action=drop
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+dnl HTTP requests from p0->p1 should work fine.
+OVS_START_L7([at_ns1], [http])
+NS_CHECK_EXEC([at_ns0], [wget -t 1 -T 1 --retry-connrefused -v -o wget0.log])
+NS_CHECK_EXEC([at_ns0], [wget -t 1 -T 1 --retry-connrefused -v -o wget0.log], [4])
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT( | sed -e 's/dst=[[45]][[0-9]]/dst=' | uniq], [0], [dnl
+/Unable to NAT due to tuple space exhaustion - if DoS attack, use firewalling and\/or zone partitioning./d
+/Dropped .* log messages in last .* seconds \(most recently, .* seconds ago\) due to excessive rate/d"])
 AT_SETUP([conntrack - more complex SNAT])