mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-05 13:51:52 +00:00
net-sched: cls_flow: add perturbation support
Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0c4c8cae44
commit
72d9794f44
2 changed files with 44 additions and 9 deletions
|
@ -374,6 +374,7 @@ enum
|
||||||
TCA_FLOW_ACT,
|
TCA_FLOW_ACT,
|
||||||
TCA_FLOW_POLICE,
|
TCA_FLOW_POLICE,
|
||||||
TCA_FLOW_EMATCHES,
|
TCA_FLOW_EMATCHES,
|
||||||
|
TCA_FLOW_PERTURB,
|
||||||
__TCA_FLOW_MAX
|
__TCA_FLOW_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,8 @@ struct flow_filter {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct tcf_exts exts;
|
struct tcf_exts exts;
|
||||||
struct tcf_ematch_tree ematches;
|
struct tcf_ematch_tree ematches;
|
||||||
|
struct timer_list perturb_timer;
|
||||||
|
u32 perturb_period;
|
||||||
u32 handle;
|
u32 handle;
|
||||||
|
|
||||||
u32 nkeys;
|
u32 nkeys;
|
||||||
|
@ -47,11 +49,9 @@ struct flow_filter {
|
||||||
u32 addend;
|
u32 addend;
|
||||||
u32 divisor;
|
u32 divisor;
|
||||||
u32 baseclass;
|
u32 baseclass;
|
||||||
|
u32 hashrnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
static u32 flow_hashrnd __read_mostly;
|
|
||||||
static int flow_hashrnd_initted __read_mostly;
|
|
||||||
|
|
||||||
static const struct tcf_ext_map flow_ext_map = {
|
static const struct tcf_ext_map flow_ext_map = {
|
||||||
.action = TCA_FLOW_ACT,
|
.action = TCA_FLOW_ACT,
|
||||||
.police = TCA_FLOW_POLICE,
|
.police = TCA_FLOW_POLICE,
|
||||||
|
@ -348,7 +348,7 @@ static int flow_classify(struct sk_buff *skb, struct tcf_proto *tp,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->mode == FLOW_MODE_HASH)
|
if (f->mode == FLOW_MODE_HASH)
|
||||||
classid = jhash2(keys, f->nkeys, flow_hashrnd);
|
classid = jhash2(keys, f->nkeys, f->hashrnd);
|
||||||
else {
|
else {
|
||||||
classid = keys[0];
|
classid = keys[0];
|
||||||
classid = (classid & f->mask) ^ f->xor;
|
classid = (classid & f->mask) ^ f->xor;
|
||||||
|
@ -369,6 +369,15 @@ static int flow_classify(struct sk_buff *skb, struct tcf_proto *tp,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void flow_perturbation(unsigned long arg)
|
||||||
|
{
|
||||||
|
struct flow_filter *f = (struct flow_filter *)arg;
|
||||||
|
|
||||||
|
get_random_bytes(&f->hashrnd, 4);
|
||||||
|
if (f->perturb_period)
|
||||||
|
mod_timer(&f->perturb_timer, jiffies + f->perturb_period);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = {
|
static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = {
|
||||||
[TCA_FLOW_KEYS] = { .type = NLA_U32 },
|
[TCA_FLOW_KEYS] = { .type = NLA_U32 },
|
||||||
[TCA_FLOW_MODE] = { .type = NLA_U32 },
|
[TCA_FLOW_MODE] = { .type = NLA_U32 },
|
||||||
|
@ -381,6 +390,7 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = {
|
||||||
[TCA_FLOW_ACT] = { .type = NLA_NESTED },
|
[TCA_FLOW_ACT] = { .type = NLA_NESTED },
|
||||||
[TCA_FLOW_POLICE] = { .type = NLA_NESTED },
|
[TCA_FLOW_POLICE] = { .type = NLA_NESTED },
|
||||||
[TCA_FLOW_EMATCHES] = { .type = NLA_NESTED },
|
[TCA_FLOW_EMATCHES] = { .type = NLA_NESTED },
|
||||||
|
[TCA_FLOW_PERTURB] = { .type = NLA_U32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int flow_change(struct tcf_proto *tp, unsigned long base,
|
static int flow_change(struct tcf_proto *tp, unsigned long base,
|
||||||
|
@ -394,6 +404,7 @@ static int flow_change(struct tcf_proto *tp, unsigned long base,
|
||||||
struct tcf_exts e;
|
struct tcf_exts e;
|
||||||
struct tcf_ematch_tree t;
|
struct tcf_ematch_tree t;
|
||||||
unsigned int nkeys = 0;
|
unsigned int nkeys = 0;
|
||||||
|
unsigned int perturb_period = 0;
|
||||||
u32 baseclass = 0;
|
u32 baseclass = 0;
|
||||||
u32 keymask = 0;
|
u32 keymask = 0;
|
||||||
u32 mode;
|
u32 mode;
|
||||||
|
@ -442,6 +453,14 @@ static int flow_change(struct tcf_proto *tp, unsigned long base,
|
||||||
mode = nla_get_u32(tb[TCA_FLOW_MODE]);
|
mode = nla_get_u32(tb[TCA_FLOW_MODE]);
|
||||||
if (mode != FLOW_MODE_HASH && nkeys > 1)
|
if (mode != FLOW_MODE_HASH && nkeys > 1)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
|
if (mode == FLOW_MODE_HASH)
|
||||||
|
perturb_period = f->perturb_period;
|
||||||
|
if (tb[TCA_FLOW_PERTURB]) {
|
||||||
|
if (mode != FLOW_MODE_HASH)
|
||||||
|
goto err2;
|
||||||
|
perturb_period = nla_get_u32(tb[TCA_FLOW_PERTURB]) * HZ;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
if (!handle)
|
if (!handle)
|
||||||
|
@ -455,6 +474,12 @@ static int flow_change(struct tcf_proto *tp, unsigned long base,
|
||||||
if (mode != FLOW_MODE_HASH && nkeys > 1)
|
if (mode != FLOW_MODE_HASH && nkeys > 1)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
|
if (tb[TCA_FLOW_PERTURB]) {
|
||||||
|
if (mode != FLOW_MODE_HASH)
|
||||||
|
goto err2;
|
||||||
|
perturb_period = nla_get_u32(tb[TCA_FLOW_PERTURB]) * HZ;
|
||||||
|
}
|
||||||
|
|
||||||
if (TC_H_MAJ(baseclass) == 0)
|
if (TC_H_MAJ(baseclass) == 0)
|
||||||
baseclass = TC_H_MAKE(tp->q->handle, baseclass);
|
baseclass = TC_H_MAKE(tp->q->handle, baseclass);
|
||||||
if (TC_H_MIN(baseclass) == 0)
|
if (TC_H_MIN(baseclass) == 0)
|
||||||
|
@ -467,6 +492,11 @@ static int flow_change(struct tcf_proto *tp, unsigned long base,
|
||||||
|
|
||||||
f->handle = handle;
|
f->handle = handle;
|
||||||
f->mask = ~0U;
|
f->mask = ~0U;
|
||||||
|
|
||||||
|
get_random_bytes(&f->hashrnd, 4);
|
||||||
|
f->perturb_timer.function = flow_perturbation;
|
||||||
|
f->perturb_timer.data = (unsigned long)f;
|
||||||
|
init_timer_deferrable(&f->perturb_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcf_exts_change(tp, &f->exts, &e);
|
tcf_exts_change(tp, &f->exts, &e);
|
||||||
|
@ -495,6 +525,11 @@ static int flow_change(struct tcf_proto *tp, unsigned long base,
|
||||||
if (baseclass)
|
if (baseclass)
|
||||||
f->baseclass = baseclass;
|
f->baseclass = baseclass;
|
||||||
|
|
||||||
|
f->perturb_period = perturb_period;
|
||||||
|
del_timer(&f->perturb_timer);
|
||||||
|
if (perturb_period)
|
||||||
|
mod_timer(&f->perturb_timer, jiffies + perturb_period);
|
||||||
|
|
||||||
if (*arg == 0)
|
if (*arg == 0)
|
||||||
list_add_tail(&f->list, &head->filters);
|
list_add_tail(&f->list, &head->filters);
|
||||||
|
|
||||||
|
@ -512,6 +547,7 @@ err1:
|
||||||
|
|
||||||
static void flow_destroy_filter(struct tcf_proto *tp, struct flow_filter *f)
|
static void flow_destroy_filter(struct tcf_proto *tp, struct flow_filter *f)
|
||||||
{
|
{
|
||||||
|
del_timer_sync(&f->perturb_timer);
|
||||||
tcf_exts_destroy(tp, &f->exts);
|
tcf_exts_destroy(tp, &f->exts);
|
||||||
tcf_em_tree_destroy(tp, &f->ematches);
|
tcf_em_tree_destroy(tp, &f->ematches);
|
||||||
kfree(f);
|
kfree(f);
|
||||||
|
@ -532,11 +568,6 @@ static int flow_init(struct tcf_proto *tp)
|
||||||
{
|
{
|
||||||
struct flow_head *head;
|
struct flow_head *head;
|
||||||
|
|
||||||
if (!flow_hashrnd_initted) {
|
|
||||||
get_random_bytes(&flow_hashrnd, 4);
|
|
||||||
flow_hashrnd_initted = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
head = kzalloc(sizeof(*head), GFP_KERNEL);
|
head = kzalloc(sizeof(*head), GFP_KERNEL);
|
||||||
if (head == NULL)
|
if (head == NULL)
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
|
@ -605,6 +636,9 @@ static int flow_dump(struct tcf_proto *tp, unsigned long fh,
|
||||||
if (f->baseclass)
|
if (f->baseclass)
|
||||||
NLA_PUT_U32(skb, TCA_FLOW_BASECLASS, f->baseclass);
|
NLA_PUT_U32(skb, TCA_FLOW_BASECLASS, f->baseclass);
|
||||||
|
|
||||||
|
if (f->perturb_period)
|
||||||
|
NLA_PUT_U32(skb, TCA_FLOW_PERTURB, f->perturb_period / HZ);
|
||||||
|
|
||||||
if (tcf_exts_dump(skb, &f->exts, &flow_ext_map) < 0)
|
if (tcf_exts_dump(skb, &f->exts, &flow_ext_map) < 0)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
#ifdef CONFIG_NET_EMATCH
|
#ifdef CONFIG_NET_EMATCH
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue