summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/conntrack.c8
-rw-r--r--lib/ovs-actions.xml11
-rw-r--r--tests/system-traffic.at50
3 files changed, 61 insertions, 8 deletions
diff --git a/lib/conntrack.c b/lib/conntrack.c
index ecac584d7..7ead3ad83 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 fec0b95fe..84df842a1 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:1.2.3.4
<dd>
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.
</dd>
</dl>
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index d1f8c1021..b1241812e 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -3994,6 +3994,56 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([conntrack - SNAT with port range with exhaustion])
+CHECK_CONNTRACK()
+CHECK_CONNTRACK_NAT()
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+NS_CHECK_EXEC([at_ns0], [ip link set dev p0 address 80:88:88:88:88:88])
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0.
+AT_DATA([flows.txt], [dnl
+in_port=1,tcp,action=ct(commit,zone=1,nat(src=10.1.1.240:34568,random)),2
+in_port=2,ct_state=-trk,tcp,tp_dst=34567,action=ct(table=0,zone=1,nat)
+in_port=2,ct_state=-trk,tcp,tp_dst=34568,action=ct(table=0,zone=1,nat)
+in_port=2,ct_state=+trk,ct_zone=1,tcp,action=1
+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
+priority=0,action=drop
+dnl
+dnl MAC resolution table for IP in reg2, stores mac in OXM_OF_PKT_REG0
+table=8,reg2=0x0a0101f0/0xfffffff0,action=load:0x808888888888->OXM_OF_PKT_REG0[[]]
+table=8,priority=0,action=load:0->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 10.1.1.2 -t 1 -T 1 --retry-connrefused -v -o wget0.log])
+
+NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 1 -T 1 --retry-connrefused -v -o wget0.log], [4])
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2) | sed -e 's/dst=10.1.1.2[[45]][[0-9]]/dst=10.1.1.2XX/' | uniq], [0], [dnl
+tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.2XX,sport=<cleared>,dport=<cleared>),zone=1,protoinfo=(state=<cleared>)
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP(["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_CLEANUP
AT_SETUP([conntrack - more complex SNAT])
CHECK_CONNTRACK()