cls_fw.c (f43dc23d5ea91fca257be02138a255f02d98e806) cls_fw.c (cc7ec456f82da7f89a5b376e613b3ac4311b3e9a)
1/*
2 * net/sched/cls_fw.c Classifier mapping ipchains' fwmark to traffic class.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *

--- 17 unchanged lines hidden (view full) ---

26#include <linux/errno.h>
27#include <linux/skbuff.h>
28#include <net/netlink.h>
29#include <net/act_api.h>
30#include <net/pkt_cls.h>
31
32#define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *))
33
1/*
2 * net/sched/cls_fw.c Classifier mapping ipchains' fwmark to traffic class.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *

--- 17 unchanged lines hidden (view full) ---

26#include <linux/errno.h>
27#include <linux/skbuff.h>
28#include <net/netlink.h>
29#include <net/act_api.h>
30#include <net/pkt_cls.h>
31
32#define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *))
33
34struct fw_head
35{
34struct fw_head {
36 struct fw_filter *ht[HTSIZE];
37 u32 mask;
38};
39
35 struct fw_filter *ht[HTSIZE];
36 u32 mask;
37};
38
40struct fw_filter
41{
39struct fw_filter {
42 struct fw_filter *next;
43 u32 id;
44 struct tcf_result res;
45#ifdef CONFIG_NET_CLS_IND
46 char indev[IFNAMSIZ];
47#endif /* CONFIG_NET_CLS_IND */
48 struct tcf_exts exts;
49};
50
51static const struct tcf_ext_map fw_ext_map = {
52 .action = TCA_FW_ACT,
53 .police = TCA_FW_POLICE
54};
55
40 struct fw_filter *next;
41 u32 id;
42 struct tcf_result res;
43#ifdef CONFIG_NET_CLS_IND
44 char indev[IFNAMSIZ];
45#endif /* CONFIG_NET_CLS_IND */
46 struct tcf_exts exts;
47};
48
49static const struct tcf_ext_map fw_ext_map = {
50 .action = TCA_FW_ACT,
51 .police = TCA_FW_POLICE
52};
53
56static __inline__ int fw_hash(u32 handle)
54static inline int fw_hash(u32 handle)
57{
58 if (HTSIZE == 4096)
59 return ((handle >> 24) & 0xFFF) ^
60 ((handle >> 12) & 0xFFF) ^
61 (handle & 0xFFF);
62 else if (HTSIZE == 2048)
63 return ((handle >> 22) & 0x7FF) ^
64 ((handle >> 11) & 0x7FF) ^

--- 12 unchanged lines hidden (view full) ---

77 return t[0] ^ t[1] ^ t[2] ^ t[3];
78 } else
79 return handle & (HTSIZE - 1);
80}
81
82static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
83 struct tcf_result *res)
84{
55{
56 if (HTSIZE == 4096)
57 return ((handle >> 24) & 0xFFF) ^
58 ((handle >> 12) & 0xFFF) ^
59 (handle & 0xFFF);
60 else if (HTSIZE == 2048)
61 return ((handle >> 22) & 0x7FF) ^
62 ((handle >> 11) & 0x7FF) ^

--- 12 unchanged lines hidden (view full) ---

75 return t[0] ^ t[1] ^ t[2] ^ t[3];
76 } else
77 return handle & (HTSIZE - 1);
78}
79
80static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
81 struct tcf_result *res)
82{
85 struct fw_head *head = (struct fw_head*)tp->root;
83 struct fw_head *head = (struct fw_head *)tp->root;
86 struct fw_filter *f;
87 int r;
88 u32 id = skb->mark;
89
90 if (head != NULL) {
91 id &= head->mask;
84 struct fw_filter *f;
85 int r;
86 u32 id = skb->mark;
87
88 if (head != NULL) {
89 id &= head->mask;
92 for (f=head->ht[fw_hash(id)]; f; f=f->next) {
90 for (f = head->ht[fw_hash(id)]; f; f = f->next) {
93 if (f->id == id) {
94 *res = f->res;
95#ifdef CONFIG_NET_CLS_IND
96 if (!tcf_match_indev(skb, f->indev))
97 continue;
98#endif /* CONFIG_NET_CLS_IND */
99 r = tcf_exts_exec(skb, &f->exts, res);
100 if (r < 0)
101 continue;
102
103 return r;
104 }
105 }
106 } else {
107 /* old method */
91 if (f->id == id) {
92 *res = f->res;
93#ifdef CONFIG_NET_CLS_IND
94 if (!tcf_match_indev(skb, f->indev))
95 continue;
96#endif /* CONFIG_NET_CLS_IND */
97 r = tcf_exts_exec(skb, &f->exts, res);
98 if (r < 0)
99 continue;
100
101 return r;
102 }
103 }
104 } else {
105 /* old method */
108 if (id && (TC_H_MAJ(id) == 0 || !(TC_H_MAJ(id^tp->q->handle)))) {
106 if (id && (TC_H_MAJ(id) == 0 ||
107 !(TC_H_MAJ(id ^ tp->q->handle)))) {
109 res->classid = id;
110 res->class = 0;
111 return 0;
112 }
113 }
114
115 return -1;
116}
117
118static unsigned long fw_get(struct tcf_proto *tp, u32 handle)
119{
108 res->classid = id;
109 res->class = 0;
110 return 0;
111 }
112 }
113
114 return -1;
115}
116
117static unsigned long fw_get(struct tcf_proto *tp, u32 handle)
118{
120 struct fw_head *head = (struct fw_head*)tp->root;
119 struct fw_head *head = (struct fw_head *)tp->root;
121 struct fw_filter *f;
122
123 if (head == NULL)
124 return 0;
125
120 struct fw_filter *f;
121
122 if (head == NULL)
123 return 0;
124
126 for (f=head->ht[fw_hash(handle)]; f; f=f->next) {
125 for (f = head->ht[fw_hash(handle)]; f; f = f->next) {
127 if (f->id == handle)
128 return (unsigned long)f;
129 }
130 return 0;
131}
132
133static void fw_put(struct tcf_proto *tp, unsigned long f)
134{
135}
136
137static int fw_init(struct tcf_proto *tp)
138{
139 return 0;
140}
141
126 if (f->id == handle)
127 return (unsigned long)f;
128 }
129 return 0;
130}
131
132static void fw_put(struct tcf_proto *tp, unsigned long f)
133{
134}
135
136static int fw_init(struct tcf_proto *tp)
137{
138 return 0;
139}
140
142static inline void
143fw_delete_filter(struct tcf_proto *tp, struct fw_filter *f)
141static void fw_delete_filter(struct tcf_proto *tp, struct fw_filter *f)
144{
145 tcf_unbind_filter(tp, &f->res);
146 tcf_exts_destroy(tp, &f->exts);
147 kfree(f);
148}
149
150static void fw_destroy(struct tcf_proto *tp)
151{
152 struct fw_head *head = tp->root;
153 struct fw_filter *f;
154 int h;
155
156 if (head == NULL)
157 return;
158
142{
143 tcf_unbind_filter(tp, &f->res);
144 tcf_exts_destroy(tp, &f->exts);
145 kfree(f);
146}
147
148static void fw_destroy(struct tcf_proto *tp)
149{
150 struct fw_head *head = tp->root;
151 struct fw_filter *f;
152 int h;
153
154 if (head == NULL)
155 return;
156
159 for (h=0; h<HTSIZE; h++) {
160 while ((f=head->ht[h]) != NULL) {
157 for (h = 0; h < HTSIZE; h++) {
158 while ((f = head->ht[h]) != NULL) {
161 head->ht[h] = f->next;
162 fw_delete_filter(tp, f);
163 }
164 }
165 kfree(head);
166}
167
168static int fw_delete(struct tcf_proto *tp, unsigned long arg)
169{
159 head->ht[h] = f->next;
160 fw_delete_filter(tp, f);
161 }
162 }
163 kfree(head);
164}
165
166static int fw_delete(struct tcf_proto *tp, unsigned long arg)
167{
170 struct fw_head *head = (struct fw_head*)tp->root;
171 struct fw_filter *f = (struct fw_filter*)arg;
168 struct fw_head *head = (struct fw_head *)tp->root;
169 struct fw_filter *f = (struct fw_filter *)arg;
172 struct fw_filter **fp;
173
174 if (head == NULL || f == NULL)
175 goto out;
176
170 struct fw_filter **fp;
171
172 if (head == NULL || f == NULL)
173 goto out;
174
177 for (fp=&head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) {
175 for (fp = &head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) {
178 if (*fp == f) {
179 tcf_tree_lock(tp);
180 *fp = f->next;
181 tcf_tree_unlock(tp);
182 fw_delete_filter(tp, f);
183 return 0;
184 }
185 }

--- 49 unchanged lines hidden (view full) ---

235 return err;
236}
237
238static int fw_change(struct tcf_proto *tp, unsigned long base,
239 u32 handle,
240 struct nlattr **tca,
241 unsigned long *arg)
242{
176 if (*fp == f) {
177 tcf_tree_lock(tp);
178 *fp = f->next;
179 tcf_tree_unlock(tp);
180 fw_delete_filter(tp, f);
181 return 0;
182 }
183 }

--- 49 unchanged lines hidden (view full) ---

233 return err;
234}
235
236static int fw_change(struct tcf_proto *tp, unsigned long base,
237 u32 handle,
238 struct nlattr **tca,
239 unsigned long *arg)
240{
243 struct fw_head *head = (struct fw_head*)tp->root;
241 struct fw_head *head = (struct fw_head *)tp->root;
244 struct fw_filter *f = (struct fw_filter *) *arg;
245 struct nlattr *opt = tca[TCA_OPTIONS];
246 struct nlattr *tb[TCA_FW_MAX + 1];
247 int err;
248
249 if (!opt)
250 return handle ? -EINVAL : 0;
251

--- 45 unchanged lines hidden (view full) ---

297
298errout:
299 kfree(f);
300 return err;
301}
302
303static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg)
304{
242 struct fw_filter *f = (struct fw_filter *) *arg;
243 struct nlattr *opt = tca[TCA_OPTIONS];
244 struct nlattr *tb[TCA_FW_MAX + 1];
245 int err;
246
247 if (!opt)
248 return handle ? -EINVAL : 0;
249

--- 45 unchanged lines hidden (view full) ---

295
296errout:
297 kfree(f);
298 return err;
299}
300
301static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg)
302{
305 struct fw_head *head = (struct fw_head*)tp->root;
303 struct fw_head *head = (struct fw_head *)tp->root;
306 int h;
307
308 if (head == NULL)
309 arg->stop = 1;
310
311 if (arg->stop)
312 return;
313

--- 13 unchanged lines hidden (view full) ---

327 }
328 }
329}
330
331static int fw_dump(struct tcf_proto *tp, unsigned long fh,
332 struct sk_buff *skb, struct tcmsg *t)
333{
334 struct fw_head *head = (struct fw_head *)tp->root;
304 int h;
305
306 if (head == NULL)
307 arg->stop = 1;
308
309 if (arg->stop)
310 return;
311

--- 13 unchanged lines hidden (view full) ---

325 }
326 }
327}
328
329static int fw_dump(struct tcf_proto *tp, unsigned long fh,
330 struct sk_buff *skb, struct tcmsg *t)
331{
332 struct fw_head *head = (struct fw_head *)tp->root;
335 struct fw_filter *f = (struct fw_filter*)fh;
333 struct fw_filter *f = (struct fw_filter *)fh;
336 unsigned char *b = skb_tail_pointer(skb);
337 struct nlattr *nest;
338
339 if (f == NULL)
340 return skb->len;
341
342 t->tcm_handle = f->id;
343

--- 58 unchanged lines hidden ---
334 unsigned char *b = skb_tail_pointer(skb);
335 struct nlattr *nest;
336
337 if (f == NULL)
338 return skb->len;
339
340 t->tcm_handle = f->id;
341

--- 58 unchanged lines hidden ---