net/sched: store the last executed chain also for clsact egress
authorDavide Caratti <dcaratti@redhat.com>
Wed, 28 Jul 2021 18:08:00 +0000 (20:08 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 29 Jul 2021 21:17:37 +0000 (22:17 +0100)
currently, only 'ingress' and 'clsact ingress' qdiscs store the tc 'chain
id' in the skb extension. However, userspace programs (like ovs) are able
to setup egress rules, and datapath gets confused in case it doesn't find
the 'chain id' for a packet that's "recirculated" by tc.
Change tcf_classify() to have the same semantic as tcf_classify_ingress()
so that a single function can be called in ingress / egress, using the tc
ingress / egress block respectively.

Suggested-by: Alaa Hleilel <alaa@nvidia.com>
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
18 files changed:
include/net/pkt_cls.h
net/core/dev.c
net/sched/cls_api.c
net/sched/sch_atm.c
net/sched/sch_cake.c
net/sched/sch_cbq.c
net/sched/sch_drr.c
net/sched/sch_dsmark.c
net/sched/sch_ets.c
net/sched/sch_fq_codel.c
net/sched/sch_fq_pie.c
net/sched/sch_hfsc.c
net/sched/sch_htb.c
net/sched/sch_multiq.c
net/sched/sch_prio.c
net/sched/sch_qfq.c
net/sched/sch_sfb.c
net/sched/sch_sfq.c

index ec7823921bd26ec7e33bfef5b849c347414228fa..dc28fcb6f0a279d2ca7be08a0e1e90ebb08fa64c 100644 (file)
@@ -76,12 +76,10 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
        return block->q;
 }
 
-int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
-                struct tcf_result *res, bool compat_mode);
-int tcf_classify_ingress(struct sk_buff *skb,
-                        const struct tcf_block *ingress_block,
-                        const struct tcf_proto *tp, struct tcf_result *res,
-                        bool compat_mode);
+int tcf_classify(struct sk_buff *skb,
+                const struct tcf_block *block,
+                const struct tcf_proto *tp, struct tcf_result *res,
+                bool compat_mode);
 
 #else
 static inline bool tcf_block_shared(struct tcf_block *block)
