]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net/sched: speedup tc_dump_qdisc() when tcm_handle is provided
authorEric Dumazet <edumazet@google.com>
Sun, 3 May 2026 11:45:15 +0000 (11:45 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 5 May 2026 02:32:19 +0000 (19:32 -0700)
"tc qdisc show ... handle xxx" filtering can be done by the kernel.

A followup patch can do the same for tcm_parent.

iproute2/tc needs a small companion patch.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/20260503114515.2460477-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/sched/sch_api.c

index dd0edc9bd4610ec865fc97a81f801a7da020667b..6f7847c5536f16e6754954f0a606581e17257361 100644 (file)
@@ -979,13 +979,17 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
-static bool tc_qdisc_dump_ignore(struct Qdisc *q, bool dump_invisible)
+static bool tc_qdisc_dump_ignore(struct Qdisc *q, bool dump_invisible,
+                                const struct tcmsg *tcm)
 {
        if (q->flags & TCQ_F_BUILTIN)
                return true;
        if ((q->flags & TCQ_F_INVISIBLE) && !dump_invisible)
                return true;
-
+       if (tcm) {
+               if (tcm->tcm_handle && tcm->tcm_handle != q->handle)
+                       return true;
+       }
        return false;
 }
 
@@ -1000,7 +1004,7 @@ static int qdisc_get_notify(struct net *net, struct sk_buff *oskb,
        if (!skb)
                return -ENOBUFS;
 
-       if (!tc_qdisc_dump_ignore(q, false)) {
+       if (!tc_qdisc_dump_ignore(q, false, NULL)) {
                if (tc_fill_qdisc(skb, q, clid, portid, n->nlmsg_seq, 0,
                                  RTM_NEWQDISC, extack) < 0)
                        goto err_out;
@@ -1030,12 +1034,12 @@ static int qdisc_notify(struct net *net, struct sk_buff *oskb,
        if (!skb)
                return -ENOBUFS;
 
-       if (old && !tc_qdisc_dump_ignore(old, false)) {
+       if (old && !tc_qdisc_dump_ignore(old, false, NULL)) {
                if (tc_fill_qdisc(skb, old, clid, portid, n->nlmsg_seq,
                                  0, RTM_DELQDISC, extack) < 0)
                        goto err_out;
        }
-       if (new && !tc_qdisc_dump_ignore(new, false)) {
+       if (new && !tc_qdisc_dump_ignore(new, false, NULL)) {
                if (tc_fill_qdisc(skb, new, clid, portid, n->nlmsg_seq,
                                  old ? NLM_F_REPLACE : 0, RTM_NEWQDISC, extack) < 0)
                        goto err_out;
@@ -1825,21 +1829,24 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb,
                              int *q_idx_p, int s_q_idx, bool recur,
                              bool dump_invisible)
 {
+       const struct nlmsghdr *nlh = cb->nlh;
        int ret = 0, q_idx = *q_idx_p;
+       const struct tcmsg *tcm;
        struct Qdisc *q;
        int b;
 
        if (!root)
                return 0;
 
+       tcm = nlmsg_data(nlh);
        q = root;
        if (q_idx < s_q_idx) {
                q_idx++;
        } else {
-               if (!tc_qdisc_dump_ignore(q, dump_invisible))
+               if (!tc_qdisc_dump_ignore(q, dump_invisible, tcm))
                    ret = tc_fill_qdisc(skb, q, q->parent,
                                        NETLINK_CB(cb->skb).portid,
-                                       cb->nlh->nlmsg_seq, NLM_F_MULTI,
+                                       nlh->nlmsg_seq, NLM_F_MULTI,
                                        RTM_NEWQDISC, NULL);
                if (ret < 0)
                        goto out;
@@ -1860,10 +1867,10 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb,
                        q_idx++;
                        continue;
                }
-               if (!tc_qdisc_dump_ignore(q, dump_invisible))
+               if (!tc_qdisc_dump_ignore(q, dump_invisible, tcm))
                        ret = tc_fill_qdisc(skb, q, q->parent,
                                            NETLINK_CB(cb->skb).portid,
-                                           cb->nlh->nlmsg_seq, NLM_F_MULTI,
+                                           nlh->nlmsg_seq, NLM_F_MULTI,
                                            RTM_NEWQDISC, NULL);
                if (ret < 0)
                        goto out;
@@ -2341,7 +2348,7 @@ static int tc_dump_tclass_qdisc(struct Qdisc *q, struct sk_buff *skb,
 {
        struct qdisc_dump_args arg;
 
-       if (tc_qdisc_dump_ignore(q, false) ||
+       if (tc_qdisc_dump_ignore(q, false, NULL) ||
            *t_p < s_t || !q->ops->cl_ops ||
            (tcm->tcm_parent &&
             TC_H_MAJ(tcm->tcm_parent) != q->handle)) {