]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
net: sched: refactor flower walk to iterate over idr
authorVlad Buslov <vladbu@mellanox.com>
Mon, 9 Jul 2018 10:29:11 +0000 (13:29 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sat, 14 Jul 2018 01:24:27 +0000 (18:24 -0700)
Extend struct tcf_walker with additional 'cookie' field. It is intended to
be used by classifier walk implementations to continue iteration directly
from particular filter, instead of iterating 'skip' number of times.

Change flower walk implementation to save filter handle in 'cookie'. Each
time flower walk is called, it looks up filter with saved handle directly
with idr, instead of iterating over filter linked list 'skip' number of
times. This change improves complexity of dumping flower classifier from
quadratic to linearithmic. (assuming idr lookup has logarithmic complexity)

Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Reported-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/pkt_cls.h
net/sched/cls_api.c
net/sched/cls_flower.c

index 2081e4219f813e64ad6a2e9851086e1f8932907a..e4252a176eecaeb112612623b2b968e34e1996f6 100644 (file)
@@ -13,6 +13,7 @@ struct tcf_walker {
        int     stop;
        int     skip;
        int     count;
+       unsigned long cookie;
        int     (*fn)(struct tcf_proto *, void *node, struct tcf_walker *);
 };
 
index 73d9967c37391b21707f18ca9d81de3bdc20c934..c51b1b12450d0a0c33696779e52ff95593eb1696 100644 (file)
@@ -1508,7 +1508,9 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent,
                arg.w.stop = 0;
                arg.w.skip = cb->args[1] - 1;
                arg.w.count = 0;
+               arg.w.cookie = cb->args[2];
                tp->ops->walk(tp, &arg.w);
+               cb->args[2] = arg.w.cookie;
                cb->args[1] = arg.w.count + 1;
                if (arg.w.stop)
                        return false;
index 8b2474293db190f44c6644b4f7f837e8e614bb05..c53fdd411f90def307e88ee22098313806f51e9e 100644 (file)
@@ -1099,19 +1099,17 @@ static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 {
        struct cls_fl_head *head = rtnl_dereference(tp->root);
        struct cls_fl_filter *f;
-       struct fl_flow_mask *mask;
 
-       list_for_each_entry_rcu(mask, &head->masks, list) {
-               list_for_each_entry_rcu(f, &mask->filters, list) {
-                       if (arg->count < arg->skip)
-                               goto skip;
-                       if (arg->fn(tp, f, arg) < 0) {
-                               arg->stop = 1;
-                               break;
-                       }
-skip:
-                       arg->count++;
+       arg->count = arg->skip;
+
+       while ((f = idr_get_next_ul(&head->handle_idr,
+                                   &arg->cookie)) != NULL) {
+               if (arg->fn(tp, f, arg) < 0) {
+                       arg->stop = 1;
+                       break;
                }
+               arg->cookie = f->handle + 1;
+               arg->count++;
        }
 }