Commit 9ff464db authored by Jarno Rajahalme's avatar Jarno Rajahalme Committed by David S. Miller

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: 05752523 ("openvswitch: Interface with NAT.")
Signed-off-by: default avatarJarno Rajahalme <jarno@ovn.org>
Acked-by: default avatarJoe Stringer <joe@ovn.org>
Acked-by: default avatarPravin B Shelar <pshelar@ovn.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5e17da63
...@@ -430,7 +430,7 @@ ovs_ct_get_info(const struct nf_conntrack_tuple_hash *h) ...@@ -430,7 +430,7 @@ ovs_ct_get_info(const struct nf_conntrack_tuple_hash *h)
*/ */
static struct nf_conn * static struct nf_conn *
ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone, ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
u8 l3num, struct sk_buff *skb) u8 l3num, struct sk_buff *skb, bool natted)
{ {
struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l3proto *l3proto;
struct nf_conntrack_l4proto *l4proto; struct nf_conntrack_l4proto *l4proto;
...@@ -453,6 +453,17 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone, ...@@ -453,6 +453,17 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
return NULL; return NULL;
} }
/* Must invert the tuple if skb has been transformed by NAT. */
if (natted) {
struct nf_conntrack_tuple inverse;
if (!nf_ct_invert_tuple(&inverse, &tuple, l3proto, l4proto)) {
pr_debug("ovs_ct_find_existing: Inversion failed!\n");
return NULL;
}
tuple = inverse;
}
/* look for tuple match */ /* look for tuple match */
h = nf_conntrack_find_get(net, zone, &tuple); h = nf_conntrack_find_get(net, zone, &tuple);
if (!h) if (!h)
...@@ -460,6 +471,13 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone, ...@@ -460,6 +471,13 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
ct = nf_ct_tuplehash_to_ctrack(h); ct = nf_ct_tuplehash_to_ctrack(h);
/* Inverted packet tuple matches the reverse direction conntrack tuple,
* select the other tuplehash to get the right 'ctinfo' bits for this
* packet.
*/
if (natted)
h = &ct->tuplehash[!h->tuple.dst.dir];
nf_ct_set(skb, ct, ovs_ct_get_info(h)); nf_ct_set(skb, ct, ovs_ct_get_info(h));
return ct; return ct;
} }
...@@ -482,7 +500,9 @@ static bool skb_nfct_cached(struct net *net, ...@@ -482,7 +500,9 @@ static bool skb_nfct_cached(struct net *net,
if (!ct && key->ct.state & OVS_CS_F_TRACKED && if (!ct && key->ct.state & OVS_CS_F_TRACKED &&
!(key->ct.state & OVS_CS_F_INVALID) && !(key->ct.state & OVS_CS_F_INVALID) &&
key->ct.zone == info->zone.id) key->ct.zone == info->zone.id)
ct = ovs_ct_find_existing(net, &info->zone, info->family, skb); ct = ovs_ct_find_existing(net, &info->zone, info->family, skb,
!!(key->ct.state
& OVS_CS_F_NAT_MASK));
if (!ct) if (!ct)
return false; return false;
if (!net_eq(net, read_pnet(&ct->ct_net))) if (!net_eq(net, read_pnet(&ct->ct_net)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment