History

net/sched: introduce Match-all classifier

The matchall classifier matches every packet and allows the user to apply actions on it. This filter is very useful in usecases where every packet should be matched, for example, packet mirroring (SPAN) can be setup very easily using that filter.

Jiri Pirko committed 10 years ago

Commit bf3994d1 parent ded821c4 files · +270 −0Browse files

Unified · Split

4 files
  1. include/uapi/linux/pkt_cls.h +11 −0
  2. net/sched/Kconfig +10 −0
  3. net/sched/Makefile +1 −0
  4. net/sched/cls_matchall.c +248 −0
include/uapi/linux/pkt_cls.h+11−0
@@ -433,6 +433,17 @@ enum { · 432 unmodified lines
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 {
net/sched/Kconfig+10−0
@@ -494,6 +494,16 @@ config NET_CLS_FLOWER · 493 unmodified lines
494 To compile this code as a module, choose M here: the module will494 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_EMATCH507config NET_EMATCH
498 bool "Extended Matches"508 bool "Extended Matches"
499 select NET_CLS509 select NET_CLS
net/sched/Makefile+1−0
@@ -60,6 +60,7 @@ obj-$(CONFIG_NET_CLS_FLOW) += cls_flow.o · 59 unmodified lines
60obj-$(CONFIG_NET_CLS_CGROUP) += cls_cgroup.o60obj-$(CONFIG_NET_CLS_CGROUP) += cls_cgroup.o
61obj-$(CONFIG_NET_CLS_BPF) += cls_bpf.o61obj-$(CONFIG_NET_CLS_BPF) += cls_bpf.o
62obj-$(CONFIG_NET_CLS_FLOWER) += cls_flower.o62obj-$(CONFIG_NET_CLS_FLOWER) += cls_flower.o
63obj-$(CONFIG_NET_CLS_MATCHALL) += cls_matchall.o
63obj-$(CONFIG_NET_EMATCH) += ematch.o64obj-$(CONFIG_NET_EMATCH) += ematch.o
64obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o65obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o
65obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o66obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
net/sched/cls_matchall.c+248−0
@@ -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");

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t