Skip to content

Commit 8aa7b52

Browse files
dcearakuba-moo
authored andcommitted
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 <[email protected]> Fixes: 0575252 ("openvswitch: Interface with NAT.") Signed-off-by: Dumitru Ceara <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent d42ee76 commit 8aa7b52

File tree

1 file changed

+13
-9
lines changed

1 file changed

+13
-9
lines changed

net/openvswitch/conntrack.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -905,15 +905,19 @@ static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
905905
}
906906
err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype);
907907

908-
if (err == NF_ACCEPT &&
909-
ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
910-
if (maniptype == NF_NAT_MANIP_SRC)
911-
maniptype = NF_NAT_MANIP_DST;
912-
else
913-
maniptype = NF_NAT_MANIP_SRC;
914-
915-
err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range,
916-
maniptype);
908+
if (err == NF_ACCEPT && ct->status & IPS_DST_NAT) {
909+
if (ct->status & IPS_SRC_NAT) {
910+
if (maniptype == NF_NAT_MANIP_SRC)
911+
maniptype = NF_NAT_MANIP_DST;
912+
else
913+
maniptype = NF_NAT_MANIP_SRC;
914+
915+
err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range,
916+
maniptype);
917+
} else if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
918+
err = ovs_ct_nat_execute(skb, ct, ctinfo, NULL,
919+
NF_NAT_MANIP_SRC);
920+
}
917921
}
918922

919923
/* Mark NAT done if successful and update the flow key. */

0 commit comments

Comments
 (0)