summaryrefslogtreecommitdiff
path: root/datapath
diff options
context:
space:
mode:
authorDumitru Ceara <dceara@redhat.com>2021-09-07 10:05:24 +0200
committerIlya Maximets <i.maximets@ovn.org>2021-10-12 17:49:11 +0200
commit4a6217fab1ae2e462fbe3db89e764418b6b55726 (patch)
tree3c6231350110d736ce11aea4e837566a4eef69b3 /datapath
parentcc0a87b11cea1fae8c8d4841486b3a3cff8303eb (diff)
downloadopenvswitch-4a6217fab1ae2e462fbe3db89e764418b6b55726.tar.gz
datapath: handle DNAT tuple collision.
Upstream commit: commit 8aa7b526dc0b5dbf40c1b834d76a667ad672a410 Author: Dumitru Ceara <dceara@redhat.com> Date: Wed Oct 7 17:48:03 2020 +0200 openvswitch: handle DNAT tuple collision With multiple DNAT rules it's possible that after destination translation the resulting tuples collide. For example, two openvswitch flows: nw_dst=10.0.0.10,tp_dst=10, actions=ct(commit,table=2,nat(dst=20.0.0.1:20)) nw_dst=10.0.0.20,tp_dst=10, actions=ct(commit,table=2,nat(dst=20.0.0.1:20)) Assuming two TCP clients initiating the following connections: 10.0.0.10:5000->10.0.0.10:10 10.0.0.10:5000->10.0.0.20:10 Both tuples would translate to 10.0.0.10:5000->20.0.0.1:20 causing nf_conntrack_confirm() to fail because of tuple collision. Netfilter handles this case by allocating a null binding for SNAT at egress by default. Perform the same operation in openvswitch for DNAT if no explicit SNAT is requested by the user and allocate a null binding for SNAT for packets in the "original" direction. Reported-at: https://bugzilla.redhat.com/1877128 Suggested-by: Florian Westphal <fw@strlen.de> Fixes: 05752523e565 ("openvswitch: Interface with NAT.") Signed-off-by: Dumitru Ceara <dceara@redhat.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org> Fixes: f8f97cdce9ad ("datapath: Interface with NAT.") Signed-off-by: Dumitru Ceara <dceara@redhat.com> Acked-by: Paolo Valerio <pvalerio@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'datapath')
-rw-r--r--datapath/conntrack.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/datapath/conntrack.c b/datapath/conntrack.c
index 50b4d7bd6..fc268aeae 100644
--- a/datapath/conntrack.c
+++ b/datapath/conntrack.c
@@ -978,15 +978,19 @@ static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
}
err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype);
- if (err == NF_ACCEPT &&
- ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
- if (maniptype == NF_NAT_MANIP_SRC)
- maniptype = NF_NAT_MANIP_DST;
- else
- maniptype = NF_NAT_MANIP_SRC;
-
- err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range,
- maniptype);
+ if (err == NF_ACCEPT && ct->status & IPS_DST_NAT) {
+ if (ct->status & IPS_SRC_NAT) {
+ if (maniptype == NF_NAT_MANIP_SRC)
+ maniptype = NF_NAT_MANIP_DST;
+ else
+ maniptype = NF_NAT_MANIP_SRC;
+
+ err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range,
+ maniptype);
+ } else if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
+ err = ovs_ct_nat_execute(skb, ct, ctinfo, NULL,
+ NF_NAT_MANIP_SRC);
+ }
}
/* Mark NAT done if successful and update the flow key. */