aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-08-25 19:11:42 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:18:12 -0400
commitb4e9b520ca5d07a37ea59648e7f50f478e7487a3 (patch)
treec007ca2e57ba73e6bc6196ad1deaaf58c7d7aae4
parent88e91f290307d22ae88302e3a24f0c36905e8a6c (diff)
[NET_SCHED]: Add mask support to fwmark classifier
Support masking the nfmark value before the search. The mask value is global for all filters contained in one instance. It can only be set when a new instance is created, all filters must specify the same mask. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/pkt_cls.h1
-rw-r--r--net/sched/cls_fw.c25
2 files changed, 25 insertions, 1 deletions
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index bd2c5a2bbbf5..c3f01b3085a4 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -305,6 +305,7 @@ enum
305 TCA_FW_POLICE, 305 TCA_FW_POLICE,
306 TCA_FW_INDEV, /* used by CONFIG_NET_CLS_IND */ 306 TCA_FW_INDEV, /* used by CONFIG_NET_CLS_IND */
307 TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */ 307 TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */
308 TCA_FW_MASK,
308 __TCA_FW_MAX 309 __TCA_FW_MAX
309}; 310};
310 311
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index e6973d9b686d..e54acc6bcccd 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -50,6 +50,7 @@
50struct fw_head 50struct fw_head
51{ 51{
52 struct fw_filter *ht[HTSIZE]; 52 struct fw_filter *ht[HTSIZE];
53 u32 mask;
53}; 54};
54 55
55struct fw_filter 56struct fw_filter
@@ -101,7 +102,7 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
101 struct fw_filter *f; 102 struct fw_filter *f;
102 int r; 103 int r;
103#ifdef CONFIG_NETFILTER 104#ifdef CONFIG_NETFILTER
104 u32 id = skb->nfmark; 105 u32 id = skb->nfmark & head->mask;
105#else 106#else
106 u32 id = 0; 107 u32 id = 0;
107#endif 108#endif
@@ -209,7 +210,9 @@ static int
209fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f, 210fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
210 struct rtattr **tb, struct rtattr **tca, unsigned long base) 211 struct rtattr **tb, struct rtattr **tca, unsigned long base)
211{ 212{
213 struct fw_head *head = (struct fw_head *)tp->root;
212 struct tcf_exts e; 214 struct tcf_exts e;
215 u32 mask;
213 int err; 216 int err;
214 217
215 err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &fw_ext_map); 218 err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &fw_ext_map);
@@ -232,6 +235,15 @@ fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
232 } 235 }
233#endif /* CONFIG_NET_CLS_IND */ 236#endif /* CONFIG_NET_CLS_IND */
234 237
238 if (tb[TCA_FW_MASK-1]) {
239 if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32))
240 goto errout;
241 mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]);
242 if (mask != head->mask)
243 goto errout;
244 } else if (head->mask != 0xFFFFFFFF)
245 goto errout;
246
235 tcf_exts_change(tp, &f->exts, &e); 247 tcf_exts_change(tp, &f->exts, &e);
236 248
237 return 0; 249 return 0;
@@ -267,9 +279,17 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
267 return -EINVAL; 279 return -EINVAL;
268 280
269 if (head == NULL) { 281 if (head == NULL) {
282 u32 mask = 0xFFFFFFFF;
283 if (tb[TCA_FW_MASK-1]) {
284 if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32))
285 return -EINVAL;
286 mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]);
287 }
288
270 head = kzalloc(sizeof(struct fw_head), GFP_KERNEL); 289 head = kzalloc(sizeof(struct fw_head), GFP_KERNEL);
271 if (head == NULL) 290 if (head == NULL)
272 return -ENOBUFS; 291 return -ENOBUFS;
292 head->mask = mask;
273 293
274 tcf_tree_lock(tp); 294 tcf_tree_lock(tp);
275 tp->root = head; 295 tp->root = head;
@@ -330,6 +350,7 @@ static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg)
330static int fw_dump(struct tcf_proto *tp, unsigned long fh, 350static int fw_dump(struct tcf_proto *tp, unsigned long fh,
331 struct sk_buff *skb, struct tcmsg *t) 351 struct sk_buff *skb, struct tcmsg *t)
332{ 352{
353 struct fw_head *head = (struct fw_head *)tp->root;
333 struct fw_filter *f = (struct fw_filter*)fh; 354 struct fw_filter *f = (struct fw_filter*)fh;
334 unsigned char *b = skb->tail; 355 unsigned char *b = skb->tail;
335 struct rtattr *rta; 356 struct rtattr *rta;
@@ -351,6 +372,8 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
351 if (strlen(f->indev)) 372 if (strlen(f->indev))
352 RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev); 373 RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev);
353#endif /* CONFIG_NET_CLS_IND */ 374#endif /* CONFIG_NET_CLS_IND */
375 if (head->mask != 0xFFFFFFFF)
376 RTA_PUT(skb, TCA_FW_MASK, 4, &head->mask);
354 377
355 if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0) 378 if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0)
356 goto rtattr_failure; 379 goto rtattr_failure;