Skip to content

Commit ae372cb

Browse files
wenxudavem330
authored andcommitted
net/sched: act_ct: fix restore the qdisc_skb_cb after defrag
The fragment packets do defrag in tcf_ct_handle_fragments will clear the skb->cb which make the qdisc_skb_cb clear too. So the qdsic_skb_cb should be store before defrag and restore after that. It also update the pkt_len after all the fragments finish the defrag to one packet and make the following actions counter correct. Fixes: b57dc7c ("net/sched: Introduce action ct") Signed-off-by: wenxu <wenxu@ucloud.cn> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 1e8fd3a commit ae372cb

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

net/sched/act_ct.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,10 @@ static int tcf_ct_ipv6_is_fragment(struct sk_buff *skb, bool *frag)
673673
}
674674

675675
static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
676-
u8 family, u16 zone)
676+
u8 family, u16 zone, bool *defrag)
677677
{
678678
enum ip_conntrack_info ctinfo;
679+
struct qdisc_skb_cb cb;
679680
struct nf_conn *ct;
680681
int err = 0;
681682
bool frag;
@@ -693,6 +694,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
693694
return err;
694695

695696
skb_get(skb);
697+
cb = *qdisc_skb_cb(skb);
696698

697699
if (family == NFPROTO_IPV4) {
698700
enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone;
@@ -703,6 +705,9 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
703705
local_bh_enable();
704706
if (err && err != -EINPROGRESS)
705707
goto out_free;
708+
709+
if (!err)
710+
*defrag = true;
706711
} else { /* NFPROTO_IPV6 */
707712
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
708713
enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
@@ -711,12 +716,16 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
711716
err = nf_ct_frag6_gather(net, skb, user);
712717
if (err && err != -EINPROGRESS)
713718
goto out_free;
719+
720+
if (!err)
721+
*defrag = true;
714722
#else
715723
err = -EOPNOTSUPP;
716724
goto out_free;
717725
#endif
718726
}
719727

728+
*qdisc_skb_cb(skb) = cb;
720729
skb_clear_hash(skb);
721730
skb->ignore_df = 1;
722731
return err;
@@ -914,6 +923,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
914923
int nh_ofs, err, retval;
915924
struct tcf_ct_params *p;
916925
bool skip_add = false;
926+
bool defrag = false;
917927
struct nf_conn *ct;
918928
u8 family;
919929

@@ -946,7 +956,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
946956
*/
947957
nh_ofs = skb_network_offset(skb);
948958
skb_pull_rcsum(skb, nh_ofs);
949-
err = tcf_ct_handle_fragments(net, skb, family, p->zone);
959+
err = tcf_ct_handle_fragments(net, skb, family, p->zone, &defrag);
950960
if (err == -EINPROGRESS) {
951961
retval = TC_ACT_STOLEN;
952962
goto out;
@@ -1014,6 +1024,8 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
10141024

10151025
out:
10161026
tcf_action_update_bstats(&c->common, skb);
1027+
if (defrag)
1028+
qdisc_skb_cb(skb)->pkt_len = skb->len;
10171029
return retval;
10181030

10191031
drop:

0 commit comments

Comments
 (0)