File: /usr/src/linux/net/sched/cls_route.c

1     /*
2      * net/sched/cls_route.c	ROUTE4 classifier.
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      *
9      * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10      */
11     
12     #include <linux/module.h>
13     #include <linux/config.h>
14     #include <asm/uaccess.h>
15     #include <asm/system.h>
16     #include <asm/bitops.h>
17     #include <linux/types.h>
18     #include <linux/kernel.h>
19     #include <linux/sched.h>
20     #include <linux/string.h>
21     #include <linux/mm.h>
22     #include <linux/socket.h>
23     #include <linux/sockios.h>
24     #include <linux/in.h>
25     #include <linux/errno.h>
26     #include <linux/interrupt.h>
27     #include <linux/if_ether.h>
28     #include <linux/inet.h>
29     #include <linux/netdevice.h>
30     #include <linux/etherdevice.h>
31     #include <linux/notifier.h>
32     #include <net/ip.h>
33     #include <net/route.h>
34     #include <linux/skbuff.h>
35     #include <net/sock.h>
36     #include <net/pkt_sched.h>
37     
38     /*
39        1. For now we assume that route tags < 256.
40           It allows to use direct table lookups, instead of hash tables.
41        2. For now we assume that "from TAG" and "fromdev DEV" statements
42           are mutually  exclusive.
43        3. "to TAG from ANY" has higher priority, than "to ANY from XXX"
44      */
45     
46     struct route4_fastmap
47     {
48     	struct route4_filter	*filter;
49     	u32			id;
50     	int			iif;
51     };
52     
53     struct route4_head
54     {
55     	struct route4_fastmap	fastmap[16];
56     	struct route4_bucket	*table[256+1];
57     };
58     
59     struct route4_bucket
60     {
61     	struct route4_filter	*ht[16+16+1];
62     };
63     
64     struct route4_filter
65     {
66     	struct route4_filter	*next;
67     	u32			id;
68     	int			iif;
69     
70     	struct tcf_result	res;
71     #ifdef CONFIG_NET_CLS_POLICE
72     	struct tcf_police	*police;
73     #endif
74     
75     	u32			handle;
76     	struct route4_bucket	*bkt;
77     };
78     
79     #define ROUTE4_FAILURE ((struct route4_filter*)(-1L))
80     
81     static __inline__ int route4_fastmap_hash(u32 id, int iif)
82     {
83     	return id&0xF;
84     }
85     
86     static void route4_reset_fastmap(struct net_device *dev, struct route4_head *head, u32 id)
87     {
88     	spin_lock_bh(&dev->queue_lock);
89     	memset(head->fastmap, 0, sizeof(head->fastmap));
90     	spin_unlock_bh(&dev->queue_lock);
91     }
92     
93     static void __inline__
94     route4_set_fastmap(struct route4_head *head, u32 id, int iif,
95     		   struct route4_filter *f)
96     {
97     	int h = route4_fastmap_hash(id, iif);
98     	head->fastmap[h].id = id;
99     	head->fastmap[h].iif = iif;
100     	head->fastmap[h].filter = f;
101     }
102     
103     static __inline__ int route4_hash_to(u32 id)
104     {
105     	return id&0xFF;
106     }
107     
108     static __inline__ int route4_hash_from(u32 id)
109     {
110     	return (id>>16)&0xF;
111     }
112     
113     static __inline__ int route4_hash_iif(int iif)
114     {
115     	return 16 + ((iif>>16)&0xF);
116     }
117     
118     static __inline__ int route4_hash_wild(void)
119     {
120     	return 32;
121     }
122     
123     #ifdef CONFIG_NET_CLS_POLICE
124     #define IF_ROUTE_POLICE \
125     if (f->police) { \
126     	int pol_res = tcf_police(skb, f->police); \
127     	if (pol_res >= 0) return pol_res; \
128     	dont_cache = 1; \
129     	continue; \
130     } \
131     if (!dont_cache)
132     #else
133     #define IF_ROUTE_POLICE
134     #endif
135     
136     
137     static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp,
138     			   struct tcf_result *res)
139     {
140     	struct route4_head *head = (struct route4_head*)tp->root;
141     	struct dst_entry *dst;
142     	struct route4_bucket *b;
143     	struct route4_filter *f;
144     #ifdef CONFIG_NET_CLS_POLICE
145     	int dont_cache = 0;
146     #endif
147     	u32 id, h;
148     	int iif;
149     
150     	if ((dst = skb->dst) == NULL)
151     		goto failure;
152     
153     	id = dst->tclassid;
154     	if (head == NULL)
155     		goto old_method;
156     
157     	iif = ((struct rtable*)dst)->key.iif;
158     
159     	h = route4_fastmap_hash(id, iif);
160     	if (id == head->fastmap[h].id &&
161     	    iif == head->fastmap[h].iif &&
162     	    (f = head->fastmap[h].filter) != NULL) {
163     		if (f == ROUTE4_FAILURE)
164     			goto failure;
165     
166     		*res = f->res;
167     		return 0;
168     	}
169     
170     	h = route4_hash_to(id);
171     
172     restart:
173     	if ((b = head->table[h]) != NULL) {
174     		f = b->ht[route4_hash_from(id)];
175     
176     		for ( ; f; f = f->next) {
177     			if (f->id == id) {
178     				*res = f->res;
179     				IF_ROUTE_POLICE route4_set_fastmap(head, id, iif, f);
180     				return 0;
181     			}
182     		}
183     
184     		for (f = b->ht[route4_hash_iif(iif)]; f; f = f->next) {
185     			if (f->iif == iif) {
186     				*res = f->res;
187     				IF_ROUTE_POLICE route4_set_fastmap(head, id, iif, f);
188     				return 0;
189     			}
190     		}
191     
192     		for (f = b->ht[route4_hash_wild()]; f; f = f->next) {
193     			*res = f->res;
194     			IF_ROUTE_POLICE route4_set_fastmap(head, id, iif, f);
195     			return 0;
196     		}
197     
198     	}
199     	if (h < 256) {
200     		h = 256;
201     		id &= ~0xFFFF;
202     		goto restart;
203     	}
204     
205     #ifdef CONFIG_NET_CLS_POLICE
206     	if (!dont_cache)
207     #endif
208     		route4_set_fastmap(head, id, iif, ROUTE4_FAILURE);
209     failure:
210     	return -1;
211     
212     old_method:
213     	if (id && (TC_H_MAJ(id) == 0 ||
214     		   !(TC_H_MAJ(id^tp->q->handle)))) {
215     		res->classid = id;
216     		res->class = 0;
217     		return 0;
218     	}
219     	return -1;
220     }
221     
222     static u32 to_hash(u32 id)
223     {
224     	u32 h = id&0xFF;
225     	if (id&0x8000)
226     		h += 256;
227     	return h;
228     }
229     
230     static u32 from_hash(u32 id)
231     {
232     	id &= 0xFFFF;
233     	if (id == 0xFFFF)
234     		return 32;
235     	if (!(id & 0x8000)) {
236     		if (id > 255)
237     			return 256;
238     		return id&0xF;
239     	}
240     	return 16 + (id&0xF);
241     }
242     
243     static unsigned long route4_get(struct tcf_proto *tp, u32 handle)
244     {
245     	struct route4_head *head = (struct route4_head*)tp->root;
246     	struct route4_bucket *b;
247     	struct route4_filter *f;
248     	unsigned h1, h2;
249     
250     	if (!head)
251     		return 0;
252     
253     	h1 = to_hash(handle);
254     	if (h1 > 256)
255     		return 0;
256     
257     	h2 = from_hash(handle>>16);
258     	if (h2 > 32)
259     		return 0;
260     
261     	if ((b = head->table[h1]) != NULL) {
262     		for (f = b->ht[h2]; f; f = f->next)
263     			if (f->handle == handle)
264     				return (unsigned long)f;
265     	}
266     	return 0;
267     }
268     
269     static void route4_put(struct tcf_proto *tp, unsigned long f)
270     {
271     }
272     
273     static int route4_init(struct tcf_proto *tp)
274     {
275     	MOD_INC_USE_COUNT;
276     	return 0;
277     }
278     
279     static void route4_destroy(struct tcf_proto *tp)
280     {
281     	struct route4_head *head = xchg(&tp->root, NULL);
282     	int h1, h2;
283     
284     	if (head == NULL) {
285     		MOD_DEC_USE_COUNT;
286     		return;
287     	}
288     
289     	for (h1=0; h1<=256; h1++) {
290     		struct route4_bucket *b;
291     
292     		if ((b = head->table[h1]) != NULL) {
293     			for (h2=0; h2<=32; h2++) {
294     				struct route4_filter *f;
295     
296     				while ((f = b->ht[h2]) != NULL) {
297     					unsigned long cl;
298     
299     					b->ht[h2] = f->next;
300     					if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
301     						tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
302     #ifdef CONFIG_NET_CLS_POLICE
303     					tcf_police_release(f->police);
304     #endif
305     					kfree(f);
306     				}
307     			}
308     			kfree(b);
309     		}
310     	}
311     	kfree(head);
312     	MOD_DEC_USE_COUNT;
313     }
314     
315     static int route4_delete(struct tcf_proto *tp, unsigned long arg)
316     {
317     	struct route4_head *head = (struct route4_head*)tp->root;
318     	struct route4_filter **fp, *f = (struct route4_filter*)arg;
319     	unsigned h = 0;
320     	struct route4_bucket *b;
321     	int i;
322     
323     	if (!head || !f)
324     		return -EINVAL;
325     
326     	h = f->handle;
327     	b = f->bkt;
328     
329     	for (fp = &b->ht[from_hash(h>>16)]; *fp; fp = &(*fp)->next) {
330     		if (*fp == f) {
331     			unsigned long cl;
332     
333     			tcf_tree_lock(tp);
334     			*fp = f->next;
335     			tcf_tree_unlock(tp);
336     
337     			route4_reset_fastmap(tp->q->dev, head, f->id);
338     
339     			if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0)
340     				tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
341     
342     #ifdef CONFIG_NET_CLS_POLICE
343     			tcf_police_release(f->police);
344     #endif
345     			kfree(f);
346     
347     			/* Strip tree */
348     
349     			for (i=0; i<=32; i++)
350     				if (b->ht[i])
351     					return 0;
352     
353     			/* OK, session has no flows */
354     			tcf_tree_lock(tp);
355     			head->table[to_hash(h)] = NULL;
356     			tcf_tree_unlock(tp);
357     
358     			kfree(b);
359     			return 0;
360     		}
361     	}
362     	return 0;
363     }
364     
365     static int route4_change(struct tcf_proto *tp, unsigned long base,
366     		       u32 handle,
367     		       struct rtattr **tca,
368     		       unsigned long *arg)
369     {
370     	struct route4_head *head = tp->root;
371     	struct route4_filter *f, *f1, **ins_f;
372     	struct route4_bucket *b;
373     	struct rtattr *opt = tca[TCA_OPTIONS-1];
374     	struct rtattr *tb[TCA_ROUTE4_MAX];
375     	unsigned h1, h2;
376     	int err;
377     
378     	if (opt == NULL)
379     		return handle ? -EINVAL : 0;
380     
381     	if (rtattr_parse(tb, TCA_ROUTE4_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0)
382     		return -EINVAL;
383     
384     	if ((f = (struct route4_filter*)*arg) != NULL) {
385     		/* Node exists: adjust only classid */
386     
387     		if (f->handle != handle && handle)
388     			return -EINVAL;
389     		if (tb[TCA_ROUTE4_CLASSID-1]) {
390     			unsigned long cl;
391     
392     			f->res.classid = *(u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID-1]);
393     			cl = cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
394     			if (cl)
395     				tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
396     		}
397     #ifdef CONFIG_NET_CLS_POLICE
398     		if (tb[TCA_ROUTE4_POLICE-1]) {
399     			struct tcf_police *police = tcf_police_locate(tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]);
400     
401     			tcf_tree_lock(tp);
402     			police = xchg(&f->police, police);
403     			tcf_tree_unlock(tp);
404     
405     			tcf_police_release(police);
406     		}
407     #endif
408     		return 0;
409     	}
410     
411     	/* Now more serious part... */
412     
413     	if (head == NULL) {
414     		head = kmalloc(sizeof(struct route4_head), GFP_KERNEL);
415     		if (head == NULL)
416     			return -ENOBUFS;
417     		memset(head, 0, sizeof(struct route4_head));
418     
419     		tcf_tree_lock(tp);
420     		tp->root = head;
421     		tcf_tree_unlock(tp);
422     	}
423     
424     	f = kmalloc(sizeof(struct route4_filter), GFP_KERNEL);
425     	if (f == NULL)
426     		return -ENOBUFS;
427     
428     	memset(f, 0, sizeof(*f));
429     
430     	err = -EINVAL;
431     	f->handle = 0x8000;
432     	if (tb[TCA_ROUTE4_TO-1]) {
433     		if (handle&0x8000)
434     			goto errout;
435     		if (RTA_PAYLOAD(tb[TCA_ROUTE4_TO-1]) < 4)
436     			goto errout;
437     		f->id = *(u32*)RTA_DATA(tb[TCA_ROUTE4_TO-1]);
438     		if (f->id > 0xFF)
439     			goto errout;
440     		f->handle = f->id;
441     	}
442     	if (tb[TCA_ROUTE4_FROM-1]) {
443     		u32 sid;
444     		if (tb[TCA_ROUTE4_IIF-1])
445     			goto errout;
446     		if (RTA_PAYLOAD(tb[TCA_ROUTE4_FROM-1]) < 4)
447     			goto errout;
448     		sid = (*(u32*)RTA_DATA(tb[TCA_ROUTE4_FROM-1]));
449     		if (sid > 0xFF)
450     			goto errout;
451     		f->handle |= sid<<16;
452     		f->id |= sid<<16;
453     	} else if (tb[TCA_ROUTE4_IIF-1]) {
454     		if (RTA_PAYLOAD(tb[TCA_ROUTE4_IIF-1]) < 4)
455     			goto errout;
456     		f->iif = *(u32*)RTA_DATA(tb[TCA_ROUTE4_IIF-1]);
457     		if (f->iif > 0x7FFF)
458     			goto errout;
459     		f->handle |= (f->iif|0x8000)<<16;
460     	} else
461     		f->handle |= 0xFFFF<<16;
462     
463     	if (handle) {
464     		f->handle |= handle&0x7F00;
465     		if (f->handle != handle)
466     			goto errout;
467     	}
468     
469     	if (tb[TCA_ROUTE4_CLASSID-1]) {
470     		if (RTA_PAYLOAD(tb[TCA_ROUTE4_CLASSID-1]) < 4)
471     			goto errout;
472     		f->res.classid = *(u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID-1]);
473     	}
474     
475     	h1 = to_hash(f->handle);
476     	if ((b = head->table[h1]) == NULL) {
477     		err = -ENOBUFS;
478     		b = kmalloc(sizeof(struct route4_bucket), GFP_KERNEL);
479     		if (b == NULL)
480     			goto errout;
481     		memset(b, 0, sizeof(*b));
482     
483     		tcf_tree_lock(tp);
484     		head->table[h1] = b;
485     		tcf_tree_unlock(tp);
486     	}
487     	f->bkt = b;
488     
489     	err = -EEXIST;
490     	h2 = from_hash(f->handle>>16);
491     	for (ins_f = &b->ht[h2]; (f1=*ins_f) != NULL; ins_f = &f1->next) {
492     		if (f->handle < f1->handle)
493     			break;
494     		if (f1->handle == f->handle)
495     			goto errout;
496     	}
497     
498     	cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
499     #ifdef CONFIG_NET_CLS_POLICE
500     	if (tb[TCA_ROUTE4_POLICE-1])
501     		f->police = tcf_police_locate(tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]);
502     #endif
503     
504     	f->next = f1;
505     	tcf_tree_lock(tp);
506     	*ins_f = f;
507     	tcf_tree_unlock(tp);
508     
509     	route4_reset_fastmap(tp->q->dev, head, f->id);
510     	*arg = (unsigned long)f;
511     	return 0;
512     
513     errout:
514     	if (f)
515     		kfree(f);
516     	return err;
517     }
518     
519     static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg)
520     {
521     	struct route4_head *head = tp->root;
522     	unsigned h, h1;
523     
524     	if (head == NULL)
525     		arg->stop = 1;
526     
527     	if (arg->stop)
528     		return;
529     
530     	for (h = 0; h <= 256; h++) {
531     		struct route4_bucket *b = head->table[h];
532     
533     		if (b) {
534     			for (h1 = 0; h1 <= 32; h1++) {
535     				struct route4_filter *f;
536     
537     				for (f = b->ht[h1]; f; f = f->next) {
538     					if (arg->count < arg->skip) {
539     						arg->count++;
540     						continue;
541     					}
542     					if (arg->fn(tp, (unsigned long)f, arg) < 0) {
543     						arg->stop = 1;
544     						break;
545     					}
546     					arg->count++;
547     				}
548     			}
549     		}
550     	}
551     }
552     
553     #ifdef CONFIG_RTNETLINK
554     static int route4_dump(struct tcf_proto *tp, unsigned long fh,
555     		       struct sk_buff *skb, struct tcmsg *t)
556     {
557     	struct route4_filter *f = (struct route4_filter*)fh;
558     	unsigned char	 *b = skb->tail;
559     	struct rtattr *rta;
560     	u32 id;
561     
562     	if (f == NULL)
563     		return skb->len;
564     
565     	t->tcm_handle = f->handle;
566     
567     	rta = (struct rtattr*)b;
568     	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
569     
570     	if (!(f->handle&0x8000)) {
571     		id = f->id&0xFF;
572     		RTA_PUT(skb, TCA_ROUTE4_TO, sizeof(id), &id);
573     	}
574     	if (f->handle&0x80000000) {
575     		if ((f->handle>>16) != 0xFFFF)
576     			RTA_PUT(skb, TCA_ROUTE4_IIF, sizeof(f->iif), &f->iif);
577     	} else {
578     		id = f->id>>16;
579     		RTA_PUT(skb, TCA_ROUTE4_FROM, sizeof(id), &id);
580     	}
581     	if (f->res.classid)
582     		RTA_PUT(skb, TCA_ROUTE4_CLASSID, 4, &f->res.classid);
583     #ifdef CONFIG_NET_CLS_POLICE
584     	if (f->police) {
585     		struct rtattr * p_rta = (struct rtattr*)skb->tail;
586     
587     		RTA_PUT(skb, TCA_ROUTE4_POLICE, 0, NULL);
588     
589     		if (tcf_police_dump(skb, f->police) < 0)
590     			goto rtattr_failure;
591     
592     		p_rta->rta_len = skb->tail - (u8*)p_rta;
593     	}
594     #endif
595     
596     	rta->rta_len = skb->tail - b;
597     #ifdef CONFIG_NET_CLS_POLICE
598     	if (f->police) {
599     		if (qdisc_copy_stats(skb, &f->police->stats))
600     			goto rtattr_failure;
601     	}
602     #endif
603     	return skb->len;
604     
605     rtattr_failure:
606     	skb_trim(skb, b - skb->data);
607     	return -1;
608     }
609     #endif
610     
611     struct tcf_proto_ops cls_route4_ops = {
612     	NULL,
613     	"route",
614     	route4_classify,
615     	route4_init,
616     	route4_destroy,
617     
618     	route4_get,
619     	route4_put,
620     	route4_change,
621     	route4_delete,
622     	route4_walk,
623     #ifdef CONFIG_RTNETLINK
624     	route4_dump
625     #else
626     	NULL
627     #endif
628     };
629     
630     #ifdef MODULE
631     int init_module(void)
632     {
633     	return register_tcf_proto_ops(&cls_route4_ops);
634     }
635     
636     void cleanup_module(void)
637     {
638     	unregister_tcf_proto_ops(&cls_route4_ops);
639     }
640     #endif
641