Skip to content

Commit 9ff464d

Browse files
Jarno Rajahalmedavem330
authored andcommitted
openvswitch: Use inverted tuple in ovs_ct_find_existing() if NATted.
The conntrack lookup for existing connections fails to invert the packet 5-tuple for NATted packets, and therefore fails to find the existing conntrack entry. Conntrack only stores 5-tuples for incoming packets, and there are various situations where a lookup on a packet that has already been transformed by NAT needs to be made. Looking up an existing conntrack entry upon executing packet received from the userspace is one of them. This patch fixes ovs_ct_find_existing() to invert the packet 5-tuple for the conntrack lookup whenever the packet has already been transformed by conntrack from its input form as evidenced by one of the NAT flags being set in the conntrack state metadata. Fixes: 0575252 ("openvswitch: Interface with NAT.") Signed-off-by: Jarno Rajahalme <[email protected]> Acked-by: Joe Stringer <[email protected]> Acked-by: Pravin B Shelar <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5e17da6 commit 9ff464d

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

net/openvswitch/conntrack.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ ovs_ct_get_info(const struct nf_conntrack_tuple_hash *h)
430430
*/
431431
static struct nf_conn *
432432
ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
433-
u8 l3num, struct sk_buff *skb)
433+
u8 l3num, struct sk_buff *skb, bool natted)
434434
{
435435
struct nf_conntrack_l3proto *l3proto;
436436
struct nf_conntrack_l4proto *l4proto;
@@ -453,13 +453,31 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
453453
return NULL;
454454
}
455455

456+
/* Must invert the tuple if skb has been transformed by NAT. */
457+
if (natted) {
458+
struct nf_conntrack_tuple inverse;
459+
460+
if (!nf_ct_invert_tuple(&inverse, &tuple, l3proto, l4proto)) {
461+
pr_debug("ovs_ct_find_existing: Inversion failed!\n");
462+
return NULL;
463+
}
464+
tuple = inverse;
465+
}
466+
456467
/* look for tuple match */
457468
h = nf_conntrack_find_get(net, zone, &tuple);
458469
if (!h)
459470
return NULL; /* Not found. */
460471

461472
ct = nf_ct_tuplehash_to_ctrack(h);
462473

474+
/* Inverted packet tuple matches the reverse direction conntrack tuple,
475+
* select the other tuplehash to get the right 'ctinfo' bits for this
476+
* packet.
477+
*/
478+
if (natted)
479+
h = &ct->tuplehash[!h->tuple.dst.dir];
480+
463481
nf_ct_set(skb, ct, ovs_ct_get_info(h));
464482
return ct;
465483
}
@@ -482,7 +500,9 @@ static bool skb_nfct_cached(struct net *net,
482500
if (!ct && key->ct.state & OVS_CS_F_TRACKED &&
483501
!(key->ct.state & OVS_CS_F_INVALID) &&
484502
key->ct.zone == info->zone.id)
485-
ct = ovs_ct_find_existing(net, &info->zone, info->family, skb);
503+
ct = ovs_ct_find_existing(net, &info->zone, info->family, skb,
504+
!!(key->ct.state
505+
& OVS_CS_F_NAT_MASK));
486506
if (!ct)
487507
return false;
488508
if (!net_eq(net, read_pnet(&ct->ct_net)))

0 commit comments

Comments
 (0)