mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
net: sched: refactor flower walk to iterate over idr
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>
This commit is contained in:
parent
c921c2077b
commit
01683a1469
@ -13,6 +13,7 @@ struct tcf_walker {
|
|||||||
int stop;
|
int stop;
|
||||||
int skip;
|
int skip;
|
||||||
int count;
|
int count;
|
||||||
|
unsigned long cookie;
|
||||||
int (*fn)(struct tcf_proto *, void *node, struct tcf_walker *);
|
int (*fn)(struct tcf_proto *, void *node, struct tcf_walker *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1508,7 +1508,9 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent,
|
|||||||
arg.w.stop = 0;
|
arg.w.stop = 0;
|
||||||
arg.w.skip = cb->args[1] - 1;
|
arg.w.skip = cb->args[1] - 1;
|
||||||
arg.w.count = 0;
|
arg.w.count = 0;
|
||||||
|
arg.w.cookie = cb->args[2];
|
||||||
tp->ops->walk(tp, &arg.w);
|
tp->ops->walk(tp, &arg.w);
|
||||||
|
cb->args[2] = arg.w.cookie;
|
||||||
cb->args[1] = arg.w.count + 1;
|
cb->args[1] = arg.w.count + 1;
|
||||||
if (arg.w.stop)
|
if (arg.w.stop)
|
||||||
return false;
|
return false;
|
||||||
|
@ -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_head *head = rtnl_dereference(tp->root);
|
||||||
struct cls_fl_filter *f;
|
struct cls_fl_filter *f;
|
||||||
struct fl_flow_mask *mask;
|
|
||||||
|
|
||||||
list_for_each_entry_rcu(mask, &head->masks, list) {
|
arg->count = arg->skip;
|
||||||
list_for_each_entry_rcu(f, &mask->filters, list) {
|
|
||||||
if (arg->count < arg->skip)
|
while ((f = idr_get_next_ul(&head->handle_idr,
|
||||||
goto skip;
|
&arg->cookie)) != NULL) {
|
||||||
if (arg->fn(tp, f, arg) < 0) {
|
if (arg->fn(tp, f, arg) < 0) {
|
||||||
arg->stop = 1;
|
arg->stop = 1;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
skip:
|
|
||||||
arg->count++;
|
|
||||||
}
|
}
|
||||||
|
arg->cookie = f->handle + 1;
|
||||||
|
arg->count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user