aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/pkt_cls.h11
-rw-r--r--net/sched/Kconfig10
-rw-r--r--net/sched/Makefile1
-rw-r--r--net/sched/cls_matchall.c248
4 files changed, 270 insertions, 0 deletions
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 5702e933dc07..a32494887e01 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -433,6 +433,17 @@ enum {
433 433
434#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1) 434#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
435 435
436/* Match-all classifier */
437
438enum {
439 TCA_MATCHALL_UNSPEC,
440 TCA_MATCHALL_CLASSID,
441 TCA_MATCHALL_ACT,
442 __TCA_MATCHALL_MAX,
443};
444
445#define TCA_MATCHALL_MAX (__TCA_MATCHALL_MAX - 1)
446
436/* Extended Matches */ 447/* Extended Matches */
437 448
438struct tcf_ematch_tree_hdr { 449struct tcf_ematch_tree_hdr {
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index b148302bbaf2..ccf931b3b94c 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -494,6 +494,16 @@ config NET_CLS_FLOWER
494 To compile this code as a module, choose M here: the module will 494 To compile this code as a module, choose M here: the module will
495 be called cls_flower. 495 be called cls_flower.
496 496
497config NET_CLS_MATCHALL
498 tristate "Match-all classifier"
499 select NET_CLS
500 ---help---
501 If you say Y here, you will be able to classify packets based on
502 nothing. Every packet will match.
503
504 To compile this code as a module, choose M here: the module will
505 be called cls_matchall.
506
497config NET_EMATCH 507config NET_EMATCH
498 bool "Extended Matches" 508 bool "Extended Matches"
499 select NET_CLS 509 select NET_CLS
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 84bddb373517..ae088a5a9d95 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_NET_CLS_FLOW) += cls_flow.o
60obj-$(CONFIG_NET_CLS_CGROUP) += cls_cgroup.o 60obj-$(CONFIG_NET_CLS_CGROUP) += cls_cgroup.o
61obj-$(CONFIG_NET_CLS_BPF) += cls_bpf.o 61obj-$(CONFIG_NET_CLS_BPF) += cls_bpf.o
62obj-$(CONFIG_NET_CLS_FLOWER) += cls_flower.o 62obj-$(CONFIG_NET_CLS_FLOWER) += cls_flower.o
63obj-$(CONFIG_NET_CLS_MATCHALL) += cls_matchall.o
63obj-$(CONFIG_NET_EMATCH) += ematch.o 64obj-$(CONFIG_NET_EMATCH) += ematch.o
64obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o 65obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o
65obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o 66obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
new file mode 100644
index 000000000000..8a6b4de7a99a
--- /dev/null
+++ b/net/sched/cls_matchall.c
@@ -0,0 +1,248 @@
1/*
2 * net/sched/cls_matchll.c Match-all classifier
3 *
4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/module.h>
15
16#include <net/sch_generic.h>
17#include <net/pkt_cls.h>
18
19struct cls_mall_filter {
20 struct tcf_exts exts;
21 struct tcf_result res;
22 u32 handle;
23 struct rcu_head rcu;
24};
25
26struct cls_mall_head {
27 struct cls_mall_filter *filter;
28 struct rcu_head rcu;
29};
30
31static int mall_classify(struct sk_buff *skb, const struct tcf_proto *tp,
32 struct tcf_result *res)
33{
34 struct cls_mall_head *head = rcu_dereference_bh(tp->root);
35 struct cls_mall_filter *f = head->filter;
36
37 return tcf_exts_exec(skb, &f->exts, res);
38}
39
40static int mall_init(struct tcf_proto *tp)
41{
42 struct cls_mall_head *head;
43
44 head = kzalloc(sizeof(*head), GFP_KERNEL);
45 if (!head)
46 return -ENOBUFS;
47
48 rcu_assign_pointer(tp->root, head);
49
50 return 0;
51}
52
53static void mall_destroy_filter(struct rcu_head *head)
54{
55 struct cls_mall_filter *f = container_of(head, struct cls_mall_filter, rcu);
56
57 tcf_exts_destroy(&f->exts);
58 kfree(f);
59}
60
61static bool mall_destroy(struct tcf_proto *tp, bool force)
62{
63 struct cls_mall_head *head = rtnl_dereference(tp->root);
64
65 if (!force && head->filter)
66 return false;
67
68 if (head->filter)
69 call_rcu(&head->filter->rcu, mall_destroy_filter);
70 RCU_INIT_POINTER(tp->root, NULL);
71 kfree_rcu(head, rcu);
72 return true;
73}
74
75static unsigned long mall_get(struct tcf_proto *tp, u32 handle)
76{
77 struct cls_mall_head *head = rtnl_dereference(tp->root);
78 struct cls_mall_filter *f = head->filter;
79
80 if (f && f->handle == handle)
81 return (unsigned long) f;
82 return 0;
83}
84
85static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
86 [TCA_MATCHALL_UNSPEC] = { .type = NLA_UNSPEC },
87 [TCA_MATCHALL_CLASSID] = { .type = NLA_U32 },
88};
89
90static int mall_set_parms(struct net *net, struct tcf_proto *tp,
91 struct cls_mall_filter *f,
92 unsigned long base, struct nlattr **tb,
93 struct nlattr *est, bool ovr)
94{
95 struct tcf_exts e;
96 int err;
97
98 tcf_exts_init(&e, TCA_MATCHALL_ACT, 0);
99 err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
100 if (err < 0)
101 return err;
102
103 if (tb[TCA_MATCHALL_CLASSID]) {
104 f->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
105 tcf_bind_filter(tp, &f->res, base);
106 }
107
108 tcf_exts_change(tp, &f->exts, &e);
109
110 return 0;
111}
112
113static int mall_change(struct net *net, struct sk_buff *in_skb,
114 struct tcf_proto *tp, unsigned long base,
115 u32 handle, struct nlattr **tca,
116 unsigned long *arg, bool ovr)
117{
118 struct cls_mall_head *head = rtnl_dereference(tp->root);
119 struct cls_mall_filter *fold = (struct cls_mall_filter *) *arg;
120 struct cls_mall_filter *f;
121 struct nlattr *tb[TCA_MATCHALL_MAX + 1];
122 int err;
123
124 if (!tca[TCA_OPTIONS])
125 return -EINVAL;
126
127 if (head->filter)
128 return -EBUSY;
129
130 if (fold)
131 return -EINVAL;
132
133 err = nla_parse_nested(tb, TCA_MATCHALL_MAX,
134 tca[TCA_OPTIONS], mall_policy);
135 if (err < 0)
136 return err;
137
138 f = kzalloc(sizeof(*f), GFP_KERNEL);
139 if (!f)
140 return -ENOBUFS;
141
142 tcf_exts_init(&f->exts, TCA_MATCHALL_ACT, 0);
143
144 if (!handle)
145 handle = 1;
146 f->handle = handle;
147
148 err = mall_set_parms(net, tp, f, base, tb, tca[TCA_RATE], ovr);
149 if (err)
150 goto errout;
151
152 *arg = (unsigned long) f;
153 rcu_assign_pointer(head->filter, f);
154
155 return 0;
156
157errout:
158 kfree(f);
159 return err;
160}
161
162static int mall_delete(struct tcf_proto *tp, unsigned long arg)
163{
164 struct cls_mall_head *head = rtnl_dereference(tp->root);
165 struct cls_mall_filter *f = (struct cls_mall_filter *) arg;
166
167 RCU_INIT_POINTER(head->filter, NULL);
168 tcf_unbind_filter(tp, &f->res);
169 call_rcu(&f->rcu, mall_destroy_filter);
170 return 0;
171}
172
173static void mall_walk(struct tcf_proto *tp, struct tcf_walker *arg)
174{
175 struct cls_mall_head *head = rtnl_dereference(tp->root);
176 struct cls_mall_filter *f = head->filter;
177
178 if (arg->count < arg->skip)
179 goto skip;
180 if (arg->fn(tp, (unsigned long) f, arg) < 0)
181 arg->stop = 1;
182skip:
183 arg->count++;
184}
185
186static int mall_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
187 struct sk_buff *skb, struct tcmsg *t)
188{
189 struct cls_mall_filter *f = (struct cls_mall_filter *) fh;
190 struct nlattr *nest;
191
192 if (!f)
193 return skb->len;
194
195 t->tcm_handle = f->handle;
196
197 nest = nla_nest_start(skb, TCA_OPTIONS);
198 if (!nest)
199 goto nla_put_failure;
200
201 if (f->res.classid &&
202 nla_put_u32(skb, TCA_MATCHALL_CLASSID, f->res.classid))
203 goto nla_put_failure;
204
205 if (tcf_exts_dump(skb, &f->exts))
206 goto nla_put_failure;
207
208 nla_nest_end(skb, nest);
209
210 if (tcf_exts_dump_stats(skb, &f->exts) < 0)
211 goto nla_put_failure;
212
213 return skb->len;
214
215nla_put_failure:
216 nla_nest_cancel(skb, nest);
217 return -1;
218}
219
220static struct tcf_proto_ops cls_mall_ops __read_mostly = {
221 .kind = "matchall",
222 .classify = mall_classify,
223 .init = mall_init,
224 .destroy = mall_destroy,
225 .get = mall_get,
226 .change = mall_change,
227 .delete = mall_delete,
228 .walk = mall_walk,
229 .dump = mall_dump,
230 .owner = THIS_MODULE,
231};
232
233static int __init cls_mall_init(void)
234{
235 return register_tcf_proto_ops(&cls_mall_ops);
236}
237
238static void __exit cls_mall_exit(void)
239{
240 unregister_tcf_proto_ops(&cls_mall_ops);
241}
242
243module_init(cls_mall_init);
244module_exit(cls_mall_exit);
245
246MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
247MODULE_DESCRIPTION("Match-all classifier");
248MODULE_LICENSE("GPL v2");