提交 e82bf96f 编写于 作者: I Ilya Maximets 提交者: Zheng Zengkai

net: openvswitch: fix misuse of the cached connection on tuple changes

stable inclusion
from stable-v5.10.124
commit e1513a714de67dd7d2fcd6cfe2ebd59961fe80b1
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I5L6E7

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=e1513a714de67dd7d2fcd6cfe2ebd59961fe80b1

--------------------------------

commit 2061ecfd upstream.

If packet headers changed, the cached nfct is no longer relevant
for the packet and attempt to re-use it leads to the incorrect packet
classification.

This issue is causing broken connectivity in OpenStack deployments
with OVS/OVN due to hairpin traffic being unexpectedly dropped.

The setup has datapath flows with several conntrack actions and tuple
changes between them:

  actions:ct(commit,zone=8,mark=0/0x1,nat(src)),
          set(eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:06)),
          set(ipv4(src=172.18.2.10,dst=192.168.100.6,ttl=62)),
          ct(zone=8),recirc(0x4)

After the first ct() action the packet headers are almost fully
re-written.  The next ct() tries to re-use the existing nfct entry
and marks the packet as invalid, so it gets dropped later in the
pipeline.

Clearing the cached conntrack entry whenever packet tuple is changed
to avoid the issue.

The flow key should not be cleared though, because we should still
be able to match on the ct_state if the recirculation happens after
the tuple change but before the next ct() action.

Cc: stable@vger.kernel.org
Fixes: 7f8a436e ("openvswitch: Add conntrack action")
Reported-by: NFrode Nordahl <frode.nordahl@canonical.com>
Link: https://mail.openvswitch.org/pipermail/ovs-discuss/2022-May/051829.html
Link: https://bugs.launchpad.net/ubuntu/+source/ovn/+bug/1967856Signed-off-by: NIlya Maximets <i.maximets@ovn.org>
Link: https://lore.kernel.org/r/20220606221140.488984-1-i.maximets@ovn.orgSigned-off-by: NJakub Kicinski <kuba@kernel.org>
[Backport to 5.10: minor rebase in ovs_ct_clear function.
 This version also applicable to and tested on 5.4 and 4.19.]
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: NWei Li <liwei391@huawei.com>
上级 f1d500aa
...@@ -372,6 +372,7 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh, ...@@ -372,6 +372,7 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
update_ip_l4_checksum(skb, nh, *addr, new_addr); update_ip_l4_checksum(skb, nh, *addr, new_addr);
csum_replace4(&nh->check, *addr, new_addr); csum_replace4(&nh->check, *addr, new_addr);
skb_clear_hash(skb); skb_clear_hash(skb);
ovs_ct_clear(skb, NULL);
*addr = new_addr; *addr = new_addr;
} }
...@@ -419,6 +420,7 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto, ...@@ -419,6 +420,7 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto,
update_ipv6_checksum(skb, l4_proto, addr, new_addr); update_ipv6_checksum(skb, l4_proto, addr, new_addr);
skb_clear_hash(skb); skb_clear_hash(skb);
ovs_ct_clear(skb, NULL);
memcpy(addr, new_addr, sizeof(__be32[4])); memcpy(addr, new_addr, sizeof(__be32[4]));
} }
...@@ -659,6 +661,7 @@ static int set_nsh(struct sk_buff *skb, struct sw_flow_key *flow_key, ...@@ -659,6 +661,7 @@ static int set_nsh(struct sk_buff *skb, struct sw_flow_key *flow_key,
static void set_tp_port(struct sk_buff *skb, __be16 *port, static void set_tp_port(struct sk_buff *skb, __be16 *port,
__be16 new_port, __sum16 *check) __be16 new_port, __sum16 *check)
{ {
ovs_ct_clear(skb, NULL);
inet_proto_csum_replace2(check, skb, *port, new_port, false); inet_proto_csum_replace2(check, skb, *port, new_port, false);
*port = new_port; *port = new_port;
} }
...@@ -698,6 +701,7 @@ static int set_udp(struct sk_buff *skb, struct sw_flow_key *flow_key, ...@@ -698,6 +701,7 @@ static int set_udp(struct sk_buff *skb, struct sw_flow_key *flow_key,
uh->dest = dst; uh->dest = dst;
flow_key->tp.src = src; flow_key->tp.src = src;
flow_key->tp.dst = dst; flow_key->tp.dst = dst;
ovs_ct_clear(skb, NULL);
} }
skb_clear_hash(skb); skb_clear_hash(skb);
...@@ -760,6 +764,8 @@ static int set_sctp(struct sk_buff *skb, struct sw_flow_key *flow_key, ...@@ -760,6 +764,8 @@ static int set_sctp(struct sk_buff *skb, struct sw_flow_key *flow_key,
sh->checksum = old_csum ^ old_correct_csum ^ new_csum; sh->checksum = old_csum ^ old_correct_csum ^ new_csum;
skb_clear_hash(skb); skb_clear_hash(skb);
ovs_ct_clear(skb, NULL);
flow_key->tp.src = sh->source; flow_key->tp.src = sh->source;
flow_key->tp.dst = sh->dest; flow_key->tp.dst = sh->dest;
......
...@@ -1324,7 +1324,8 @@ int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key) ...@@ -1324,7 +1324,8 @@ int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key)
if (skb_nfct(skb)) { if (skb_nfct(skb)) {
nf_conntrack_put(skb_nfct(skb)); nf_conntrack_put(skb_nfct(skb));
nf_ct_set(skb, NULL, IP_CT_UNTRACKED); nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
ovs_ct_fill_key(skb, key); if (key)
ovs_ct_fill_key(skb, key);
} }
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册