Loading include/linux/pkt_cls.h +1 −0 Original line number Diff line number Diff line Loading @@ -374,6 +374,7 @@ enum TCA_FLOW_ACT, TCA_FLOW_POLICE, TCA_FLOW_EMATCHES, TCA_FLOW_PERTURB, __TCA_FLOW_MAX }; Loading net/sched/cls_flow.c +43 −9 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ struct flow_filter { struct list_head list; struct tcf_exts exts; struct tcf_ematch_tree ematches; struct timer_list perturb_timer; u32 perturb_period; u32 handle; u32 nkeys; Loading @@ -47,11 +49,9 @@ struct flow_filter { u32 addend; u32 divisor; 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 = { .action = TCA_FLOW_ACT, .police = TCA_FLOW_POLICE, Loading Loading @@ -348,7 +348,7 @@ static int flow_classify(struct sk_buff *skb, struct tcf_proto *tp, } if (f->mode == FLOW_MODE_HASH) classid = jhash2(keys, f->nkeys, flow_hashrnd); classid = jhash2(keys, f->nkeys, f->hashrnd); else { classid = keys[0]; classid = (classid & f->mask) ^ f->xor; Loading @@ -369,6 +369,15 @@ static int flow_classify(struct sk_buff *skb, struct tcf_proto *tp, 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] = { [TCA_FLOW_KEYS] = { .type = NLA_U32 }, [TCA_FLOW_MODE] = { .type = NLA_U32 }, Loading @@ -381,6 +390,7 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = { [TCA_FLOW_ACT] = { .type = NLA_NESTED }, [TCA_FLOW_POLICE] = { .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, Loading @@ -394,6 +404,7 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, struct tcf_exts e; struct tcf_ematch_tree t; unsigned int nkeys = 0; unsigned int perturb_period = 0; u32 baseclass = 0; u32 keymask = 0; u32 mode; Loading Loading @@ -442,6 +453,14 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, mode = nla_get_u32(tb[TCA_FLOW_MODE]); if (mode != FLOW_MODE_HASH && nkeys > 1) 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 { err = -EINVAL; if (!handle) Loading @@ -455,6 +474,12 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, if (mode != FLOW_MODE_HASH && nkeys > 1) 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) baseclass = TC_H_MAKE(tp->q->handle, baseclass); if (TC_H_MIN(baseclass) == 0) Loading @@ -467,6 +492,11 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, f->handle = handle; 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); Loading Loading @@ -495,6 +525,11 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, if (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) list_add_tail(&f->list, &head->filters); Loading @@ -512,6 +547,7 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, 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_em_tree_destroy(tp, &f->ematches); kfree(f); Loading @@ -532,11 +568,6 @@ static int flow_init(struct tcf_proto *tp) { struct flow_head *head; if (!flow_hashrnd_initted) { get_random_bytes(&flow_hashrnd, 4); flow_hashrnd_initted = 1; } head = kzalloc(sizeof(*head), GFP_KERNEL); if (head == NULL) return -ENOBUFS; Loading Loading @@ -605,6 +636,9 @@ static int flow_dump(struct tcf_proto *tp, unsigned long fh, if (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) goto nla_put_failure; #ifdef CONFIG_NET_EMATCH Loading Loading
include/linux/pkt_cls.h +1 −0 Original line number Diff line number Diff line Loading @@ -374,6 +374,7 @@ enum TCA_FLOW_ACT, TCA_FLOW_POLICE, TCA_FLOW_EMATCHES, TCA_FLOW_PERTURB, __TCA_FLOW_MAX }; Loading
net/sched/cls_flow.c +43 −9 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ struct flow_filter { struct list_head list; struct tcf_exts exts; struct tcf_ematch_tree ematches; struct timer_list perturb_timer; u32 perturb_period; u32 handle; u32 nkeys; Loading @@ -47,11 +49,9 @@ struct flow_filter { u32 addend; u32 divisor; 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 = { .action = TCA_FLOW_ACT, .police = TCA_FLOW_POLICE, Loading Loading @@ -348,7 +348,7 @@ static int flow_classify(struct sk_buff *skb, struct tcf_proto *tp, } if (f->mode == FLOW_MODE_HASH) classid = jhash2(keys, f->nkeys, flow_hashrnd); classid = jhash2(keys, f->nkeys, f->hashrnd); else { classid = keys[0]; classid = (classid & f->mask) ^ f->xor; Loading @@ -369,6 +369,15 @@ static int flow_classify(struct sk_buff *skb, struct tcf_proto *tp, 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] = { [TCA_FLOW_KEYS] = { .type = NLA_U32 }, [TCA_FLOW_MODE] = { .type = NLA_U32 }, Loading @@ -381,6 +390,7 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = { [TCA_FLOW_ACT] = { .type = NLA_NESTED }, [TCA_FLOW_POLICE] = { .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, Loading @@ -394,6 +404,7 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, struct tcf_exts e; struct tcf_ematch_tree t; unsigned int nkeys = 0; unsigned int perturb_period = 0; u32 baseclass = 0; u32 keymask = 0; u32 mode; Loading Loading @@ -442,6 +453,14 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, mode = nla_get_u32(tb[TCA_FLOW_MODE]); if (mode != FLOW_MODE_HASH && nkeys > 1) 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 { err = -EINVAL; if (!handle) Loading @@ -455,6 +474,12 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, if (mode != FLOW_MODE_HASH && nkeys > 1) 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) baseclass = TC_H_MAKE(tp->q->handle, baseclass); if (TC_H_MIN(baseclass) == 0) Loading @@ -467,6 +492,11 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, f->handle = handle; 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); Loading Loading @@ -495,6 +525,11 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, if (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) list_add_tail(&f->list, &head->filters); Loading @@ -512,6 +547,7 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, 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_em_tree_destroy(tp, &f->ematches); kfree(f); Loading @@ -532,11 +568,6 @@ static int flow_init(struct tcf_proto *tp) { struct flow_head *head; if (!flow_hashrnd_initted) { get_random_bytes(&flow_hashrnd, 4); flow_hashrnd_initted = 1; } head = kzalloc(sizeof(*head), GFP_KERNEL); if (head == NULL) return -ENOBUFS; Loading Loading @@ -605,6 +636,9 @@ static int flow_dump(struct tcf_proto *tp, unsigned long fh, if (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) goto nla_put_failure; #ifdef CONFIG_NET_EMATCH Loading