Example OpenFlow actions:
ct(commit,zone=2,nat(src=10.0.0.1:1000),table=1)
ct(commit,zone=3,nat)
An empty nat nest on ct(commit) passes nat_action_info with
nat_action unset. conn_not_found() treated any non-NULL pointer as
configured NAT and allocated bindings via nat_get_unique_tuple(),
producing entries with zero reply tuples:
orig=(src=10.0.0.1,dst=10.1.1.2,sport=1000,dport=5201)
reply=(src=0.0.0.0,dst=10.0.0.1,sport=5201,dport=0)
Only create NAT bindings when OVS_NAT_ATTR_SRC or OVS_NAT_ATTR_DST was
parsed. Keep passing nat_action_info for an empty nest so ct(nat) still
triggers reverse NAT on established flows.
Add an ofproto-dpif testsuite case.
Fixes: 286de2729955 ("dpdk: Userspace Datapath: Introduce NAT Support.")
Signed-off-by: Eli Britstein <[email protected]>
---
lib/conntrack.c | 22 +++++++++++++---------
tests/ofproto-dpif.at | 22 ++++++++++++++++++++++
2 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/lib/conntrack.c b/lib/conntrack.c
index f84cdd216..7e09537b9 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -1095,8 +1095,6 @@ conn_not_found(struct conntrack *ct, struct dp_packet
*pkt,
}
if (nat_action_info) {
- nc->nat_action = nat_action_info->nat_action;
-
if (alg_exp) {
if (alg_exp->nat_rpl_dst) {
rev_key_node->key.dst.addr = alg_exp->alg_nat_repl_addr;
@@ -1105,18 +1103,24 @@ conn_not_found(struct conntrack *ct, struct dp_packet
*pkt,
rev_key_node->key.src.addr = alg_exp->alg_nat_repl_addr;
nc->nat_action = NAT_ACTION_DST;
}
- } else {
- bool nat_res = nat_get_unique_tuple(ct, nc, nat_action_info);
+ } else if (nat_action_info->nat_action) {
+ bool nat_res;
+
+ nc->nat_action = nat_action_info->nat_action;
+ nat_res = nat_get_unique_tuple(ct, nc, nat_action_info);
if (!nat_res) {
goto nat_res_exhaustion;
}
}
- nat_packet(pkt, nc, false, ctx->icmp_related);
- uint32_t rev_hash = conn_key_hash(&rev_key_node->key,
- ct->hash_basis);
- cmap_insert(&ct->conns[ctx->key.zone],
- &rev_key_node->cm_node, rev_hash);
+ if (nc->nat_action) {
+ uint32_t rev_hash;
+
+ nat_packet(pkt, nc, false, ctx->icmp_related);
+ rev_hash = conn_key_hash(&rev_key_node->key, ct->hash_basis);
+ cmap_insert(&ct->conns[ctx->key.zone],
+ &rev_key_node->cm_node, rev_hash);
+ }
}
cmap_insert(&ct->conns[ctx->key.zone],
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 9e64e8ee4..9a48f5013 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -13364,6 +13364,28 @@ AT_CHECK([tail -1 stdout], [0],
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([ofproto-dpif - nat - empty nat on ct(commit)])
+OVS_VSWITCHD_START
+
+add_of_ports br0 1 2
+
+dnl SNAT in zone 2, then empty ct(commit,nat) in zone 3.
+AT_DATA([flows.txt], [dnl
+table=0,priority=100,in_port=1,tcp,ct_state=-trk,action=ct(commit,zone=2,nat(src=10.0.0.1:1000),table=1)
+table=1,priority=100,ct_zone=2,tcp,action=ct(commit,zone=3,nat)
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+AT_CHECK([ovs-appctl netdev-dummy/receive p1
'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=12345,dst=5201),tcp_flags(syn)'])
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack zone=3], [0], [dnl
+tcp,orig=(src=10.0.0.1,dst=10.1.1.2,sport=1000,dport=5201),reply=(src=10.1.1.2,dst=10.0.0.1,sport=5201,dport=1000),zone=3,protoinfo=(state=SYN_SENT)
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
dnl Checks the get/set sweep interval
AT_SETUP([ofproto-dpif - conntrack - change sweep interval])
OVS_VSWITCHD_START
--
2.43.0
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev