net/sched: act_ct: fix miss set mru for ovs after defrag in act_ct
authorwenxu <wenxu@ucloud.cn>
Fri, 31 Jul 2020 02:45:01 +0000 (10:45 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 3 Aug 2020 22:04:48 +0000 (15:04 -0700)
When openvswitch conntrack offload with act_ct action. Fragment packets
defrag in the ingress tc act_ct action and miss the next chain. Then the
packet pass to the openvswitch datapath without the mru. The over
mtu packet will be dropped in output action in openvswitch for over mtu.

"kernel: net2: dropped over-mtu packet: 1528 > 1500"

This patch add mru in the tc_skb_ext for adefrag and miss next chain
situation. And also add mru in the qdisc_skb_cb. The act_ct set the mru
to the qdisc_skb_cb when the packet defrag. And When the chain miss,
The mru is set to tc_skb_ext which can be got by ovs datapath.

Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
Signed-off-by: wenxu <wenxu@ucloud.cn>
Reviewed-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/skbuff.h
include/net/sch_generic.h
net/openvswitch/flow.c
net/sched/act_ct.c
net/sched/cls_api.c

index fa817a105517e1bb67cd3f27bbb02d6605f0482b..3ad65d4ce085ca9cafa3ed706008b38705cbc0e7 100644 (file)
@@ -283,6 +283,7 @@ struct nf_bridge_info {
  */
 struct tc_skb_ext {
        __u32 chain;
+       __u16 mru;
 };
 #endif
 
index c510b03b97513d6be0447c74c44d029d838781b0..d60e7c39d60c72829bde045bd9dcbb6d36d52141 100644 (file)
@@ -384,6 +384,7 @@ struct qdisc_skb_cb {
        };
 #define QDISC_CB_PRIV_LEN 20
        unsigned char           data[QDISC_CB_PRIV_LEN];
+       u16                     mru;
 };
 
 typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv);
@@ -463,7 +464,7 @@ static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
 {
        struct qdisc_skb_cb *qcb;
 
-       BUILD_BUG_ON(sizeof(skb->cb) < offsetof(struct qdisc_skb_cb, data) + sz);
+       BUILD_BUG_ON(sizeof(skb->cb) < sizeof(*qcb));
        BUILD_BUG_ON(sizeof(qcb->data) < sz);
 }
 
index 9d375e74b60738e6961cfde27b16b75110b62f45..03942c30d83e67bc412a4748edd70beedb42dfd3 100644 (file)
@@ -890,6 +890,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
        if (static_branch_unlikely(&tc_recirc_sharing_support)) {
                tc_ext = skb_ext_find(skb, TC_SKB_EXT);
                key->recirc_id = tc_ext ? tc_ext->chain : 0;
+               OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0;
        } else {
                key->recirc_id = 0;
        }
index 97e27946897f57e51c4117b48778c045688dadc6..e6ad42b11835f8d35d2c96604c910985a5f44325 100644 (file)
@@ -706,8 +706,10 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
                if (err && err != -EINPROGRESS)
                        goto out_free;
 
-               if (!err)
+               if (!err) {
                        *defrag = true;
+                       cb.mru = IPCB(skb)->frag_max_size;
+               }
        } else { /* NFPROTO_IPV6 */
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
                enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
@@ -717,8 +719,10 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
                if (err && err != -EINPROGRESS)
                        goto out_free;
 
-               if (!err)
+               if (!err) {
                        *defrag = true;
+                       cb.mru = IP6CB(skb)->frag_max_size;
+               }
 #else
                err = -EOPNOTSUPP;
                goto out_free;
index 0b8623b3b24fa77bec3ba1bbc727c684238e3a6d..41a55c6cbeb8fc862adc6cf1bf90e15edce8acc7 100644 (file)
@@ -1629,6 +1629,7 @@ int tcf_classify_ingress(struct sk_buff *skb,
                if (WARN_ON_ONCE(!ext))
                        return TC_ACT_SHOT;
                ext->chain = last_executed_chain;
+               ext->mru = qdisc_skb_cb(skb)->mru;
        }
 
        return ret;