@@ -138,20 +136,14 @@ void tc_setup_cb_block_unregister(struct tcf_block *block, flow_setup_cb_t *cb,
 {
 }
 
-static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+static inline int tcf_classify(struct sk_buff *skb,
+                              const struct tcf_block *block,
+                              const struct tcf_proto *tp,
                               struct tcf_result *res, bool compat_mode)
 {
        return TC_ACT_UNSPEC;
 }
 
-static inline int tcf_classify_ingress(struct sk_buff *skb,
-                                      const struct tcf_block *ingress_block,
-                                      const struct tcf_proto *tp,
-                                      struct tcf_result *res, bool compat_mode)
-{
-       return TC_ACT_UNSPEC;
-}
-
 #endif
 
 static inline unsigned long
index dcc87fcd64babe417875f57c1dce781fc1856941..b51e41d0a7fe226360805815bc772eed916362e1 100644 (file)
@@ -4012,7 +4012,7 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
        qdisc_skb_cb(skb)->post_ct = false;
        mini_qdisc_bstats_cpu_update(miniq, skb);
 
-       switch (tcf_classify(skb, miniq->filter_list, &cl_res, false)) {
+       switch (tcf_classify(skb, miniq->block, miniq->filter_list, &cl_res, false)) {
        case TC_ACT_OK:
        case TC_ACT_RECLASSIFY:
                skb->tc_index = TC_H_MIN(cl_res.classid);
@@ -5164,8 +5164,7 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
        skb->tc_at_ingress = 1;
        mini_qdisc_bstats_cpu_update(miniq, skb);
 
-       switch (tcf_classify_ingress(skb, miniq->block, miniq->filter_list,
-                                    &cl_res, false)) {
+       switch (tcf_classify(skb, miniq->block, miniq->filter_list, &cl_res, false)) {
        case TC_ACT_OK:
        case TC_ACT_RECLASSIFY:
                skb->tc_index = TC_H_MIN(cl_res.classid);
index 1167cd0be179e2cdeb79bb86e4e6ba8cfe81081a..7be5b9d2aead08752bf50275bda82fe29d6dd89d 100644 (file)
@@ -1577,20 +1577,10 @@ reset:
 #endif
 }
 
-int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
+int tcf_classify(struct sk_buff *skb,
+                const struct tcf_block *block,
+                const struct tcf_proto *tp,
                 struct tcf_result *res, bool compat_mode)
-{
-       u32 last_executed_chain = 0;
-
-       return __tcf_classify(skb, tp, tp, res, compat_mode,
-                             &last_executed_chain);
-}
-EXPORT_SYMBOL(tcf_classify);
-
-int tcf_classify_ingress(struct sk_buff *skb,
-                        const struct tcf_block *ingress_block,
-                        const struct tcf_proto *tp,
-                        struct tcf_result *res, bool compat_mode)
 {
 #if !IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
        u32 last_executed_chain = 0;
@@ -1603,20 +1593,22 @@ int tcf_classify_ingress(struct sk_buff *skb,
        struct tc_skb_ext *ext;
        int ret;
 
-       ext = skb_ext_find(skb, TC_SKB_EXT);
+       if (block) {
+               ext = skb_ext_find(skb, TC_SKB_EXT);
 
-       if (ext && ext->chain) {
-               struct tcf_chain *fchain;
+               if (ext && ext->chain) {
+                       struct tcf_chain *fchain;
 
-               fchain = tcf_chain_lookup_rcu(ingress_block, ext->chain);
-               if (!fchain)
-                       return TC_ACT_SHOT;
+                       fchain = tcf_chain_lookup_rcu(block, ext->chain);
+                       if (!fchain)
+                               return TC_ACT_SHOT;
 
-               /* Consume, so cloned/redirect skbs won't inherit ext */
-               skb_ext_del(skb, TC_SKB_EXT);
+                       /* Consume, so cloned/redirect skbs won't inherit ext */
+                       skb_ext_del(skb, TC_SKB_EXT);
 
-               tp = rcu_dereference_bh(fchain->filter_chain);
-               last_executed_chain = fchain->index;
+                       tp = rcu_dereference_bh(fchain->filter_chain);
+                       last_executed_chain = fchain->index;
+               }
        }
 
        ret = __tcf_classify(skb, tp, orig_tp, res, compat_mode,
@@ -1635,7 +1627,7 @@ int tcf_classify_ingress(struct sk_buff *skb,
        return ret;
 #endif
 }
-EXPORT_SYMBOL(tcf_classify_ingress);
+EXPORT_SYMBOL(tcf_classify);
 
 struct tcf_chain_info {
        struct tcf_proto __rcu **pprev;
@@ -3825,7 +3817,7 @@ struct sk_buff *tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, stru
 
        fl = rcu_dereference_bh(qe->filter_chain);
 
-       switch (tcf_classify(skb, fl, &cl_res, false)) {
+       switch (tcf_classify(skb, NULL, fl, &cl_res, false)) {
        case TC_ACT_SHOT:
                qdisc_qstats_drop(sch);
                __qdisc_drop(skb, to_free);
index d0c9a57398fc2619aae98c452fd643330e508332..7d8518176b45a6e5a02535649c3ade4d3288576b 100644 (file)
@@ -394,7 +394,7 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                list_for_each_entry(flow, &p->flows, list) {
                        fl = rcu_dereference_bh(flow->filter_list);
                        if (fl) {
-                               result = tcf_classify(skb, fl, &res, true);
+                               result = tcf_classify(skb, NULL, fl, &res, true);
                                if (result < 0)
                                        continue;
                                flow = (struct atm_flow_data *)res.class;
index 951542843cab282f4841e2bb7a5bc6afc5f33ee8..ecc5c4d937792145ba665e593f9ecfd604c0d303 100644 (file)
@@ -1665,7 +1665,7 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t,
                goto hash;
 
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
-       result = tcf_classify(skb, filter, &res, false);
+       result = tcf_classify(skb, NULL, filter, &res, false);
 
        if (result >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
index b79a7e27bb3157363ff8403950549c9ef09087de..2dabaffd39d05ce460e1c3e886b2b6c9172e45ce 100644 (file)
@@ -228,7 +228,7 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
                /*
                 * Step 2+n. Apply classifier.
                 */
-               result = tcf_classify(skb, fl, &res, true);
+               result = tcf_classify(skb, NULL, fl, &res, true);
                if (!fl || result < 0)
                        goto fallback;
 
index fc1e47069593679927bccdc4e966d96e89de05d3..642cd179b7a75a2d6621910e75c11ca11c13d9ea 100644 (file)
@@ -317,7 +317,7 @@ static struct drr_class *drr_classify(struct sk_buff *skb, struct Qdisc *sch,
 
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
        fl = rcu_dereference_bh(q->filter_list);
-       result = tcf_classify(skb, fl, &res, false);
+       result = tcf_classify(skb, NULL, fl, &res, false);
        if (result >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {
index d320bcfb2da2c9aac72c546750dac1586860df25..4c100d10526996c8d26adc22666e0f5f4ecad148 100644 (file)
@@ -242,7 +242,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        else {
                struct tcf_result res;
                struct tcf_proto *fl = rcu_dereference_bh(p->filter_list);
-               int result = tcf_classify(skb, fl, &res, false);
+               int result = tcf_classify(skb, NULL, fl, &res, false);
 
                pr_debug("result %d class 0x%04x\n", result, res.classid);
 
index c1e84d1eeaba8fc2181c9dba3bfad78b6f981097..925924fab1ab91107bd452ab901c0c3e2ab00601 100644 (file)
@@ -390,7 +390,7 @@ static struct ets_class *ets_classify(struct sk_buff *skb, struct Qdisc *sch,
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
        if (TC_H_MAJ(skb->priority) != sch->handle) {
                fl = rcu_dereference_bh(q->filter_list);
-               err = tcf_classify(skb, fl, &res, false);
+               err = tcf_classify(skb, NULL, fl, &res, false);
 #ifdef CONFIG_NET_CLS_ACT
                switch (err) {
                case TC_ACT_STOLEN:
index bbd5f8753600624f2eba9a91d2efa21333f4221f..c4afdd026f5197daf78e942731dfa1eb18a5f777 100644 (file)
@@ -91,7 +91,7 @@ static unsigned int fq_codel_classify(struct sk_buff *skb, struct Qdisc *sch,
                return fq_codel_hash(q, skb) + 1;
 
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
-       result = tcf_classify(skb, filter, &res, false);
+       result = tcf_classify(skb, NULL, filter, &res, false);
        if (result >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {
index cac684952edc55712197b307536fdc9ad3c7e064..830f3559f727ad471b595b2f5b04788827da89b0 100644 (file)
@@ -94,7 +94,7 @@ static unsigned int fq_pie_classify(struct sk_buff *skb, struct Qdisc *sch,
                return fq_pie_hash(q, skb) + 1;
 
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
-       result = tcf_classify(skb, filter, &res, false);
+       result = tcf_classify(skb, NULL, filter, &res, false);
        if (result >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {
index bf0034c66e359674322845b7b09959c047a6d248..b7ac30cca035d10799d6edcb5a275d1ab7dc4a73 100644 (file)
@@ -1130,7 +1130,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
        head = &q->root;
        tcf = rcu_dereference_bh(q->root.filter_list);
-       while (tcf && (result = tcf_classify(skb, tcf, &res, false)) >= 0) {
+       while (tcf && (result = tcf_classify(skb, NULL, tcf, &res, false)) >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {
                case TC_ACT_QUEUED:
index 5f7ac27a526493cf1eab053299d37cbfdeb34d26..81ea8332547a0777efe6a956adebeab930f480bd 100644 (file)
@@ -238,7 +238,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
        }
 
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
-       while (tcf && (result = tcf_classify(skb, tcf, &res, false)) >= 0) {
+       while (tcf && (result = tcf_classify(skb, NULL, tcf, &res, false)) >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {
                case TC_ACT_QUEUED:
index 5c27b4270b90894dcfdd5c9621a0db8cf13582c3..e282e7382117a54cc6147d3e427f8e5c1fa5bf5c 100644 (file)
@@ -36,7 +36,7 @@ multiq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
        int err;
 
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
-       err = tcf_classify(skb, fl, &res, false);
+       err = tcf_classify(skb, NULL, fl, &res, false);
 #ifdef CONFIG_NET_CLS_ACT
        switch (err) {
        case TC_ACT_STOLEN:
index 3eabb871a1d522ad72b903ad43666ce801220c2d..03fdf31ccb6aff66ba3afbc85b8dcba21c70ae03 100644 (file)
@@ -39,7 +39,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
        if (TC_H_MAJ(skb->priority) != sch->handle) {
                fl = rcu_dereference_bh(q->filter_list);
-               err = tcf_classify(skb, fl, &res, false);
+               err = tcf_classify(skb, NULL, fl, &res, false);
 #ifdef CONFIG_NET_CLS_ACT
                switch (err) {
                case TC_ACT_STOLEN:
index b692a0de1ad5e5af8c630d7ddf68be4e62645c5b..58a9d42b52b8ffd7a1dc4fc3d1d36d4a9372cf40 100644 (file)
@@ -690,7 +690,7 @@ static struct qfq_class *qfq_classify(struct sk_buff *skb, struct Qdisc *sch,
 
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
        fl = rcu_dereference_bh(q->filter_list);
-       result = tcf_classify(skb, fl, &res, false);
+       result = tcf_classify(skb, NULL, fl, &res, false);
        if (result >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {
index dde829d4b9f8349147a14b3366e1b420df815a9c..3d061a13d7ed2bd5294c3eddd1bd1bcdaafda464 100644 (file)
@@ -257,7 +257,7 @@ static bool sfb_classify(struct sk_buff *skb, struct tcf_proto *fl,
        struct tcf_result res;
        int result;
 
-       result = tcf_classify(skb, fl, &res, false);
+       result = tcf_classify(skb, NULL, fl, &res, false);
        if (result >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {
index 066754a18569ba8f8a295f14049b06dfbeb4c7c6..f8e569f79f1367563bf92793dbd2a9c0a4ce957b 100644 (file)
@@ -178,7 +178,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,
                return sfq_hash(q, skb) + 1;
 
        *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
-       result = tcf_classify(skb, fl, &res, false);
+       result = tcf_classify(skb, NULL, fl, &res, false);
        if (result >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {