Skip to content

Commit

Permalink
net: sched: refactor flower walk to iterate over idr
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vlad Buslov authored and David S. Miller committed Jul 14, 2018
1 parent c921c20 commit 01683a1
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 11 deletions.
1 change: 1 addition & 0 deletions include/net/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
};

Expand Down
2 changes: 2 additions & 0 deletions net/sched/cls_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
20 changes: 9 additions & 11 deletions net/sched/cls_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
}
}

Expand Down

0 comments on commit 01683a1

Please sign in to comment.