1 diff -urN ../v2.2.21/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
2 --- ../v2.2.21/linux/include/linux/netdevice.h Sun Nov 4 10:16:15 2001
3 +++ linux/include/linux/netdevice.h Wed Jul 31 00:00:59 2002
6 struct Qdisc *qdisc_sleeping;
7 struct Qdisc *qdisc_list;
8 + struct Qdisc *qdisc_ingress;
9 unsigned long tx_queue_len; /* Max frames per queue allowed */
12 diff -urN ../v2.2.21/linux/include/linux/pkt_cls.h linux/include/linux/pkt_cls.h
13 --- ../v2.2.21/linux/include/linux/pkt_cls.h Sat Oct 21 12:10:47 2000
14 +++ linux/include/linux/pkt_cls.h Wed Jul 31 00:00:59 2002
17 #define TCA_FW_MAX TCA_FW_POLICE
19 +/* TC index filter */
27 + TCA_TCINDEX_FALL_THROUGH,
28 + TCA_TCINDEX_CLASSID,
32 +#define TCA_TCINDEX_MAX TCA_TCINDEX_POLICE
36 diff -urN ../v2.2.21/linux/include/linux/pkt_sched.h linux/include/linux/pkt_sched.h
37 --- ../v2.2.21/linux/include/linux/pkt_sched.h Tue Apr 28 18:10:10 1998
38 +++ linux/include/linux/pkt_sched.h Sun Aug 4 14:54:40 2002
41 #define TC_H_UNSPEC (0U)
42 #define TC_H_ROOT (0xFFFFFFFFU)
43 +#define TC_H_INGRESS (0xFFFFFFF1U)
48 unsigned char Wlog; /* log(W) */
49 unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
50 unsigned char Scell_log; /* cell size for idle damping */
51 + unsigned char flags;
57 + __u32 early; /* Early drops */
58 + __u32 pdrop; /* Drops due to queue limits */
59 + __u32 other; /* Drops due to drop() calls */
60 + __u32 marked; /* Marked packets */
75 +#define TCA_SET_OFF TCA_GRED_PARMS
78 + __u32 limit; /* HARD maximal queue length (bytes)
80 + __u32 qth_min; /* Min average length threshold (bytes)
82 + __u32 qth_max; /* Max average length threshold (bytes)
84 + __u32 DP; /* upto 2^32 DPs */
92 + unsigned char Wlog; /* log(W) */
93 + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
94 + unsigned char Scell_log; /* cell size for idle damping */
95 + __u8 prio; /* prio of this VQ */
111 #define TCA_CBQ_MAX TCA_CBQ_POLICE
114 +/* dsmark section */
118 + TCA_DSMARK_INDICES,
119 + TCA_DSMARK_DEFAULT_INDEX,
120 + TCA_DSMARK_SET_TC_INDEX,
125 +#define TCA_DSMARK_MAX TCA_DSMARK_VALUE
130 diff -urN ../v2.2.21/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
131 --- ../v2.2.21/linux/include/linux/skbuff.h Sat Oct 21 12:11:03 2000
132 +++ linux/include/linux/skbuff.h Wed Jul 31 00:00:59 2002
138 +#ifdef CONFIG_NET_SCHED
139 + __u32 tc_index; /* traffic control index */
142 #if defined(CONFIG_ATM) && !defined(CONFIG_ATM_SKB)
144 /* ----- For updated drivers ----------------------------------------------- */
145 diff -urN ../v2.2.21/linux/include/net/dsfield.h linux/include/net/dsfield.h
146 --- ../v2.2.21/linux/include/net/dsfield.h Thu Jan 1 00:00:00 1970
147 +++ linux/include/net/dsfield.h Wed Jul 31 00:00:59 2002
149 +/* include/net/dsfield.h - Manipulation of the Differentiated Services field */
151 +/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
154 +#ifndef __NET_DSFIELD_H
155 +#define __NET_DSFIELD_H
157 +#include <linux/types.h>
158 +#include <linux/ip.h>
159 +#include <linux/ipv6.h>
160 +#include <asm/byteorder.h>
163 +extern __inline__ __u8 ipv4_get_dsfield(struct iphdr *iph)
169 +extern __inline__ __u8 ipv6_get_dsfield(struct ipv6hdr *ipv6h)
171 + return ntohs(*(__u16 *) ipv6h) >> 4;
175 +extern __inline__ void ipv4_change_dsfield(struct iphdr *iph,__u8 mask,
178 + __u32 check = ntohs(iph->check);
181 + dsfield = (iph->tos & mask) | value;
183 + if ((check+1) >> 16) check = (check+1) & 0xffff;
185 + check += check >> 16; /* adjust carry */
186 + iph->check = htons(check);
187 + iph->tos = dsfield;
191 +extern __inline__ void ipv6_change_dsfield(struct ipv6hdr *ipv6h,__u8 mask,
196 + tmp = ntohs(*(__u16 *) ipv6h);
197 + tmp = (tmp & ((mask << 4) | 0xf00f)) | (value << 4);
198 + *(__u16 *) ipv6h = htons(tmp);
202 +#if 0 /* put this later into asm-i386 or such ... */
204 +extern __inline__ void ip_change_dsfield(struct iphdr *iph,__u16 dsfield)
208 + __asm__ __volatile__("
221 + : "r" (iph), "r" (dsfield)
228 diff -urN ../v2.2.21/linux/include/net/pkt_cls.h linux/include/net/pkt_cls.h
229 --- ../v2.2.21/linux/include/net/pkt_cls.h Sat Oct 21 12:11:28 2000
230 +++ linux/include/net/pkt_cls.h Thu Aug 1 00:12:52 2002
235 -extern __inline__ unsigned long cls_set_class(unsigned long *clp, unsigned long cl)
237 - unsigned long old_cl;
245 extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
246 extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
248 diff -urN ../v2.2.21/linux/include/net/pkt_sched.h linux/include/net/pkt_sched.h
249 --- ../v2.2.21/linux/include/net/pkt_sched.h Sat Oct 21 12:10:57 2000
250 +++ linux/include/net/pkt_sched.h Wed Aug 7 00:23:36 2002
252 #define PSCHED_CLOCK_SOURCE PSCHED_JIFFIES
254 #include <linux/pkt_sched.h>
255 +#include <linux/ip.h>
256 #include <net/pkt_cls.h>
261 #define TCQ_F_BUILTIN 1
262 #define TCQ_F_THROTTLED 2
263 +#define TCQ_F_INGRES 4
264 struct Qdisc_ops *ops;
267 @@ -106,6 +108,111 @@
271 +#ifndef MODULE_LICENSE
272 +#define MODULE_LICENSE(X)
275 +#ifndef NET_XMIT_SUCCESS
276 +#define NET_XMIT_SUCCESS 0
277 +#define NET_XMIT_DROP 1 /* skb dropped */
278 +#define NET_XMIT_CN 2 /* congestion notification */
279 +#define NET_XMIT_POLICED 3 /* skb is shot by police */
280 +#define NET_XMIT_BYPASS 4 /* packet does not leave via dequeue;
281 + (TC use only - dev_queue_xmit
282 + returns this as NET_XMIT_SUCCESS) */
285 +#define likely(e) (e)
286 +#define unlikely(e) (e)
289 +#define min_t(type,x,y) \
290 + ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
291 +#define max_t(type,x,y) \
292 + ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
295 +static inline void list_del_init(struct list_head *entry)
297 + __list_del(entry->prev, entry->next);
298 + INIT_LIST_HEAD(entry);
301 +static inline void __skb_queue_purge(struct sk_buff_head *list)
303 + struct sk_buff *skb;
304 + while ((skb=__skb_dequeue(list))!=NULL)
307 +#define del_timer_sync(t) del_timer(t)
309 +#define netif_schedule qdisc_wakeup
310 +#define netif_queue_stopped(D) (D->tbusy)
312 +#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
315 +static inline void IP_ECN_set_ce(struct iphdr *iph)
317 + u32 check = iph->check;
318 + check += __constant_htons(0xFFFE);
319 + iph->check = check + (check>=0xFFFF);
323 +static inline void sch_tree_lock(struct Qdisc *q)
328 +static inline void sch_tree_unlock(struct Qdisc *q)
333 +static inline void tcf_tree_lock(struct tcf_proto *tp)
338 +static inline void tcf_tree_unlock(struct tcf_proto *tp)
343 +static inline void sch_dev_queue_lock(struct device *dev)
348 +static inline void sch_dev_queue_unlock(struct device *dev)
354 +static inline unsigned long
355 +cls_set_class(struct tcf_proto *tp, unsigned long *clp, unsigned long cl)
357 + unsigned long old_cl;
366 +static inline unsigned long
367 +__cls_set_class(unsigned long *clp, unsigned long cl)
369 + unsigned long old_cl;
378 Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
381 #define PSCHED_EXPORTLIST_2
383 -#if ~0UL == 0xFFFFFFFF
384 +#if BITS_PER_LONG <= 32
386 #define PSCHED_WATCHER unsigned long
390 #define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
392 -#if CPU == 586 || CPU == 686
393 +#ifdef CONFIG_X86_TSC
395 #define PSCHED_GET_TIME(stamp) \
398 #define PSCHED_TDIFF(tv1, tv2) (long)((tv1) - (tv2))
399 #define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) \
401 - long __delta = (tv1) - (tv2); \
402 - if ( __delta > (bound)) { __delta = (bound); guard; } \
403 + long long __delta = (tv1) - (tv2); \
404 + if ( __delta > (long long)(bound)) { __delta = (bound); guard; } \
409 struct tc_stats stats;
412 +extern int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st);
413 extern void tcf_police_destroy(struct tcf_police *p);
414 extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
415 extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
417 extern struct Qdisc_ops noop_qdisc_ops;
418 extern struct Qdisc_ops pfifo_qdisc_ops;
419 extern struct Qdisc_ops bfifo_qdisc_ops;
421 +extern int call_in_ingress(struct sk_buff *skb);
423 int register_qdisc(struct Qdisc_ops *qops);
424 int unregister_qdisc(struct Qdisc_ops *qops);
425 diff -urN ../v2.2.21/linux/net/core/skbuff.c linux/net/core/skbuff.c
426 --- ../v2.2.21/linux/net/core/skbuff.c Sat Oct 21 12:10:41 2000
427 +++ linux/net/core/skbuff.c Sun Aug 4 13:18:42 2002
429 #ifdef CONFIG_IP_FIREWALL
432 +#ifdef CONFIG_NET_SCHED
435 memset(skb->cb, 0, sizeof(skb->cb));
439 #ifdef CONFIG_IP_FIREWALL
440 n->fwmark = skb->fwmark;
442 +#ifdef CONFIG_NET_SCHED
443 + n->tc_index = skb->tc_index;
449 n->security=skb->security;
450 #ifdef CONFIG_IP_FIREWALL
451 n->fwmark = skb->fwmark;
453 +#ifdef CONFIG_NET_SCHED
454 + n->tc_index = skb->tc_index;
458 diff -urN ../v2.2.21/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c
459 --- ../v2.2.21/linux/net/ipv4/ip_input.c Sun Nov 4 10:16:16 2001
460 +++ linux/net/ipv4/ip_input.c Tue Aug 6 11:02:54 2002
462 * Jos Vos : Do accounting *before* call_in_firewall
463 * Willy Konynenberg : Transparent proxying support
464 * Stephan Uphoff : Check IP header length field
465 + * Jamal Hadi Salim : Ingress policer support
470 #include <linux/mroute.h>
471 #include <linux/netlink.h>
473 +#ifdef CONFIG_FIREWALL
474 +#if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE)
475 +#include <net/pkt_sched.h>
479 * SNMP management statistics
482 fwres = call_in_firewall(PF_INET, dev, iph, &rport, &skb);
483 if (fwres < FW_ACCEPT && fwres != FW_REJECT)
485 +#if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE)
486 + if (FW_ACCEPT != call_in_ingress(skb))
491 #endif /* CONFIG_FIREWALL */
493 diff -urN ../v2.2.21/linux/net/netsyms.c linux/net/netsyms.c
494 --- ../v2.2.21/linux/net/netsyms.c Sat Aug 4 12:52:33 2001
495 +++ linux/net/netsyms.c Tue Aug 6 10:40:17 2002
497 EXPORT_SYMBOL(unregister_qdisc);
498 EXPORT_SYMBOL(qdisc_get_rtab);
499 EXPORT_SYMBOL(qdisc_put_rtab);
500 +EXPORT_SYMBOL(qdisc_copy_stats);
501 #ifdef CONFIG_NET_ESTIMATOR
502 EXPORT_SYMBOL(qdisc_new_estimator);
503 EXPORT_SYMBOL(qdisc_kill_estimator);
505 EXPORT_SYMBOL(tcf_police_dump);
509 +#ifdef CONFIG_NET_SCH_INGRESS
510 +EXPORT_SYMBOL(call_in_ingress);
512 #ifdef CONFIG_NET_CLS
513 EXPORT_SYMBOL(register_tcf_proto_ops);
514 diff -urN ../v2.2.21/linux/net/sched/Config.in linux/net/sched/Config.in
515 --- ../v2.2.21/linux/net/sched/Config.in Sat Oct 21 12:10:47 2000
516 +++ linux/net/sched/Config.in Wed Jul 31 00:00:59 2002
518 tristate 'SFQ queue' CONFIG_NET_SCH_SFQ
519 tristate 'TEQL queue' CONFIG_NET_SCH_TEQL
520 tristate 'TBF queue' CONFIG_NET_SCH_TBF
521 +tristate 'GRED queue' CONFIG_NET_SCH_GRED
522 +tristate 'Diffserv field marker' CONFIG_NET_SCH_DSMARK
523 +tristate 'Ingress Qdisc/policing' CONFIG_NET_SCH_INGRESS
525 bool 'QoS support' CONFIG_NET_QOS
526 if [ "$CONFIG_NET_QOS" = "y" ]; then
527 bool 'Rate estimator' CONFIG_NET_ESTIMATOR
529 bool 'Packet classifier API' CONFIG_NET_CLS
530 if [ "$CONFIG_NET_CLS" = "y" ]; then
531 + tristate 'TC index classifier' CONFIG_NET_CLS_TCINDEX
532 tristate 'Routing table based classifier' CONFIG_NET_CLS_ROUTE4
533 if [ "$CONFIG_NET_CLS_ROUTE4" != "n" ]; then
534 define_bool CONFIG_NET_CLS_ROUTE y
536 if [ "$CONFIG_NET_QOS" = "y" ]; then
537 tristate 'Special RSVP classifier' CONFIG_NET_CLS_RSVP
538 tristate 'Special RSVP classifier for IPv6' CONFIG_NET_CLS_RSVP6
539 - bool 'Ingres traffic policing' CONFIG_NET_CLS_POLICE
540 + bool 'Traffic policing (needed for in/egress)' CONFIG_NET_CLS_POLICE
544 diff -urN ../v2.2.21/linux/net/sched/Makefile linux/net/sched/Makefile
545 --- ../v2.2.21/linux/net/sched/Makefile Sat Oct 21 12:10:47 2000
546 +++ linux/net/sched/Makefile Wed Jul 31 00:00:59 2002
551 +ifeq ($(CONFIG_NET_SCH_INGRESS), y)
552 +O_OBJS += sch_ingress.o
554 + ifeq ($(CONFIG_NET_SCH_INGRESS), m)
555 + M_OBJS += sch_ingress.o
559 ifeq ($(CONFIG_NET_SCH_CBQ), y)
564 ifeq ($(CONFIG_NET_SCH_TEQL), m)
569 +ifeq ($(CONFIG_NET_SCH_GRED), y)
570 +O_OBJS += sch_gred.o
572 + ifeq ($(CONFIG_NET_SCH_GRED), m)
573 + M_OBJS += sch_gred.o
577 +ifeq ($(CONFIG_NET_SCH_DSMARK), y)
578 +O_OBJS += sch_dsmark.o
580 + ifeq ($(CONFIG_NET_SCH_DSMARK), m)
581 + M_OBJS += sch_dsmark.o
585 +ifeq ($(CONFIG_NET_CLS_TCINDEX), y)
586 +O_OBJS += cls_tcindex.o
588 + ifeq ($(CONFIG_NET_CLS_TCINDEX), m)
589 + M_OBJS += cls_tcindex.o
593 diff -urN ../v2.2.21/linux/net/sched/cls_api.c linux/net/sched/cls_api.c
594 --- ../v2.2.21/linux/net/sched/cls_api.c Sat Oct 21 12:10:50 2000
595 +++ linux/net/sched/cls_api.c Sun Aug 4 16:57:48 2002
600 + sch_dev_queue_lock(dev);
603 + sch_dev_queue_unlock(dev);
604 } else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
609 #ifdef CONFIG_NET_CLS_RSVP
610 INIT_TC_FILTER(rsvp);
612 +#ifdef CONFIG_NET_CLS_TCINDEX
613 + INIT_TC_FILTER(tcindex);
615 #ifdef CONFIG_NET_CLS_RSVP6
616 INIT_TC_FILTER(rsvp6);
617 diff -urN ../v2.2.21/linux/net/sched/cls_fw.c linux/net/sched/cls_fw.c
618 --- ../v2.2.21/linux/net/sched/cls_fw.c Sat Oct 21 12:10:57 2000
619 +++ linux/net/sched/cls_fw.c Thu Aug 1 00:34:59 2002
622 head->ht[h] = f->next;
624 - if ((cl = cls_set_class(&f->res.class, 0)) != 0)
625 + if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
626 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
627 #ifdef CONFIG_NET_CLS_POLICE
628 tcf_police_release(f->police);
629 @@ -161,10 +161,11 @@
636 + tcf_tree_unlock(tp);
638 - if ((cl = cls_set_class(&f->res.class, 0)) != 0)
639 + if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0)
640 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
641 #ifdef CONFIG_NET_CLS_POLICE
642 tcf_police_release(f->police);
645 f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]);
646 cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid);
647 - cl = cls_set_class(&f->res.class, cl);
648 + cl = cls_set_class(tp, &f->res.class, cl);
650 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
653 if (tb[TCA_FW_POLICE-1]) {
654 struct tcf_police *police = tcf_police_locate(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1]);
657 police = xchg(&f->police, police);
659 + tcf_tree_unlock(tp);
661 tcf_police_release(police);
665 memset(head, 0, sizeof(*head));
670 + tcf_tree_unlock(tp);
673 f = kmalloc(sizeof(struct fw_filter), GFP_KERNEL);
675 if (RTA_PAYLOAD(tb[TCA_FW_CLASSID-1]) != 4)
677 f->res.classid = *(u32*)RTA_DATA(tb[TCA_FW_CLASSID-1]);
678 - cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
679 + cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
682 #ifdef CONFIG_NET_CLS_POLICE
686 f->next = head->ht[fw_hash(handle)];
689 head->ht[fw_hash(handle)] = f;
690 + tcf_tree_unlock(tp);
692 *arg = (unsigned long)f;
698 -#ifdef CONFIG_RTNETLINK
699 static int fw_dump(struct tcf_proto *tp, unsigned long fh,
700 struct sk_buff *skb, struct tcmsg *t)
703 rta->rta_len = skb->tail - b;
704 #ifdef CONFIG_NET_CLS_POLICE
706 - RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), &f->police->stats);
707 + if (qdisc_copy_stats(skb, &f->police->stats))
708 + goto rtattr_failure;
713 skb_trim(skb, b - skb->data);
719 struct tcf_proto_ops cls_fw_ops = {
725 -#ifdef CONFIG_RTNETLINK
733 diff -urN ../v2.2.21/linux/net/sched/cls_route.c linux/net/sched/cls_route.c
734 --- ../v2.2.21/linux/net/sched/cls_route.c Sat Oct 21 12:10:50 2000
735 +++ linux/net/sched/cls_route.c Sun Aug 4 17:08:47 2002
740 -static void route4_reset_fastmap(struct route4_head *head, u32 id)
741 +static void route4_reset_fastmap(struct device *dev, struct route4_head *head, u32 id)
744 + sch_dev_queue_lock(dev);
745 memset(head->fastmap, 0, sizeof(head->fastmap));
747 + sch_dev_queue_unlock(dev);
750 static void __inline__
755 - if ((cl = cls_set_class(&f->res.class, 0)) != 0)
756 + if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
757 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
758 #ifdef CONFIG_NET_CLS_POLICE
759 tcf_police_release(f->police);
760 @@ -316,25 +316,27 @@
762 struct route4_head *head = (struct route4_head*)tp->root;
763 struct route4_filter **fp, *f = (struct route4_filter*)arg;
764 - unsigned h = f->handle;
766 struct route4_bucket *b;
775 for (fp = &b->ht[from_hash(h>>16)]; *fp; fp = &(*fp)->next) {
782 + tcf_tree_unlock(tp);
784 - route4_reset_fastmap(head, f->id);
785 + route4_reset_fastmap(tp->q->dev, head, f->id);
787 - if ((cl = cls_set_class(&f->res.class, 0)) != 0)
788 + if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0)
789 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
791 #ifdef CONFIG_NET_CLS_POLICE
795 /* OK, session has no flows */
797 head->table[to_hash(h)] = NULL;
799 + tcf_tree_unlock(tp);
806 f->res.classid = *(u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID-1]);
807 - cl = cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
808 + cl = cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
810 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
813 if (tb[TCA_ROUTE4_POLICE-1]) {
814 struct tcf_police *police = tcf_police_locate(tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]);
817 police = xchg(&f->police, police);
819 + tcf_tree_unlock(tp);
821 tcf_police_release(police);
825 memset(head, 0, sizeof(struct route4_head));
830 + tcf_tree_unlock(tp);
833 f = kmalloc(sizeof(struct route4_filter), GFP_KERNEL);
836 memset(b, 0, sizeof(*b));
841 + tcf_tree_unlock(tp);
845 @@ -489,17 +495,18 @@
849 - cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
850 + cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
851 #ifdef CONFIG_NET_CLS_POLICE
852 if (tb[TCA_ROUTE4_POLICE-1])
853 f->police = tcf_police_locate(tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]);
860 + tcf_tree_unlock(tp);
862 - route4_reset_fastmap(head, f->id);
863 + route4_reset_fastmap(tp->q->dev, head, f->id);
864 *arg = (unsigned long)f;
871 -#ifdef CONFIG_RTNETLINK
872 static int route4_dump(struct tcf_proto *tp, unsigned long fh,
873 struct sk_buff *skb, struct tcmsg *t)
876 rta->rta_len = skb->tail - b;
877 #ifdef CONFIG_NET_CLS_POLICE
879 - RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), &f->police->stats);
880 + if (qdisc_copy_stats(skb, &f->police->stats))
881 + goto rtattr_failure;
886 skb_trim(skb, b - skb->data);
891 struct tcf_proto_ops cls_route4_ops = {
897 -#ifdef CONFIG_RTNETLINK
906 unregister_tcf_proto_ops(&cls_route4_ops);
909 +MODULE_LICENSE("GPL");
910 diff -urN ../v2.2.21/linux/net/sched/cls_rsvp.c linux/net/sched/cls_rsvp.c
911 --- ../v2.2.21/linux/net/sched/cls_rsvp.c Thu Apr 30 05:46:59 1998
912 +++ linux/net/sched/cls_rsvp.c Tue Nov 13 01:29:33 2001
914 #define RSVP_OPS cls_rsvp_ops
916 #include "cls_rsvp.h"
917 +MODULE_LICENSE("GPL");
918 diff -urN ../v2.2.21/linux/net/sched/cls_rsvp.h linux/net/sched/cls_rsvp.h
919 --- ../v2.2.21/linux/net/sched/cls_rsvp.h Sat Oct 21 12:10:57 2000
920 +++ linux/net/sched/cls_rsvp.h Sun Mar 31 03:18:28 2002
925 - if ((cl = cls_set_class(&f->res.class, 0)) != 0)
926 + if ((cl = __cls_set_class(&f->res.class, 0)) != 0)
927 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
928 #ifdef CONFIG_NET_CLS_POLICE
929 tcf_police_release(f->police);
930 @@ -310,10 +310,11 @@
937 + tcf_tree_unlock(tp);
939 - if ((cl = cls_set_class(&f->res.class, 0)) != 0)
940 + if ((cl = cls_set_class(tp, &f->res.class, 0)) != 0)
941 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
943 #ifdef CONFIG_NET_CLS_POLICE
945 for (sp = &((struct rsvp_head*)tp->root)->ht[h&0xFF];
946 *sp; sp = &(*sp)->next) {
951 + tcf_tree_unlock(tp);
958 f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]);
959 - cl = cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
960 + cl = cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
962 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
965 if (tb[TCA_RSVP_POLICE-1]) {
966 struct tcf_police *police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]);
969 police = xchg(&f->police, police);
971 + tcf_tree_unlock(tp);
973 tcf_police_release(police);
978 if (f->tunnelhdr == 0)
979 - cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
980 + cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));
981 #ifdef CONFIG_NET_CLS_POLICE
982 if (tb[TCA_RSVP_POLICE-1])
983 f->police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]);
988 -#ifdef CONFIG_RTNETLINK
989 static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
990 struct sk_buff *skb, struct tcmsg *t)
993 rta->rta_len = skb->tail - b;
994 #ifdef CONFIG_NET_CLS_POLICE
996 - RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), &f->police->stats);
997 + if (qdisc_copy_stats(skb, &f->police->stats))
998 + goto rtattr_failure;
1003 skb_trim(skb, b - skb->data);
1008 struct tcf_proto_ops RSVP_OPS = {
1010 @@ -682,11 +684,7 @@
1014 -#ifdef CONFIG_RTNETLINK
1022 diff -urN ../v2.2.21/linux/net/sched/cls_rsvp6.c linux/net/sched/cls_rsvp6.c
1023 --- ../v2.2.21/linux/net/sched/cls_rsvp6.c Thu Apr 30 05:46:59 1998
1024 +++ linux/net/sched/cls_rsvp6.c Tue Nov 13 01:29:33 2001
1026 #define RSVP_OPS cls_rsvp6_ops
1028 #include "cls_rsvp.h"
1029 +MODULE_LICENSE("GPL");
1030 diff -urN ../v2.2.21/linux/net/sched/cls_tcindex.c linux/net/sched/cls_tcindex.c
1031 --- ../v2.2.21/linux/net/sched/cls_tcindex.c Thu Jan 1 00:00:00 1970
1032 +++ linux/net/sched/cls_tcindex.c Sun Mar 31 03:18:28 2002
1035 + * net/sched/cls_tcindex.c Packet classifier for skb->tc_index
1037 + * Written 1998,1999 by Werner Almesberger, EPFL ICA
1040 +#include <linux/config.h>
1041 +#include <linux/module.h>
1042 +#include <linux/types.h>
1043 +#include <linux/kernel.h>
1044 +#include <linux/skbuff.h>
1045 +#include <linux/errno.h>
1046 +#include <linux/netdevice.h>
1047 +#include <net/ip.h>
1048 +#include <net/pkt_sched.h>
1049 +#include <net/route.h>
1053 + * Not quite sure if we need all the xchgs Alexey uses when accessing things.
1054 + * Can always add them later ... :)
1058 + * Passing parameters to the root seems to be done more awkwardly than really
1059 + * necessary. At least, u32 doesn't seem to use such dirty hacks. To be
1060 + * verified. FIXME.
1063 +#define PERFECT_HASH_THRESHOLD 64 /* use perfect hash if not bigger */
1064 +#define DEFAULT_HASH_SIZE 64 /* optimized for diffserv */
1067 +#if 1 /* control */
1068 +#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
1070 +#define DPRINTK(format,args...)
1074 +#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
1076 +#define D2PRINTK(format,args...)
1080 +#define PRIV(tp) ((struct tcindex_data *) (tp)->root)
1083 +struct tcindex_filter_result {
1084 + struct tcf_police *police;
1085 + struct tcf_result res;
1088 +struct tcindex_filter {
1090 + struct tcindex_filter_result result;
1091 + struct tcindex_filter *next;
1095 +struct tcindex_data {
1096 + struct tcindex_filter_result *perfect; /* perfect hash; NULL if none */
1097 + struct tcindex_filter **h; /* imperfect hash; only used if !perfect;
1099 + __u16 mask; /* AND key with mask */
1100 + int shift; /* shift ANDed key to the right */
1101 + int hash; /* hash table size; 0 if undefined */
1102 + int alloc_hash; /* allocated size */
1103 + int fall_through; /* 0: only classify if explicit match */
1107 +static struct tcindex_filter_result *lookup(struct tcindex_data *p,__u16 key)
1109 + struct tcindex_filter *f;
1112 + return p->perfect[key].res.class ? p->perfect+key : NULL;
1115 + for (f = p->h[key % p->hash]; f; f = f->next) {
1116 + if (f->key == key)
1117 + return &f->result;
1123 +static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
1124 + struct tcf_result *res)
1126 + struct tcindex_data *p = PRIV(tp);
1127 + struct tcindex_filter_result *f;
1129 + D2PRINTK("tcindex_classify(skb %p,tp %p,res %p),p %p\n",skb,tp,res,p);
1131 + f = lookup(p,(skb->tc_index & p->mask) >> p->shift);
1133 + if (!p->fall_through)
1135 + res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle),
1136 + (skb->tc_index& p->mask) >> p->shift);
1138 + D2PRINTK("alg 0x%x\n",res->classid);
1142 + D2PRINTK("map 0x%x\n",res->classid);
1143 +#ifdef CONFIG_NET_CLS_POLICE
1147 + result = tcf_police(skb,f->police);
1148 + D2PRINTK("police %d\n",res);
1156 +static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
1158 + struct tcindex_data *p = PRIV(tp);
1159 + struct tcindex_filter_result *r;
1161 + DPRINTK("tcindex_get(tp %p,handle 0x%08x)\n",tp,handle);
1162 + if (p->perfect && handle >= p->alloc_hash)
1164 + r = lookup(PRIV(tp),handle);
1165 + return r && r->res.class ? (unsigned long) r : 0;
1169 +static void tcindex_put(struct tcf_proto *tp, unsigned long f)
1171 + DPRINTK("tcindex_put(tp %p,f 0x%lx)\n",tp,f);
1175 +static int tcindex_init(struct tcf_proto *tp)
1177 + struct tcindex_data *p;
1179 + DPRINTK("tcindex_init(tp %p)\n",tp);
1180 + MOD_INC_USE_COUNT;
1181 + p = kmalloc(sizeof(struct tcindex_data),GFP_KERNEL);
1183 + MOD_DEC_USE_COUNT;
1187 + p->perfect = NULL;
1192 + p->fall_through = 1;
1197 +static int tcindex_delete(struct tcf_proto *tp, unsigned long arg)
1199 + struct tcindex_data *p = PRIV(tp);
1200 + struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg;
1201 + struct tcindex_filter *f = NULL;
1204 + DPRINTK("tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n",tp,arg,p,f);
1206 + if (!r->res.class)
1210 + struct tcindex_filter **walk = NULL;
1212 + for (i = 0; i < p->hash; i++)
1213 + for (walk = p->h+i; *walk; walk = &(*walk)->next)
1214 + if (&(*walk)->result == r)
1220 + tcf_tree_lock(tp);
1222 + tcf_tree_unlock(tp);
1224 + cl = __cls_set_class(&r->res.class,0);
1226 + tp->q->ops->cl_ops->unbind_tcf(tp->q,cl);
1227 +#ifdef CONFIG_NET_CLS_POLICE
1228 + tcf_police_release(r->police);
1237 + * There are no parameters for tcindex_init, so we overload tcindex_change
1241 +static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
1242 + struct rtattr **tca,unsigned long *arg)
1244 + struct tcindex_filter_result new_filter_result = {
1245 + NULL, /* no policing */
1246 + { 0,0 }, /* no classification */
1248 + struct rtattr *opt = tca[TCA_OPTIONS-1];
1249 + struct rtattr *tb[TCA_TCINDEX_MAX];
1250 + struct tcindex_data *p = PRIV(tp);
1251 + struct tcindex_filter *f;
1252 + struct tcindex_filter_result *r = (struct tcindex_filter_result *) *arg;
1253 + struct tcindex_filter **walk;
1257 + DPRINTK("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
1258 + "p %p,r %p\n",tp,handle,tca,arg,opt,p,r);
1260 + DPRINTK("*arg = 0x%lx\n",*arg);
1263 + if (rtattr_parse(tb,TCA_TCINDEX_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0)
1265 + if (!tb[TCA_TCINDEX_HASH-1]) {
1268 + if (RTA_PAYLOAD(tb[TCA_TCINDEX_HASH-1]) < sizeof(int))
1270 + hash = *(int *) RTA_DATA(tb[TCA_TCINDEX_HASH-1]);
1272 + if (!tb[TCA_TCINDEX_MASK-1]) {
1275 + if (RTA_PAYLOAD(tb[TCA_TCINDEX_MASK-1]) < sizeof(__u16))
1277 + mask = *(__u16 *) RTA_DATA(tb[TCA_TCINDEX_MASK-1]);
1279 + if (!tb[TCA_TCINDEX_SHIFT-1])
1282 + if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(__u16))
1284 + shift = *(int *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]);
1286 + if (p->perfect && hash <= (mask >> shift))
1288 + if (p->perfect && hash > p->alloc_hash)
1290 + if (p->h && hash != p->alloc_hash)
1295 + if (tb[TCA_TCINDEX_FALL_THROUGH-1]) {
1296 + if (RTA_PAYLOAD(tb[TCA_TCINDEX_FALL_THROUGH-1]) < sizeof(int))
1299 + *(int *) RTA_DATA(tb[TCA_TCINDEX_FALL_THROUGH-1]);
1301 + DPRINTK("classid/police %p/%p\n",tb[TCA_TCINDEX_CLASSID-1],
1302 + tb[TCA_TCINDEX_POLICE-1]);
1303 + if (!tb[TCA_TCINDEX_CLASSID-1] && !tb[TCA_TCINDEX_POLICE-1])
1306 + if ((mask >> shift) < PERFECT_HASH_THRESHOLD) {
1307 + p->hash = (mask >> shift)+1;
1309 + p->hash = DEFAULT_HASH_SIZE;
1312 + if (!p->perfect && !p->h) {
1313 + p->alloc_hash = p->hash;
1314 + DPRINTK("hash %d mask %d\n",p->hash,p->mask);
1315 + if (p->hash > (mask >> shift)) {
1316 + p->perfect = kmalloc(p->hash*
1317 + sizeof(struct tcindex_filter_result),GFP_KERNEL);
1320 + memset(p->perfect, 0,
1321 + p->hash * sizeof(struct tcindex_filter_result));
1323 + p->h = kmalloc(p->hash*sizeof(struct tcindex_filter *),
1327 + memset(p->h, 0, p->hash*sizeof(struct tcindex_filter *));
1331 + * Note: this could be as restrictive as
1332 + * if (handle & ~(mask >> shift))
1333 + * but then, we'd fail handles that may become valid after some
1334 + * future mask change. While this is extremely unlikely to ever
1335 + * matter, the check below is safer (and also more
1336 + * backwards-compatible).
1338 + if (p->perfect && handle >= p->alloc_hash)
1341 + r = p->perfect+handle;
1343 + r = lookup(p,handle);
1344 + DPRINTK("r=%p\n",r);
1346 + r = &new_filter_result;
1348 + DPRINTK("r=%p\n",r);
1349 + if (tb[TCA_TCINDEX_CLASSID-1]) {
1350 + unsigned long cl = cls_set_class(tp,&r->res.class,0);
1353 + tp->q->ops->cl_ops->unbind_tcf(tp->q,cl);
1354 + r->res.classid = *(__u32 *) RTA_DATA(tb[TCA_TCINDEX_CLASSID-1]);
1355 + r->res.class = tp->q->ops->cl_ops->bind_tcf(tp->q,base,
1357 + if (!r->res.class) {
1358 + r->res.classid = 0;
1362 +#ifdef CONFIG_NET_CLS_POLICE
1364 + struct tcf_police *police;
1366 + police = tb[TCA_TCINDEX_POLICE-1] ?
1367 + tcf_police_locate(tb[TCA_TCINDEX_POLICE-1],NULL) : NULL;
1368 + tcf_tree_lock(tp);
1369 + police = xchg(&r->police,police);
1370 + tcf_tree_unlock(tp);
1371 + tcf_police_release(police);
1374 + if (r != &new_filter_result)
1376 + f = kmalloc(sizeof(struct tcindex_filter),GFP_KERNEL);
1380 + f->result = new_filter_result;
1382 + for (walk = p->h+(handle % p->hash); *walk; walk = &(*walk)->next)
1390 +static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
1392 + struct tcindex_data *p = PRIV(tp);
1393 + struct tcindex_filter *f,*next;
1396 + DPRINTK("tcindex_walk(tp %p,walker %p),p %p\n",tp,walker,p);
1398 + for (i = 0; i < p->hash; i++) {
1399 + if (!p->perfect[i].res.class)
1401 + if (walker->count >= walker->skip) {
1402 + if (walker->fn(tp,
1403 + (unsigned long) (p->perfect+i), walker)
1414 + for (i = 0; i < p->hash; i++) {
1415 + for (f = p->h[i]; f; f = next) {
1417 + if (walker->count >= walker->skip) {
1418 + if (walker->fn(tp,(unsigned long) &f->result,
1430 +static int tcindex_destroy_element(struct tcf_proto *tp,
1431 + unsigned long arg, struct tcf_walker *walker)
1433 + return tcindex_delete(tp,arg);
1437 +static void tcindex_destroy(struct tcf_proto *tp)
1439 + struct tcindex_data *p = PRIV(tp);
1440 + struct tcf_walker walker;
1442 + DPRINTK("tcindex_destroy(tp %p),p %p\n",tp,p);
1445 + walker.fn = &tcindex_destroy_element;
1446 + tcindex_walk(tp,&walker);
1448 + kfree(p->perfect);
1453 + MOD_DEC_USE_COUNT;
1457 +static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
1458 + struct sk_buff *skb, struct tcmsg *t)
1460 + struct tcindex_data *p = PRIV(tp);
1461 + struct tcindex_filter_result *r = (struct tcindex_filter_result *) fh;
1462 + unsigned char *b = skb->tail;
1463 + struct rtattr *rta;
1465 + DPRINTK("tcindex_dump(tp %p,fh 0x%lx,skb %p,t %p),p %p,r %p,b %p\n",
1466 + tp,fh,skb,t,p,r,b);
1467 + DPRINTK("p->perfect %p p->h %p\n",p->perfect,p->h);
1468 + rta = (struct rtattr *) b;
1469 + RTA_PUT(skb,TCA_OPTIONS,0,NULL);
1471 + t->tcm_handle = ~0; /* whatever ... */
1472 + RTA_PUT(skb,TCA_TCINDEX_HASH,sizeof(p->hash),&p->hash);
1473 + RTA_PUT(skb,TCA_TCINDEX_MASK,sizeof(p->mask),&p->mask);
1474 + RTA_PUT(skb,TCA_TCINDEX_SHIFT,sizeof(p->shift),&p->shift);
1475 + RTA_PUT(skb,TCA_TCINDEX_FALL_THROUGH,sizeof(p->fall_through),
1476 + &p->fall_through);
1479 + t->tcm_handle = r-p->perfect;
1481 + struct tcindex_filter *f;
1484 + t->tcm_handle = 0;
1485 + for (i = 0; !t->tcm_handle && i < p->hash; i++) {
1486 + for (f = p->h[i]; !t->tcm_handle && f;
1488 + if (&f->result == r)
1489 + t->tcm_handle = f->key;
1493 + DPRINTK("handle = %d\n",t->tcm_handle);
1495 + RTA_PUT(skb, TCA_TCINDEX_CLASSID, 4, &r->res.classid);
1496 +#ifdef CONFIG_NET_CLS_POLICE
1498 + struct rtattr *p_rta = (struct rtattr *) skb->tail;
1500 + RTA_PUT(skb,TCA_TCINDEX_POLICE,0,NULL);
1501 + if (tcf_police_dump(skb,r->police) < 0)
1502 + goto rtattr_failure;
1503 + p_rta->rta_len = skb->tail-(u8 *) p_rta;
1507 + rta->rta_len = skb->tail-b;
1511 + skb_trim(skb, b - skb->data);
1515 +struct tcf_proto_ops cls_tcindex_ops = {
1532 +int init_module(void)
1534 + return register_tcf_proto_ops(&cls_tcindex_ops);
1537 +void cleanup_module(void)
1539 + unregister_tcf_proto_ops(&cls_tcindex_ops);
1542 +MODULE_LICENSE("GPL");
1543 diff -urN ../v2.2.21/linux/net/sched/cls_u32.c linux/net/sched/cls_u32.c
1544 --- ../v2.2.21/linux/net/sched/cls_u32.c Sat Aug 4 12:52:33 2001
1545 +++ linux/net/sched/cls_u32.c Sun Mar 31 03:18:28 2002
1547 #include <net/sock.h>
1548 #include <net/pkt_sched.h>
1550 -#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
1556 if (!(n->sel.flags&(TC_U32_VAROFFSET|TC_U32_OFFSET|TC_U32_EAT)))
1559 - if (n->sel.flags&(TC_U32_EAT|TC_U32_VAROFFSET)) {
1560 + if (n->sel.flags&(TC_U32_OFFSET|TC_U32_VAROFFSET)) {
1561 off2 = n->sel.off + 3;
1562 if (n->sel.flags&TC_U32_VAROFFSET)
1563 off2 += ntohs(n->sel.offmask & *(u16*)(ptr+n->sel.offoff)) >>n->sel.offshift;
1568 - if ((cl = cls_set_class(&n->res.class, 0)) != 0)
1569 + if ((cl = __cls_set_class(&n->res.class, 0)) != 0)
1570 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
1571 #ifdef CONFIG_NET_CLS_POLICE
1572 tcf_police_release(n->police);
1575 for (kp = &ht->ht[TC_U32_HASH(key->handle)]; *kp; kp = &(*kp)->next) {
1577 + tcf_tree_lock(tp);
1580 + tcf_tree_unlock(tp);
1582 u32_destroy_key(tp, key);
1585 for (h=0; h<=ht->divisor; h++) {
1586 while ((n = ht->ht[h]) != NULL) {
1587 ht->ht[h] = n->next;
1590 u32_destroy_key(tp, n);
1597 ht_down = xchg(&n->ht_down, ht_down);
1599 + sch_tree_unlock(q);
1606 n->res.classid = *(u32*)RTA_DATA(tb[TCA_U32_CLASSID-1]);
1607 - cl = cls_set_class(&n->res.class, q->ops->cl_ops->bind_tcf(q, base, n->res.classid));
1609 + cl = __cls_set_class(&n->res.class, q->ops->cl_ops->bind_tcf(q, base, n->res.classid));
1610 + sch_tree_unlock(q);
1612 q->ops->cl_ops->unbind_tcf(q, cl);
1615 if (tb[TCA_U32_POLICE-1]) {
1616 struct tcf_police *police = tcf_police_locate(tb[TCA_U32_POLICE-1], est);
1619 police = xchg(&n->police, police);
1621 + sch_tree_unlock(q);
1623 tcf_police_release(police);
1629 -#ifdef CONFIG_RTNETLINK
1630 static int u32_dump(struct tcf_proto *tp, unsigned long fh,
1631 struct sk_buff *skb, struct tcmsg *t)
1634 rta->rta_len = skb->tail - b;
1635 #ifdef CONFIG_NET_CLS_POLICE
1636 if (TC_U32_KEY(n->handle) && n->police) {
1637 - RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), &n->police->stats);
1638 + if (qdisc_copy_stats(skb, &n->police->stats))
1639 + goto rtattr_failure;
1644 skb_trim(skb, b - skb->data);
1649 struct tcf_proto_ops cls_u32_ops = {
1651 @@ -705,11 +706,7 @@
1655 -#ifdef CONFIG_RTNETLINK
1664 unregister_tcf_proto_ops(&cls_u32_ops);
1667 +MODULE_LICENSE("GPL");
1668 diff -urN ../v2.2.21/linux/net/sched/police.c linux/net/sched/police.c
1669 --- ../v2.2.21/linux/net/sched/police.c Sat Oct 21 12:10:47 2000
1670 +++ linux/net/sched/police.c Wed Aug 7 23:28:12 2002
1672 #include <net/sock.h>
1673 #include <net/pkt_sched.h>
1675 -#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
1677 #define L2T(p,L) ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log])
1678 #define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log])
1681 for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) {
1685 #ifdef CONFIG_NET_ESTIMATOR
1686 qdisc_kill_estimator(&p->stats);
1690 h = tcf_police_hash(p->index);
1691 p->next = tcf_police_ht[h];
1693 tcf_police_ht[h] = p;
1698 diff -urN ../v2.2.21/linux/net/sched/sch_api.c linux/net/sched/sch_api.c
1699 --- ../v2.2.21/linux/net/sched/sch_api.c Sat Oct 21 12:10:47 2000
1700 +++ linux/net/sched/sch_api.c Wed Aug 7 23:27:29 2002
1704 * Rani Assaf <rani@magic.metawire.com> :980802: JIFFIES and CPU clock sources are repaired.
1705 + * J Hadi Salim (hadi@nortelnetworks.com):981128: "Append" message
1707 * Eduardo J. Blanco <ejbs@netlabs.com.uy> :990222: kmod support
1708 + * Jamal Hadi Salim <hadi@nortelnetworks.com>: 990501: ingress support
1711 #include <linux/config.h>
1713 #include <linux/init.h>
1714 #include <linux/proc_fs.h>
1715 #include <linux/kmod.h>
1716 +#include <linux/firewall.h>
1718 #include <net/sock.h>
1719 #include <net/pkt_sched.h>
1721 #include <asm/system.h>
1722 #include <asm/bitops.h>
1724 -#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
1726 #ifdef CONFIG_RTNETLINK
1727 static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid,
1728 struct Qdisc *old, struct Qdisc *new);
1733 - enqueue returns number of enqueued packets i.e. this number is 1,
1734 - if packet was enqueued successfully and <1 if something (not
1735 - necessary THIS packet) was dropped.
1736 + enqueue returns 0, if packet was enqueued successfully.
1737 + If packet (this one or another one) was dropped, it returns
1738 + not zero error code.
1739 + NET_XMIT_DROP - this packet dropped
1740 + Expected action: do not backoff, but wait until queue will clear.
1741 + NET_XMIT_CN - probably this packet enqueued, but another one dropped.
1742 + Expected action: backoff or ignore
1743 + NET_XMIT_POLICED - dropped by police.
1744 + Expected action: backoff or error to real-time apps.
1748 @@ -139,9 +147,11 @@
1750 struct Qdisc_ops *q, **qp;
1752 - for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next)
1753 - if (strcmp(qops->id, q->id) == 0)
1754 + for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next) {
1755 + if (strcmp(qops->id, q->id) == 0) {
1760 if (qops->enqueue == NULL)
1761 qops->enqueue = noop_qdisc_ops.enqueue;
1762 @@ -158,14 +168,17 @@
1763 int unregister_qdisc(struct Qdisc_ops *qops)
1765 struct Qdisc_ops *q, **qp;
1766 + int err = -ENOENT;
1768 for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next)
1784 /* We know handle. Find qdisc among all qdisc's attached to device
1788 cl = cops->get(p, classid);
1792 leaf = cops->leaf(p, cl);
1793 @@ -203,15 +217,15 @@
1795 struct Qdisc_ops *qdisc_lookup_ops(struct rtattr *kind)
1797 - struct Qdisc_ops *q;
1798 + struct Qdisc_ops *q = NULL;
1801 for (q = qdisc_base; q; q = q->next) {
1802 if (rtattr_strcmp(kind, q->id) == 0)
1811 static struct qdisc_rate_table *qdisc_rtab_list;
1812 @@ -285,17 +299,32 @@
1813 dev_deactivate(dev);
1816 - oqdisc = dev->qdisc_sleeping;
1817 + if (qdisc && qdisc->flags&TCQ_F_INGRES) {
1818 + oqdisc = dev->qdisc_ingress;
1819 + /* Prune old scheduler */
1820 + if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) {
1822 + qdisc_reset(oqdisc);
1823 + dev->qdisc_ingress = NULL;
1824 + } else { /* new */
1825 + dev->qdisc_ingress = qdisc;
1830 + oqdisc = dev->qdisc_sleeping;
1832 + /* Prune old scheduler */
1833 + if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
1834 + qdisc_reset(oqdisc);
1836 + /* ... and graft new one */
1837 + if (qdisc == NULL)
1838 + qdisc = &noop_qdisc;
1839 + dev->qdisc_sleeping = qdisc;
1840 + dev->qdisc = &noop_qdisc;
1843 - /* Prune old scheduler */
1844 - if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
1845 - qdisc_reset(oqdisc);
1847 - /* ... and graft new one */
1848 - if (qdisc == NULL)
1849 - qdisc = &noop_qdisc;
1850 - dev->qdisc_sleeping = qdisc;
1851 - dev->qdisc = &noop_qdisc;
1854 if (dev->flags & IFF_UP)
1855 @@ -315,9 +344,15 @@
1856 struct Qdisc *new, struct Qdisc **old)
1859 + struct Qdisc *q = *old;
1862 - if (parent == NULL) {
1863 - *old = dev_graft_qdisc(dev, new);
1864 + if (parent == NULL) {
1865 + if (q && q->flags&TCQ_F_INGRES) {
1866 + *old = dev_graft_qdisc(dev, q);
1868 + *old = dev_graft_qdisc(dev, new);
1871 struct Qdisc_class_ops *cops = parent->ops->cl_ops;
1877 -#ifdef CONFIG_RTNETLINK
1880 Allocate and initialize new qdisc.
1885 /* Grrr... Resolve race condition with module unload */
1889 if (ops != qdisc_lookup_ops(kind))
1891 @@ -384,6 +417,10 @@
1892 memset(sch, 0, size);
1894 skb_queue_head_init(&sch->q);
1896 + if (handle == TC_H_INGRESS)
1897 + sch->flags |= TCQ_F_INGRES;
1900 sch->enqueue = ops->enqueue;
1901 sch->dequeue = ops->dequeue;
1902 @@ -395,7 +432,11 @@
1906 - sch->handle = handle;
1908 + if (handle == TC_H_INGRESS)
1909 + sch->handle =TC_H_MAKE(TC_H_INGRESS, 0);
1911 + sch->handle = handle;
1913 if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
1914 sch->next = dev->qdisc_list;
1915 @@ -493,12 +534,16 @@
1918 if (clid != TC_H_ROOT) {
1919 - if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
1921 - q = qdisc_leaf(p, clid);
1923 + if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {
1924 + if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
1926 + q = qdisc_leaf(p, clid);
1927 + } else { /* ingress */
1928 + q = dev->qdisc_ingress;
1931 q = dev->qdisc_sleeping;
1940 qdisc_notify(skb, n, clid, q, NULL);
1941 + sch_dev_queue_lock(dev);
1943 + sch_dev_queue_unlock(dev);
1946 qdisc_notify(skb, n, clid, NULL, q);
1947 @@ -548,9 +595,13 @@
1950 if (clid != TC_H_ROOT) {
1951 - if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
1953 - q = qdisc_leaf(p, clid);
1954 + if (clid != TC_H_INGRESS) {
1955 + if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
1957 + q = qdisc_leaf(p, clid);
1958 + } else { /*ingress */
1959 + q = dev->qdisc_ingress;
1962 q = dev->qdisc_sleeping;
1964 @@ -628,7 +679,10 @@
1966 if (!(n->nlmsg_flags&NLM_F_CREATE))
1968 - q = qdisc_create(dev, tcm->tcm_handle, tca, &err);
1969 + if (clid == TC_H_INGRESS)
1970 + q = qdisc_create(dev, tcm->tcm_parent, tca, &err);
1972 + q = qdisc_create(dev, tcm->tcm_handle, tca, &err);
1976 @@ -637,17 +691,36 @@
1977 struct Qdisc *old_q = NULL;
1978 err = qdisc_graft(dev, p, clid, q, &old_q);
1982 + sch_dev_queue_lock(dev);
1984 + sch_dev_queue_unlock(dev);
1988 qdisc_notify(skb, n, clid, old_q, q);
1991 + sch_dev_queue_lock(dev);
1992 qdisc_destroy(old_q);
1993 + sch_dev_queue_unlock(dev);
1999 +int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st)
2001 + start_bh_atomic();
2002 + RTA_PUT(skb, TCA_STATS, sizeof(*st), st);
2012 static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
2013 u32 pid, u32 seq, unsigned flags, int event)
2016 if (q->ops->dump && q->ops->dump(q, skb) < 0)
2017 goto rtattr_failure;
2018 q->stats.qlen = q->q.qlen;
2019 - RTA_PUT(skb, TCA_STATS, sizeof(q->stats), &q->stats);
2020 + if (qdisc_copy_stats(skb, &q->stats))
2021 + goto rtattr_failure;
2022 nlh->nlmsg_len = skb->tail - b;
2026 if (q_idx < s_q_idx)
2028 if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid,
2029 - cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0)
2030 + cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
2036 @@ -956,6 +1031,13 @@
2041 +#if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE)
2042 +int call_in_ingress(struct sk_buff *skb)
2044 + if (!skb->dev->qdisc_ingress) return FW_ACCEPT;
2045 + return skb->dev->qdisc_ingress->enqueue(skb,skb->dev->qdisc_ingress);
2049 int psched_us_per_tick = 1;
2050 @@ -967,8 +1049,9 @@
2054 - len = sprintf(buffer, "%08x %08x\n",
2055 - psched_tick_per_us, psched_us_per_tick);
2056 + len = sprintf(buffer, "%08x %08x %08x %08x\n",
2057 + psched_tick_per_us, psched_us_per_tick,
2062 @@ -1011,7 +1094,7 @@
2063 static void psched_tick(unsigned long);
2065 static struct timer_list psched_timer =
2066 - { NULL, NULL, 0, 0L, psched_tick };
2067 + { function: psched_tick };
2069 static void psched_tick(unsigned long dummy)
2071 @@ -1022,7 +1105,7 @@
2072 psched_timer.expires = jiffies + 1*HZ;
2074 unsigned long now = jiffies;
2075 - psched_time_base = ((u64)now)<<PSCHED_JSCALE;
2076 + psched_time_base += ((u64)(now-psched_time_mark))<<PSCHED_JSCALE;
2077 psched_time_mark = now;
2078 psched_timer.expires = now + 60*60*HZ;
2080 @@ -1072,9 +1155,7 @@
2082 __initfunc(int pktsched_init(void))
2084 -#ifdef CONFIG_RTNETLINK
2085 struct rtnetlink_link *link_p;
2087 #ifdef CONFIG_PROC_FS
2088 struct proc_dir_entry *ent;
2090 @@ -1090,7 +1171,6 @@
2094 -#ifdef CONFIG_RTNETLINK
2095 link_p = rtnetlink_links[PF_UNSPEC];
2097 /* Setup rtnetlink links. It is made here to avoid
2098 @@ -1107,11 +1187,10 @@
2099 link_p[RTM_GETTCLASS-RTM_BASE].doit = tc_ctl_tclass;
2100 link_p[RTM_GETTCLASS-RTM_BASE].dumpit = tc_dump_tclass;
2104 #define INIT_QDISC(name) { \
2105 extern struct Qdisc_ops name##_qdisc_ops; \
2106 - register_qdisc(&##name##_qdisc_ops); \
2107 + register_qdisc(& name##_qdisc_ops); \
2111 @@ -1134,6 +1213,9 @@
2113 #ifdef CONFIG_NET_SCH_GRED
2116 +#ifdef CONFIG_NET_SCH_INGRESS
2117 + INIT_QDISC(ingress);
2119 #ifdef CONFIG_NET_SCH_DSMARK
2121 diff -urN ../v2.2.21/linux/net/sched/sch_cbq.c linux/net/sched/sch_cbq.c
2122 --- ../v2.2.21/linux/net/sched/sch_cbq.c Sat Oct 21 12:11:29 2000
2123 +++ linux/net/sched/sch_cbq.c Thu Aug 1 23:43:46 2002
2126 #define L2T(cl,len) ((cl)->R_tab->data[(len)>>(cl)->R_tab->rate.cell_log])
2128 -#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
2131 static __inline__ unsigned cbq_hash(u32 h)
2134 case TC_POLICE_SHOT:
2142 struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
2143 struct cbq_class *cl = cbq_classify(skb, sch);
2145 + int ret = NET_XMIT_POLICED;
2147 #ifdef CONFIG_NET_CLS_POLICE
2149 @@ -405,14 +405,14 @@
2150 #ifdef CONFIG_NET_CLS_POLICE
2151 cl->q->__parent = sch;
2153 - if (cl->q->enqueue(skb, cl->q) == 1) {
2154 + if ((ret = cl->q->enqueue(skb, cl->q)) == 0) {
2156 sch->stats.packets++;
2157 sch->stats.bytes+=len;
2158 cbq_mark_toplevel(q, cl);
2159 if (!cl->next_alive)
2160 cbq_activate_class(cl);
2167 cbq_mark_toplevel(q, cl);
2175 @@ -431,11 +431,12 @@
2177 struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
2178 struct cbq_class *cl;
2181 if ((cl = q->tx_class) == NULL) {
2185 + return NET_XMIT_CN;
2189 @@ -445,15 +446,15 @@
2191 cl->q->__parent = sch;
2193 - if (cl->q->ops->requeue(skb, cl->q) == 1) {
2194 + if ((ret = cl->q->ops->requeue(skb, cl->q)) == 0) {
2196 if (!cl->next_alive)
2197 cbq_activate_class(cl);
2207 /* Overlimit actions */
2209 static void cbq_watchdog(unsigned long arg)
2211 struct Qdisc *sch = (struct Qdisc*)arg;
2213 sch->flags &= ~TCQ_F_THROTTLED;
2214 - qdisc_wakeup(sch->dev);
2215 + netif_schedule(sch->dev);
2218 static unsigned long cbq_undelay_prio(struct cbq_sched_data *q, int prio)
2222 sch->flags &= ~TCQ_F_THROTTLED;
2223 - qdisc_wakeup(sch->dev);
2224 + netif_schedule(sch->dev);
2230 cl->q->__parent = sch;
2232 - if (cl->q->enqueue(skb, cl->q) == 1) {
2233 + if (cl->q->enqueue(skb, cl->q) == 0) {
2235 sch->stats.packets++;
2236 sch->stats.bytes+=len;
2241 - struct cbq_class *borrow = NULL;
2242 + struct cbq_class *borrow = cl;
2244 if (cl->q->q.qlen &&
2245 (borrow = cbq_under_limit(cl)) == NULL)
2246 @@ -1052,16 +1054,11 @@
2249 sch->stats.overlimits++;
2250 - if (q->wd_expires && !sch->dev->tbusy) {
2251 + if (q->wd_expires && !netif_queue_stopped(sch->dev)) {
2252 long delay = PSCHED_US2JIFFIE(q->wd_expires);
2253 del_timer(&q->wd_timer);
2256 - if (delay > 10*HZ) {
2257 - if (net_ratelimit())
2258 - printk(KERN_DEBUG "CBQ delay %ld > 10sec\n", delay);
2261 q->wd_timer.expires = jiffies + delay;
2262 add_timer(&q->wd_timer);
2263 sch->flags |= TCQ_F_THROTTLED;
2264 @@ -1248,8 +1245,10 @@
2268 - if (cl->q->ops->drop && cl->q->ops->drop(cl->q))
2269 + if (cl->q->ops->drop && cl->q->ops->drop(cl->q)) {
2273 } while ((cl = cl->next_alive) != cl_head);
2276 @@ -1457,8 +1456,6 @@
2280 -#ifdef CONFIG_RTNETLINK
2282 static __inline__ int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl)
2284 unsigned char *b = skb->tail;
2285 @@ -1580,6 +1577,16 @@
2289 +int cbq_copy_xstats(struct sk_buff *skb, struct tc_cbq_xstats *st)
2291 + RTA_PUT(skb, TCA_XSTATS, sizeof(*st), st);
2299 static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb)
2301 struct cbq_sched_data *q = (struct cbq_sched_data*)sch->data;
2302 @@ -1591,8 +1598,13 @@
2303 if (cbq_dump_attr(skb, &q->link) < 0)
2304 goto rtattr_failure;
2305 rta->rta_len = skb->tail - b;
2306 + sch_dev_queue_lock(sch->dev);
2307 q->link.xstats.avgidle = q->link.avgidle;
2308 - RTA_PUT(skb, TCA_XSTATS, sizeof(q->link.xstats), &q->link.xstats);
2309 + if (cbq_copy_xstats(skb, &q->link.xstats)) {
2310 + sch_dev_queue_unlock(sch->dev);
2311 + goto rtattr_failure;
2313 + sch_dev_queue_unlock(sch->dev);
2317 @@ -1622,12 +1634,19 @@
2318 goto rtattr_failure;
2319 rta->rta_len = skb->tail - b;
2320 cl->stats.qlen = cl->q->q.qlen;
2321 - RTA_PUT(skb, TCA_STATS, sizeof(cl->stats), &cl->stats);
2322 + if (qdisc_copy_stats(skb, &cl->stats))
2323 + goto rtattr_failure;
2324 + sch_dev_queue_lock(sch->dev);
2325 cl->xstats.avgidle = cl->avgidle;
2326 cl->xstats.undertime = 0;
2327 if (!PSCHED_IS_PASTPERFECT(cl->undertime))
2328 cl->xstats.undertime = PSCHED_TDIFF(cl->undertime, q->now);
2329 - RTA_PUT(skb, TCA_XSTATS, sizeof(cl->xstats), &cl->xstats);
2330 + q->link.xstats.avgidle = q->link.avgidle;
2331 + if (cbq_copy_xstats(skb, &cl->xstats)) {
2332 + sch_dev_queue_unlock(sch->dev);
2333 + goto rtattr_failure;
2335 + sch_dev_queue_unlock(sch->dev);
2339 @@ -1636,8 +1655,6 @@
2345 static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
2348 @@ -1653,8 +1670,11 @@
2349 new->reshape_fail = cbq_reshape_fail;
2352 - if ((*old = xchg(&cl->q, new)) != NULL)
2353 - qdisc_reset(*old);
2354 + sch_tree_lock(sch);
2357 + qdisc_reset(*old);
2358 + sch_tree_unlock(sch);
2362 @@ -1718,9 +1738,13 @@
2365 for (h = 0; h < 16; h++) {
2366 - for (cl = q->classes[h]; cl; cl = cl->next)
2367 + struct cbq_class *next;
2369 + for (cl = q->classes[h]; cl; cl = next) {
2372 cbq_destroy_class(cl);
2376 qdisc_put_rtab(q->link.R_tab);
2377 @@ -1729,19 +1753,20 @@
2379 static void cbq_put(struct Qdisc *sch, unsigned long arg)
2381 - struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
2382 struct cbq_class *cl = (struct cbq_class*)arg;
2384 - start_bh_atomic();
2385 if (--cl->refcnt == 0) {
2386 #ifdef CONFIG_NET_CLS_POLICE
2387 + struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
2389 + sch_dev_queue_lock(sch->dev);
2390 if (q->rx_class == cl)
2392 + sch_dev_queue_unlock(sch->dev);
2395 cbq_destroy_class(cl);
2402 @@ -1802,7 +1827,7 @@
2405 /* Change class parameters */
2406 - start_bh_atomic();
2407 + sch_tree_lock(sch);
2409 if (cl->next_alive != NULL)
2410 cbq_deactivate_class(cl);
2411 @@ -1834,7 +1859,7 @@
2413 cbq_activate_class(cl);
2416 + sch_tree_unlock(sch);
2418 #ifdef CONFIG_NET_ESTIMATOR
2419 if (tca[TCA_RATE-1]) {
2420 @@ -1901,7 +1926,7 @@
2421 cl->quantum = cl->allot;
2422 cl->weight = cl->R_tab->rate.rate;
2424 - start_bh_atomic();
2425 + sch_tree_lock(sch);
2427 cl->borrow = cl->tparent;
2428 if (cl->tparent != &q->link)
2429 @@ -1925,7 +1950,7 @@
2431 if (tb[TCA_CBQ_FOPT-1])
2432 cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1]));
2434 + sch_tree_unlock(sch);
2436 #ifdef CONFIG_NET_ESTIMATOR
2437 if (tca[TCA_RATE-1])
2438 @@ -1948,7 +1973,7 @@
2439 if (cl->filters || cl->children || cl == &q->link)
2442 - start_bh_atomic();
2443 + sch_tree_lock(sch);
2446 cbq_deactivate_class(cl);
2447 @@ -1970,12 +1995,11 @@
2448 cbq_sync_defmap(cl);
2451 + sch_tree_unlock(sch);
2453 if (--cl->refcnt == 0)
2454 cbq_destroy_class(cl);
2461 @@ -2052,9 +2076,7 @@
2465 -#ifdef CONFIG_RTNETLINK
2470 struct Qdisc_ops cbq_qdisc_ops =
2471 @@ -2074,9 +2096,7 @@
2473 NULL /* cbq_change */,
2475 -#ifdef CONFIG_RTNETLINK
2481 @@ -2090,3 +2110,4 @@
2482 unregister_qdisc(&cbq_qdisc_ops);
2485 +MODULE_LICENSE("GPL");
2486 diff -urN ../v2.2.21/linux/net/sched/sch_csz.c linux/net/sched/sch_csz.c
2487 --- ../v2.2.21/linux/net/sched/sch_csz.c Sat Oct 21 12:10:47 2000
2488 +++ linux/net/sched/sch_csz.c Thu Aug 1 23:53:01 2002
2490 if (this->q.qlen >= this->limit || this->L_tab == NULL) {
2494 + return NET_XMIT_DROP;
2497 R = csz_update(sch);
2500 sch->stats.bytes += skb->len;
2501 sch->stats.packets++;
2506 static __inline__ struct sk_buff *
2511 -#ifdef CONFIG_RTNETLINK
2512 static int csz_dump(struct Qdisc *sch, struct sk_buff *skb)
2514 struct csz_sched_data *q = (struct csz_sched_data *)sch->data;
2516 skb_trim(skb, b - skb->data);
2522 static int csz_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,
2528 - start_bh_atomic();
2529 + sch_dev_queue_lock(sch->dev);
2531 a->rate_log = copt->rate_log;
2534 if (tb[TCA_CSZ_RTAB-1])
2535 memcpy(a->L_tab, RTA_DATA(tb[TCA_CSZ_RTAB-1]), 1024);
2538 + sch_dev_queue_unlock(sch->dev);
2542 @@ -920,19 +917,18 @@
2546 - start_bh_atomic();
2547 + sch_dev_queue_lock(sch->dev);
2548 a->fprev->fnext = a->fnext;
2549 a->fnext->fprev = a->fprev;
2550 a->sprev->snext = a->snext;
2551 a->snext->sprev = a->sprev;
2552 a->start = a->finish = 0;
2553 kfree(xchg(&q->flow[cl].L_tab, NULL));
2555 + sch_dev_queue_unlock(sch->dev);
2560 -#ifdef CONFIG_RTNETLINK
2561 static int csz_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, struct tcmsg *tcm)
2563 struct csz_sched_data *q = (struct csz_sched_data *)sch->data;
2565 skb_trim(skb, b - skb->data);
2570 static void csz_walk(struct Qdisc *sch, struct qdisc_walker *arg)
2572 @@ -1030,9 +1025,7 @@
2576 -#ifdef CONFIG_RTNETLINK
2581 struct Qdisc_ops csz_qdisc_ops =
2582 @@ -1052,9 +1045,7 @@
2584 NULL /* csz_change */,
2586 -#ifdef CONFIG_RTNETLINK
2592 @@ -1069,3 +1060,4 @@
2593 unregister_qdisc(&csz_qdisc_ops);
2596 +MODULE_LICENSE("GPL");
2597 diff -urN ../v2.2.21/linux/net/sched/sch_dsmark.c linux/net/sched/sch_dsmark.c
2598 --- ../v2.2.21/linux/net/sched/sch_dsmark.c Thu Jan 1 00:00:00 1970
2599 +++ linux/net/sched/sch_dsmark.c Sun Mar 31 03:18:30 2002
2601 +/* net/sched/sch_dsmark.c - Differentiated Services field marker */
2603 +/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
2606 +#include <linux/config.h>
2607 +#include <linux/module.h>
2608 +#include <linux/types.h>
2609 +#include <linux/string.h>
2610 +#include <linux/errno.h>
2611 +#include <linux/skbuff.h>
2612 +#include <linux/netdevice.h> /* for pkt_sched */
2613 +#include <linux/rtnetlink.h>
2614 +#include <net/pkt_sched.h>
2615 +#include <net/dsfield.h>
2616 +#include <asm/byteorder.h>
2619 +#if 1 /* control */
2620 +#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
2622 +#define DPRINTK(format,args...)
2626 +#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
2628 +#define D2PRINTK(format,args...)
2632 +#define PRIV(sch) ((struct dsmark_qdisc_data *) (sch)->data)
2636 + * classid class marking
2637 + * ------- ----- -------
2639 + * x:0 1 use entry [0]
2641 + * x:y y>0 y+1 use entry [y]
2643 + * x:indices-1 indices use entry [indices-1]
2645 + * x:y y+1 use entry [y & (indices-1)]
2647 + * 0xffff 0x10000 use entry [indices-1]
2651 +#define NO_DEFAULT_INDEX (1 << 16)
2653 +struct dsmark_qdisc_data {
2655 + struct tcf_proto *filter_list;
2656 + __u8 *mask; /* "owns" the array */
2659 + __u32 default_index; /* index range is 0...0xffff */
2664 +/* ------------------------- Class/flow operations ------------------------- */
2667 +static int dsmark_graft(struct Qdisc *sch,unsigned long arg,
2668 + struct Qdisc *new,struct Qdisc **old)
2670 + struct dsmark_qdisc_data *p = PRIV(sch);
2672 + DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",sch,p,new,
2675 + new = &noop_qdisc;
2676 + sch_tree_lock(sch);
2677 + *old = xchg(&p->q,new);
2679 + qdisc_reset(*old);
2680 + sch_tree_unlock(sch); /* @@@ move up ? */
2685 +static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
2687 + struct dsmark_qdisc_data *p = PRIV(sch);
2693 +static unsigned long dsmark_get(struct Qdisc *sch,u32 classid)
2695 + struct dsmark_qdisc_data *p __attribute__((unused)) = PRIV(sch);
2697 + DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
2698 + return TC_H_MIN(classid)+1;
2702 +static unsigned long dsmark_bind_filter(struct Qdisc *sch,
2703 + unsigned long parent, u32 classid)
2705 + return dsmark_get(sch,classid);
2709 +static void dsmark_put(struct Qdisc *sch, unsigned long cl)
2714 +static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
2715 + struct rtattr **tca, unsigned long *arg)
2717 + struct dsmark_qdisc_data *p = PRIV(sch);
2718 + struct rtattr *opt = tca[TCA_OPTIONS-1];
2719 + struct rtattr *tb[TCA_DSMARK_MAX];
2721 + DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x),"
2722 + "arg 0x%lx\n",sch,p,classid,parent,*arg);
2723 + if (*arg > p->indices)
2725 + if (!opt || rtattr_parse(tb, TCA_DSMARK_MAX, RTA_DATA(opt),
2726 + RTA_PAYLOAD(opt)))
2728 + if (tb[TCA_DSMARK_MASK-1]) {
2729 + if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK-1]))
2731 + p->mask[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_MASK-1]);
2733 + if (tb[TCA_DSMARK_VALUE-1]) {
2734 + if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE-1]))
2736 + p->value[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_VALUE-1]);
2742 +static int dsmark_delete(struct Qdisc *sch,unsigned long arg)
2744 + struct dsmark_qdisc_data *p = PRIV(sch);
2746 + if (!arg || arg > p->indices)
2748 + p->mask[arg-1] = 0xff;
2749 + p->value[arg-1] = 0;
2754 +static void dsmark_walk(struct Qdisc *sch,struct qdisc_walker *walker)
2756 + struct dsmark_qdisc_data *p = PRIV(sch);
2759 + DPRINTK("dsmark_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker);
2762 + for (i = 0; i < p->indices; i++) {
2763 + if (p->mask[i] == 0xff && !p->value[i])
2765 + if (walker->count >= walker->skip) {
2766 + if (walker->fn(sch, i+1, walker) < 0) {
2776 +static struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch,unsigned long cl)
2778 + struct dsmark_qdisc_data *p = PRIV(sch);
2780 + return &p->filter_list;
2784 +/* --------------------------- Qdisc operations ---------------------------- */
2787 +static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
2789 + struct dsmark_qdisc_data *p = PRIV(sch);
2790 + struct tcf_result res;
2792 + int ret = NET_XMIT_POLICED;
2794 + D2PRINTK("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
2795 + if (p->set_tc_index) {
2796 + switch (skb->protocol) {
2797 + case __constant_htons(ETH_P_IP):
2798 + skb->tc_index = ipv4_get_dsfield(skb->nh.iph);
2800 + case __constant_htons(ETH_P_IPV6):
2801 + skb->tc_index = ipv6_get_dsfield(skb->nh.ipv6h);
2804 + skb->tc_index = 0;
2808 + result = TC_POLICE_OK; /* be nice to gcc */
2809 + if (TC_H_MAJ(skb->priority) == sch->handle) {
2810 + skb->tc_index = TC_H_MIN(skb->priority);
2812 + result = tc_classify(skb,p->filter_list,&res);
2813 + D2PRINTK("result %d class 0x%04x\n",result,res.classid);
2815 +#ifdef CONFIG_NET_CLS_POLICE
2816 + case TC_POLICE_SHOT:
2820 + case TC_POLICE_RECLASSIFY:
2821 + /* FIXME: what to do here ??? */
2824 + case TC_POLICE_OK:
2825 + skb->tc_index = TC_H_MIN(res.classid);
2827 + case TC_POLICE_UNSPEC:
2828 + /* fall through */
2830 + if (p->default_index != NO_DEFAULT_INDEX)
2831 + skb->tc_index = p->default_index;
2836 +#ifdef CONFIG_NET_CLS_POLICE
2837 + result == TC_POLICE_SHOT ||
2840 + ((ret = p->q->enqueue(skb,p->q)) != 0)) {
2841 + sch->stats.drops++;
2844 + sch->stats.bytes += skb->len;
2845 + sch->stats.packets++;
2851 +static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
2853 + struct dsmark_qdisc_data *p = PRIV(sch);
2854 + struct sk_buff *skb;
2857 + D2PRINTK("dsmark_dequeue(sch %p,[qdisc %p])\n",sch,p);
2858 + skb = p->q->ops->dequeue(p->q);
2862 + index = skb->tc_index & (p->indices-1);
2863 + D2PRINTK("index %d->%d\n",skb->tc_index,index);
2864 + switch (skb->protocol) {
2865 + case __constant_htons(ETH_P_IP):
2866 + ipv4_change_dsfield(skb->nh.iph,
2867 + p->mask[index],p->value[index]);
2869 + case __constant_htons(ETH_P_IPV6):
2870 + ipv6_change_dsfield(skb->nh.ipv6h,
2871 + p->mask[index],p->value[index]);
2875 + * Only complain if a change was actually attempted.
2876 + * This way, we can send non-IP traffic through dsmark
2877 + * and don't need yet another qdisc as a bypass.
2879 + if (p->mask[index] != 0xff || p->value[index])
2880 + printk(KERN_WARNING "dsmark_dequeue: "
2881 + "unsupported protocol %d\n",
2882 + htons(skb->protocol));
2889 +static int dsmark_requeue(struct sk_buff *skb,struct Qdisc *sch)
2892 + struct dsmark_qdisc_data *p = PRIV(sch);
2894 + D2PRINTK("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
2895 + if ((ret = p->q->ops->requeue(skb, p->q)) == 0) {
2899 + sch->stats.drops++;
2904 +static int dsmark_drop(struct Qdisc *sch)
2906 + struct dsmark_qdisc_data *p = PRIV(sch);
2908 + DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
2909 + if (!p->q->ops->drop)
2911 + if (!p->q->ops->drop(p->q))
2918 +int dsmark_init(struct Qdisc *sch,struct rtattr *opt)
2920 + struct dsmark_qdisc_data *p = PRIV(sch);
2921 + struct rtattr *tb[TCA_DSMARK_MAX];
2924 + DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
2925 + if (rtattr_parse(tb,TCA_DSMARK_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0 ||
2926 + !tb[TCA_DSMARK_INDICES-1] ||
2927 + RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16))
2929 + memset(p,0,sizeof(*p));
2930 + p->filter_list = NULL;
2931 + p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
2934 + for (tmp = p->indices; tmp != 1; tmp >>= 1) {
2938 + p->default_index = NO_DEFAULT_INDEX;
2939 + if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) {
2940 + if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX-1]) < sizeof(__u16))
2942 + p->default_index =
2943 + *(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
2945 + p->set_tc_index = !!tb[TCA_DSMARK_SET_TC_INDEX-1];
2946 + p->mask = kmalloc(p->indices*2,GFP_KERNEL);
2949 + p->value = p->mask+p->indices;
2950 + memset(p->mask,0xff,p->indices);
2951 + memset(p->value,0,p->indices);
2952 + if (!(p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)))
2953 + p->q = &noop_qdisc;
2954 + DPRINTK("dsmark_init: qdisc %p\n",&p->q);
2955 + MOD_INC_USE_COUNT;
2960 +static void dsmark_reset(struct Qdisc *sch)
2962 + struct dsmark_qdisc_data *p = PRIV(sch);
2964 + DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
2965 + qdisc_reset(p->q);
2970 +static void dsmark_destroy(struct Qdisc *sch)
2972 + struct dsmark_qdisc_data *p = PRIV(sch);
2973 + struct tcf_proto *tp;
2975 + DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n",sch,p);
2976 + while (p->filter_list) {
2977 + tp = p->filter_list;
2978 + p->filter_list = tp->next;
2979 + tp->ops->destroy(tp);
2981 + qdisc_destroy(p->q);
2982 + p->q = &noop_qdisc;
2984 + MOD_DEC_USE_COUNT;
2988 +static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
2989 + struct sk_buff *skb, struct tcmsg *tcm)
2991 + struct dsmark_qdisc_data *p = PRIV(sch);
2992 + unsigned char *b = skb->tail;
2993 + struct rtattr *rta;
2995 + DPRINTK("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n",sch,p,cl);
2996 + if (!cl || cl > p->indices)
2998 + tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle),cl-1);
2999 + rta = (struct rtattr *) b;
3000 + RTA_PUT(skb,TCA_OPTIONS,0,NULL);
3001 + RTA_PUT(skb,TCA_DSMARK_MASK,1,&p->mask[cl-1]);
3002 + RTA_PUT(skb,TCA_DSMARK_VALUE,1,&p->value[cl-1]);
3003 + rta->rta_len = skb->tail-b;
3007 + skb_trim(skb,b-skb->data);
3011 +static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb)
3013 + struct dsmark_qdisc_data *p = PRIV(sch);
3014 + unsigned char *b = skb->tail;
3015 + struct rtattr *rta;
3017 + rta = (struct rtattr *) b;
3018 + RTA_PUT(skb,TCA_OPTIONS,0,NULL);
3019 + RTA_PUT(skb,TCA_DSMARK_INDICES,sizeof(__u16),&p->indices);
3020 + if (p->default_index != NO_DEFAULT_INDEX) {
3021 + __u16 tmp = p->default_index;
3023 + RTA_PUT(skb,TCA_DSMARK_DEFAULT_INDEX, sizeof(__u16), &tmp);
3025 + if (p->set_tc_index)
3026 + RTA_PUT(skb, TCA_DSMARK_SET_TC_INDEX, 0, NULL);
3027 + rta->rta_len = skb->tail-b;
3031 + skb_trim(skb,b-skb->data);
3035 +static struct Qdisc_class_ops dsmark_class_ops =
3037 + dsmark_graft, /* graft */
3038 + dsmark_leaf, /* leaf */
3039 + dsmark_get, /* get */
3040 + dsmark_put, /* put */
3041 + dsmark_change, /* change */
3042 + dsmark_delete, /* delete */
3043 + dsmark_walk, /* walk */
3045 + dsmark_find_tcf, /* tcf_chain */
3046 + dsmark_bind_filter, /* bind_tcf */
3047 + dsmark_put, /* unbind_tcf */
3049 + dsmark_dump_class, /* dump */
3052 +struct Qdisc_ops dsmark_qdisc_ops =
3055 + &dsmark_class_ops, /* cl_ops */
3057 + sizeof(struct dsmark_qdisc_data),
3059 + dsmark_enqueue, /* enqueue */
3060 + dsmark_dequeue, /* dequeue */
3061 + dsmark_requeue, /* requeue */
3062 + dsmark_drop, /* drop */
3064 + dsmark_init, /* init */
3065 + dsmark_reset, /* reset */
3066 + dsmark_destroy, /* destroy */
3067 + NULL, /* change */
3069 + dsmark_dump /* dump */
3073 +int init_module(void)
3075 + return register_qdisc(&dsmark_qdisc_ops);
3079 +void cleanup_module(void)
3081 + unregister_qdisc(&dsmark_qdisc_ops);
3084 +MODULE_LICENSE("GPL");
3085 diff -urN ../v2.2.21/linux/net/sched/sch_fifo.c linux/net/sched/sch_fifo.c
3086 --- ../v2.2.21/linux/net/sched/sch_fifo.c Sat Oct 21 12:10:47 2000
3087 +++ linux/net/sched/sch_fifo.c Sun Mar 31 03:18:30 2002
3089 sch->stats.backlog += skb->len;
3090 sch->stats.bytes += skb->len;
3091 sch->stats.packets++;
3096 #ifdef CONFIG_NET_CLS_POLICE
3097 if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
3101 + return NET_XMIT_DROP;
3107 __skb_queue_head(&sch->q, skb);
3108 sch->stats.backlog += skb->len;
3113 static struct sk_buff *
3114 @@ -110,21 +110,21 @@
3115 __skb_queue_tail(&sch->q, skb);
3116 sch->stats.bytes += skb->len;
3117 sch->stats.packets++;
3122 #ifdef CONFIG_NET_CLS_POLICE
3123 if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
3127 + return NET_XMIT_DROP;
3131 pfifo_requeue(struct sk_buff *skb, struct Qdisc* sch)
3133 __skb_queue_head(&sch->q, skb);
3143 -#ifdef CONFIG_RTNETLINK
3144 static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
3146 struct fifo_sched_data *q = (void*)sch->data;
3148 skb_trim(skb, b - skb->data);
3153 struct Qdisc_ops pfifo_qdisc_ops =
3159 -#ifdef CONFIG_RTNETLINK
3164 struct Qdisc_ops bfifo_qdisc_ops =
3169 -#ifdef CONFIG_RTNETLINK
3173 diff -urN ../v2.2.21/linux/net/sched/sch_generic.c linux/net/sched/sch_generic.c
3174 --- ../v2.2.21/linux/net/sched/sch_generic.c Sat Oct 21 12:11:45 2000
3175 +++ linux/net/sched/sch_generic.c Wed Aug 7 23:26:44 2002
3177 * 2 of the License, or (at your option) any later version.
3179 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
3180 + * Jamal Hadi Salim, <hadi@nortelnetworks.com>
3181 + * - Ingress support
3184 #include <asm/uaccess.h>
3186 #include <net/sock.h>
3187 #include <net/pkt_sched.h>
3189 -#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
3191 /* Main transmission queue. */
3193 struct Qdisc_head qdisc_head = { &qdisc_head };
3195 noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc)
3199 + return NET_XMIT_CN;
3202 static struct sk_buff *
3204 if (net_ratelimit())
3205 printk(KERN_DEBUG "%s deferred output. It is buggy.\n", skb->dev->name);
3208 + return NET_XMIT_CN;
3211 struct Qdisc_ops noop_qdisc_ops =
3221 @@ -227,14 +227,14 @@
3222 list = ((struct sk_buff_head*)qdisc->data) +
3223 prio2band[skb->priority&TC_PRIO_MAX];
3225 - if (list->qlen <= skb->dev->tx_queue_len) {
3226 + if (list->qlen <= qdisc->dev->tx_queue_len) {
3227 __skb_queue_tail(list, skb);
3232 qdisc->stats.drops++;
3235 + return NET_XMIT_DROP;
3238 static struct sk_buff *
3241 __skb_queue_head(list, skb);
3248 @@ -333,39 +333,39 @@
3249 void qdisc_reset(struct Qdisc *qdisc)
3251 struct Qdisc_ops *ops = qdisc->ops;
3252 - start_bh_atomic();
3259 void qdisc_destroy(struct Qdisc *qdisc)
3261 struct Qdisc_ops *ops = qdisc->ops;
3262 + struct device *dev;
3264 if (!atomic_dec_and_test(&qdisc->refcnt))
3269 #ifdef CONFIG_NET_SCHED
3272 struct Qdisc *q, **qp;
3273 - for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next)
3274 + for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) {
3282 #ifdef CONFIG_NET_ESTIMATOR
3283 qdisc_kill_estimator(&qdisc->stats);
3286 - start_bh_atomic();
3290 ops->destroy(qdisc);
3292 if (!(qdisc->flags&TCQ_F_BUILTIN))
3295 @@ -380,19 +380,20 @@
3298 if (dev->qdisc_sleeping == &noop_qdisc) {
3299 + struct Qdisc *qdisc;
3300 if (dev->tx_queue_len) {
3301 - struct Qdisc *qdisc;
3302 qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops);
3303 if (qdisc == NULL) {
3304 printk(KERN_INFO "%s: activation failed\n", dev->name);
3307 - dev->qdisc_sleeping = qdisc;
3309 - dev->qdisc_sleeping = &noqueue_qdisc;
3311 + qdisc = &noqueue_qdisc;
3313 + dev->qdisc_sleeping = qdisc;
3316 - start_bh_atomic();
3317 + sch_dev_queue_lock(dev);
3318 if ((dev->qdisc = dev->qdisc_sleeping) != &noqueue_qdisc) {
3319 dev->qdisc->tx_timeo = 5*HZ;
3320 dev->qdisc->tx_last = jiffies - dev->qdisc->tx_timeo;
3321 @@ -400,16 +401,17 @@
3322 dev_watchdog.expires = jiffies + 5*HZ;
3323 add_timer(&dev_watchdog);
3326 + sch_dev_queue_unlock(dev);
3329 void dev_deactivate(struct device *dev)
3331 struct Qdisc *qdisc;
3333 - start_bh_atomic();
3334 + sch_dev_queue_lock(dev);
3336 - qdisc = xchg(&dev->qdisc, &noop_qdisc);
3337 + qdisc = dev->qdisc;
3338 + dev->qdisc = &noop_qdisc;
3347 + sch_dev_queue_unlock(dev);
3350 void dev_init_scheduler(struct device *dev)
3351 @@ -439,13 +441,16 @@
3353 struct Qdisc *qdisc;
3355 - start_bh_atomic();
3356 + sch_dev_queue_lock(dev);
3357 qdisc = dev->qdisc_sleeping;
3358 dev->qdisc = &noop_qdisc;
3359 dev->qdisc_sleeping = &noop_qdisc;
3360 qdisc_destroy(qdisc);
3361 + if ((qdisc = dev->qdisc_ingress) != NULL) {
3362 + dev->qdisc_ingress = NULL;
3363 + qdisc_destroy(qdisc);
3365 BUG_TRAP(dev->qdisc_list == NULL);
3366 dev->qdisc_list = NULL;
3368 + sch_dev_queue_unlock(dev);
3371 diff -urN ../v2.2.21/linux/net/sched/sch_gred.c linux/net/sched/sch_gred.c
3372 --- ../v2.2.21/linux/net/sched/sch_gred.c Thu Jan 1 00:00:00 1970
3373 +++ linux/net/sched/sch_gred.c Fri Jul 5 22:06:27 2002
3376 + * net/sched/sch_gred.c Generic Random Early Detection queue.
3379 + * This program is free software; you can redistribute it and/or
3380 + * modify it under the terms of the GNU General Public License
3381 + * as published by the Free Software Foundation; either version
3382 + * 2 of the License, or (at your option) any later version.
3384 + * Authors: J Hadi Salim (hadi@cyberus.ca) 1998-2002
3386 + * 991129: - Bug fix with grio mode
3387 + * - a better sing. AvgQ mode with Grio(WRED)
3388 + * - A finer grained VQ dequeue based on sugestion
3390 + * - More error checks
3394 + * For all the glorious comments look at Alexey's sch_red.c
3397 +#include <linux/config.h>
3398 +#include <linux/module.h>
3399 +#include <asm/uaccess.h>
3400 +#include <asm/system.h>
3401 +#include <asm/bitops.h>
3402 +#include <linux/types.h>
3403 +#include <linux/kernel.h>
3404 +#include <linux/sched.h>
3405 +#include <linux/string.h>
3406 +#include <linux/mm.h>
3407 +#include <linux/socket.h>
3408 +#include <linux/sockios.h>
3409 +#include <linux/in.h>
3410 +#include <linux/errno.h>
3411 +#include <linux/interrupt.h>
3412 +#include <linux/if_ether.h>
3413 +#include <linux/inet.h>
3414 +#include <linux/netdevice.h>
3415 +#include <linux/etherdevice.h>
3416 +#include <linux/notifier.h>
3417 +#include <net/ip.h>
3418 +#include <net/route.h>
3419 +#include <linux/skbuff.h>
3420 +#include <net/sock.h>
3421 +#include <net/pkt_sched.h>
3423 +#if 1 /* control */
3424 +#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
3426 +#define DPRINTK(format,args...)
3430 +#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
3432 +#define D2PRINTK(format,args...)
3435 +struct gred_sched_data;
3438 +struct gred_sched_data
3441 + u32 limit; /* HARD maximal queue length */
3442 + u32 qth_min; /* Min average length threshold: A scaled */
3443 + u32 qth_max; /* Max average length threshold: A scaled */
3444 + u32 DP; /* the drop pramaters */
3445 + char Wlog; /* log(W) */
3446 + char Plog; /* random number bits */
3449 + u32 bytesin; /* bytes seen on virtualQ so far*/
3450 + u32 packetsin; /* packets seen on virtualQ so far*/
3451 + u32 backlog; /* bytes on the virtualQ */
3452 + u32 forced; /* packets dropped for exceeding limits */
3453 + u32 early; /* packets dropped as a warning */
3454 + u32 other; /* packets dropped by invoking drop() */
3455 + u32 pdrop; /* packets dropped because we exceeded physical queue limits */
3458 + u8 prio; /* the prio of this vq */
3461 + unsigned long qave; /* Average queue length: A scaled */
3462 + int qcount; /* Packets since last random number generation */
3463 + u32 qR; /* Cached random number */
3465 + psched_time_t qidlestart; /* Start of idle period */
3470 + struct gred_sched_data *tab[MAX_DPs];
3479 +gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
3481 + psched_time_t now;
3482 + struct gred_sched_data *q=NULL;
3483 + struct gred_sched *t= (struct gred_sched *)sch->data;
3484 + unsigned long qave=0;
3487 + if (!t->initd && skb_queue_len(&sch->q) <= sch->dev->tx_queue_len) {
3488 + D2PRINTK("NO GRED Queues setup yet! Enqueued anyway\n");
3493 + if ( ((skb->tc_index&0xf) > t->DPs) || !(q=t->tab[skb->tc_index&0xf])) {
3494 + printk("GRED: setting to default (%d)\n ",t->def);
3495 + if (!(q=t->tab[t->def])) {
3496 + DPRINTK("GRED: setting to default FAILED! dropping!! "
3497 + "(%d)\n ", t->def);
3500 + /* fix tc_index? --could be controvesial but needed for
3502 + skb->tc_index=(skb->tc_index&0xfffffff0) | t->def;
3505 + D2PRINTK("gred_enqueue virtualQ 0x%x classid %x backlog %d "
3506 + "general backlog %d\n",skb->tc_index&0xf,sch->handle,q->backlog,
3507 + sch->stats.backlog);
3508 + /* sum up all the qaves of prios <= to ours to get the new qave*/
3509 + if (!t->eqp && t->grio) {
3510 + for (i=0;i<t->DPs;i++) {
3511 + if ((!t->tab[i]) || (i==q->DP))
3514 + if ((t->tab[i]->prio < q->prio) && (PSCHED_IS_PASTPERFECT(t->tab[i]->qidlestart)))
3515 + qave +=t->tab[i]->qave;
3521 + q->bytesin+=skb->len;
3523 + if (t->eqp && t->grio) {
3525 + q->qave=t->tab[t->def]->qave;
3526 + q->qidlestart=t->tab[t->def]->qidlestart;
3529 + if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) {
3531 + PSCHED_GET_TIME(now);
3532 + us_idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max, 0);
3533 + PSCHED_SET_PASTPERFECT(q->qidlestart);
3535 + q->qave >>= q->Stab[(us_idle>>q->Scell_log)&0xFF];
3538 + q->qave += sch->stats.backlog - (q->qave >> q->Wlog);
3540 + q->qave += q->backlog - (q->qave >> q->Wlog);
3546 + if (t->eqp && t->grio)
3547 + t->tab[t->def]->qave=q->qave;
3549 + if ((q->qave+qave) < q->qth_min) {
3552 + if (q->backlog <= q->limit) {
3553 + q->backlog += skb->len;
3555 + __skb_queue_tail(&sch->q, skb);
3556 + sch->stats.backlog += skb->len;
3557 + sch->stats.bytes += skb->len;
3558 + sch->stats.packets++;
3566 + sch->stats.drops++;
3567 + return NET_XMIT_DROP;
3569 + if ((q->qave+qave) >= q->qth_max) {
3571 + sch->stats.overlimits++;
3575 + if (++q->qcount) {
3576 + if ((((qave+q->qave) - q->qth_min)>>q->Wlog)*q->qcount < q->qR)
3579 + q->qR = net_random()&q->Rmask;
3580 + sch->stats.overlimits++;
3584 + q->qR = net_random()&q->Rmask;
3589 +gred_requeue(struct sk_buff *skb, struct Qdisc* sch)
3591 + struct gred_sched_data *q;
3592 + struct gred_sched *t= (struct gred_sched *)sch->data;
3593 + q= t->tab[(skb->tc_index&0xf)];
3594 +/* error checking here -- probably unnecessary */
3595 + PSCHED_SET_PASTPERFECT(q->qidlestart);
3597 + __skb_queue_head(&sch->q, skb);
3598 + sch->stats.backlog += skb->len;
3599 + q->backlog += skb->len;
3603 +static struct sk_buff *
3604 +gred_dequeue(struct Qdisc* sch)
3606 + struct sk_buff *skb;
3607 + struct gred_sched_data *q;
3608 + struct gred_sched *t= (struct gred_sched *)sch->data;
3610 + skb = __skb_dequeue(&sch->q);
3612 + sch->stats.backlog -= skb->len;
3613 + q= t->tab[(skb->tc_index&0xf)];
3615 + q->backlog -= skb->len;
3616 + if (!q->backlog && !t->eqp)
3617 + PSCHED_GET_TIME(q->qidlestart);
3619 + D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf);
3625 + q= t->tab[t->def];
3627 + D2PRINTK("no default VQ set: Results will be "
3630 + PSCHED_GET_TIME(q->qidlestart);
3637 +gred_drop(struct Qdisc* sch)
3639 + struct sk_buff *skb;
3641 + struct gred_sched_data *q;
3642 + struct gred_sched *t= (struct gred_sched *)sch->data;
3644 + skb = __skb_dequeue_tail(&sch->q);
3646 + sch->stats.backlog -= skb->len;
3647 + sch->stats.drops++;
3648 + q= t->tab[(skb->tc_index&0xf)];
3650 + q->backlog -= skb->len;
3652 + if (!q->backlog && !t->eqp)
3653 + PSCHED_GET_TIME(q->qidlestart);
3655 + D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf);
3664 + D2PRINTK("no default VQ set: Results might be screwed up\n");
3668 + PSCHED_GET_TIME(q->qidlestart);
3673 +static void gred_reset(struct Qdisc* sch)
3676 + struct gred_sched_data *q;
3677 + struct gred_sched *t= (struct gred_sched *)sch->data;
3679 + __skb_queue_purge(&sch->q);
3681 + sch->stats.backlog = 0;
3683 + for (i=0;i<t->DPs;i++) {
3687 + PSCHED_SET_PASTPERFECT(q->qidlestart);
3698 +static int gred_change(struct Qdisc *sch, struct rtattr *opt)
3700 + struct gred_sched *table = (struct gred_sched *)sch->data;
3701 + struct gred_sched_data *q;
3702 + struct tc_gred_qopt *ctl;
3703 + struct tc_gred_sopt *sopt;
3704 + struct rtattr *tb[TCA_GRED_STAB];
3705 + struct rtattr *tb2[TCA_GRED_STAB];
3708 + if (opt == NULL ||
3709 + rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
3712 + if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0 &&
3713 + tb[TCA_GRED_DPS-1] != 0) {
3714 + rtattr_parse(tb2, TCA_GRED_DPS, RTA_DATA(opt),
3715 + RTA_PAYLOAD(opt));
3717 + sopt = RTA_DATA(tb2[TCA_GRED_DPS-1]);
3718 + table->DPs=sopt->DPs;
3719 + table->def=sopt->def_DP;
3720 + table->grio=sopt->grio;
3722 + /* probably need to clear all the table DP entries as well */
3723 + MOD_INC_USE_COUNT;
3728 + if (!table->DPs || tb[TCA_GRED_PARMS-1] == 0 || tb[TCA_GRED_STAB-1] == 0 ||
3729 + RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) ||
3730 + RTA_PAYLOAD(tb[TCA_GRED_STAB-1]) < 256)
3733 + ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]);
3734 + if (ctl->DP > MAX_DPs-1 ) {
3735 + /* misbehaving is punished! Put in the default drop probability */
3736 + DPRINTK("\nGRED: DP %u not in the proper range fixed. New DP "
3737 + "set to default at %d\n",ctl->DP,table->def);
3738 + ctl->DP=table->def;
3741 + if (table->tab[ctl->DP] == NULL) {
3742 + table->tab[ctl->DP]=kmalloc(sizeof(struct gred_sched_data),
3744 + if (NULL == table->tab[ctl->DP])
3746 + memset(table->tab[ctl->DP], 0, (sizeof(struct gred_sched_data)));
3748 + q= table->tab[ctl->DP];
3750 + if (table->grio) {
3751 + if (ctl->prio <=0) {
3752 + if (table->def && table->tab[table->def]) {
3753 + DPRINTK("\nGRED: DP %u does not have a prio"
3754 + "setting default to %d\n",ctl->DP,
3755 + table->tab[table->def]->prio);
3756 + q->prio=table->tab[table->def]->prio;
3758 + DPRINTK("\nGRED: DP %u does not have a prio"
3759 + " setting default to 8\n",ctl->DP);
3763 + q->prio=ctl->prio;
3771 + q->Wlog = ctl->Wlog;
3772 + q->Plog = ctl->Plog;
3773 + q->limit = ctl->limit;
3774 + q->Scell_log = ctl->Scell_log;
3775 + q->Rmask = ctl->Plog < 32 ? ((1<<ctl->Plog) - 1) : ~0UL;
3776 + q->Scell_max = (255<<q->Scell_log);
3777 + q->qth_min = ctl->qth_min<<ctl->Wlog;
3778 + q->qth_max = ctl->qth_max<<ctl->Wlog;
3787 + PSCHED_SET_PASTPERFECT(q->qidlestart);
3788 + memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256);
3790 + if ( table->initd && table->grio) {
3791 + /* this looks ugly but its not in the fast path */
3792 + for (i=0;i<table->DPs;i++) {
3793 + if ((!table->tab[i]) || (i==q->DP) )
3795 + if (table->tab[i]->prio == q->prio ){
3796 + /* WRED mode detected */
3803 + if (!table->initd) {
3806 + the first entry also goes into the default until
3810 + if (table->tab[table->def] == NULL) {
3811 + table->tab[table->def]=
3812 + kmalloc(sizeof(struct gred_sched_data), GFP_KERNEL);
3813 + if (NULL == table->tab[table->def])
3816 + memset(table->tab[table->def], 0,
3817 + (sizeof(struct gred_sched_data)));
3819 + q= table->tab[table->def];
3821 + q->Wlog = ctl->Wlog;
3822 + q->Plog = ctl->Plog;
3823 + q->limit = ctl->limit;
3824 + q->Scell_log = ctl->Scell_log;
3825 + q->Rmask = ctl->Plog < 32 ? ((1<<ctl->Plog) - 1) : ~0UL;
3826 + q->Scell_max = (255<<q->Scell_log);
3827 + q->qth_min = ctl->qth_min<<ctl->Wlog;
3828 + q->qth_max = ctl->qth_max<<ctl->Wlog;
3831 + q->prio=table->tab[ctl->DP]->prio;
3836 + PSCHED_SET_PASTPERFECT(q->qidlestart);
3837 + memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256);
3843 +static int gred_init(struct Qdisc *sch, struct rtattr *opt)
3845 + struct gred_sched *table = (struct gred_sched *)sch->data;
3846 + struct tc_gred_sopt *sopt;
3847 + struct rtattr *tb[TCA_GRED_STAB];
3848 + struct rtattr *tb2[TCA_GRED_STAB];
3850 + if (opt == NULL ||
3851 + rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
3854 + if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0 &&
3855 + tb[TCA_GRED_DPS-1] != 0) {
3856 + rtattr_parse(tb2, TCA_GRED_DPS, RTA_DATA(opt),RTA_PAYLOAD(opt));
3858 + sopt = RTA_DATA(tb2[TCA_GRED_DPS-1]);
3859 + table->DPs=sopt->DPs;
3860 + table->def=sopt->def_DP;
3861 + table->grio=sopt->grio;
3863 + MOD_INC_USE_COUNT;
3867 + DPRINTK("\n GRED_INIT error!\n");
3871 +static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
3873 + unsigned long qave;
3874 + struct rtattr *rta;
3875 + struct tc_gred_qopt *opt = NULL ;
3876 + struct tc_gred_qopt *dst;
3877 + struct gred_sched *table = (struct gred_sched *)sch->data;
3878 + struct gred_sched_data *q;
3880 + unsigned char *b = skb->tail;
3882 + rta = (struct rtattr*)b;
3883 + RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
3885 + opt=kmalloc(sizeof(struct tc_gred_qopt)*MAX_DPs, GFP_KERNEL);
3887 + if (opt == NULL) {
3888 + DPRINTK("gred_dump:failed to malloc for %Zd\n",
3889 + sizeof(struct tc_gred_qopt)*MAX_DPs);
3890 + goto rtattr_failure;
3893 + memset(opt, 0, (sizeof(struct tc_gred_qopt))*table->DPs);
3895 + if (!table->initd) {
3896 + DPRINTK("NO GRED Queues setup!\n");
3899 + for (i=0;i<MAX_DPs;i++) {
3904 + /* hack -- fix at some point with proper message
3905 + This is how we indicate to tc that there is no VQ
3908 + dst->DP=MAX_DPs+i;
3912 + dst->limit=q->limit;
3913 + dst->qth_min=q->qth_min>>q->Wlog;
3914 + dst->qth_max=q->qth_max>>q->Wlog;
3916 + dst->backlog=q->backlog;
3918 + if (table->eqp && table->grio) {
3919 + q->qidlestart=table->tab[table->def]->qidlestart;
3920 + q->qave=table->tab[table->def]->qave;
3922 + if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) {
3924 + psched_time_t now;
3925 + PSCHED_GET_TIME(now);
3926 + idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max, 0);
3927 + qave = q->qave >> q->Stab[(idle>>q->Scell_log)&0xFF];
3928 + dst->qave = qave >> q->Wlog;
3931 + dst->qave = q->qave >> q->Wlog;
3938 + dst->Wlog = q->Wlog;
3939 + dst->Plog = q->Plog;
3940 + dst->Scell_log = q->Scell_log;
3941 + dst->other = q->other;
3942 + dst->forced = q->forced;
3943 + dst->early = q->early;
3944 + dst->pdrop = q->pdrop;
3945 + dst->prio = q->prio;
3946 + dst->packets=q->packetsin;
3947 + dst->bytesin=q->bytesin;
3950 + RTA_PUT(skb, TCA_GRED_PARMS, sizeof(struct tc_gred_qopt)*MAX_DPs, opt);
3951 + rta->rta_len = skb->tail - b;
3959 + DPRINTK("gred_dump: FAILURE!!!!\n");
3961 +/* also free the opt struct here */
3962 + skb_trim(skb, b - skb->data);
3966 +static void gred_destroy(struct Qdisc *sch)
3968 + struct gred_sched *table = (struct gred_sched *)sch->data;
3971 + for (i = 0;i < table->DPs; i++) {
3972 + if (table->tab[i])
3973 + kfree(table->tab[i]);
3975 + MOD_DEC_USE_COUNT;
3978 +struct Qdisc_ops gred_qdisc_ops =
3983 + sizeof(struct gred_sched),
3991 + gred_change, /* change */
3997 +int init_module(void)
3999 + return register_qdisc(&gred_qdisc_ops);
4002 +void cleanup_module(void)
4004 + unregister_qdisc(&gred_qdisc_ops);
4007 +MODULE_LICENSE("GPL");
4008 diff -urN ../v2.2.21/linux/net/sched/sch_ingress.c linux/net/sched/sch_ingress.c
4009 --- ../v2.2.21/linux/net/sched/sch_ingress.c Thu Jan 1 00:00:00 1970
4010 +++ linux/net/sched/sch_ingress.c Sun Aug 4 18:02:57 2002
4012 +/* net/sched/sch_ingress.c - Ingress qdisc */
4014 +/* Written 1999 by Jamal Hadi Salim */
4017 +#include <linux/config.h>
4018 +#include <linux/module.h>
4019 +#include <linux/types.h>
4020 +#include <linux/skbuff.h>
4021 +#include <linux/netdevice.h> /* for pkt_sched */
4022 +#include <linux/rtnetlink.h>
4023 +#include <linux/firewall.h>
4024 +#include <net/pkt_sched.h>
4025 +#include <asm/byteorder.h>
4027 +#undef DEBUG_INGRESS
4029 +#ifdef DEBUG_INGRESS /* control */
4030 +#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
4032 +#define DPRINTK(format,args...)
4036 +#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
4038 +#define D2PRINTK(format,args...)
4042 +#define PRIV(sch) ((struct ingress_qdisc_data *) (sch)->data)
4046 +struct ingress_qdisc_data {
4048 + struct tcf_proto *filter_list;
4052 +/* ------------------------- Class/flow operations ------------------------- */
4055 +static int ingress_graft(struct Qdisc *sch,unsigned long arg,
4056 + struct Qdisc *new,struct Qdisc **old)
4058 +#ifdef DEBUG_INGRESS
4059 + struct ingress_qdisc_data *p = PRIV(sch);
4062 + DPRINTK("ingress_graft(sch %p,[qdisc %p],new %p,old %p)\n",
4063 + sch, p, new, old);
4064 + DPRINTK("\n ingress_graft: You cannot add qdiscs to classes");
4069 +static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
4075 +static unsigned long ingress_get(struct Qdisc *sch,u32 classid)
4077 +#ifdef DEBUG_INGRESS
4078 + struct ingress_qdisc_data *p = PRIV(sch);
4080 + DPRINTK("ingress_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
4081 + return TC_H_MIN(classid) + 1;
4085 +static unsigned long ingress_bind_filter(struct Qdisc *sch,
4086 + unsigned long parent, u32 classid)
4088 + return ingress_get(sch, classid);
4092 +static void ingress_put(struct Qdisc *sch, unsigned long cl)
4097 +static int ingress_change(struct Qdisc *sch, u32 classid, u32 parent,
4098 + struct rtattr **tca, unsigned long *arg)
4100 +#ifdef DEBUG_INGRESS
4101 + struct ingress_qdisc_data *p = PRIV(sch);
4103 + DPRINTK("ingress_change(sch %p,[qdisc %p],classid %x,parent %x),"
4104 + "arg 0x%lx\n", sch, p, classid, parent, *arg);
4105 + DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment");
4111 +static void ingress_walk(struct Qdisc *sch,struct qdisc_walker *walker)
4113 +#ifdef DEBUG_INGRESS
4114 + struct ingress_qdisc_data *p = PRIV(sch);
4116 + DPRINTK("ingress_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
4117 + DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment");
4121 +static struct tcf_proto **ingress_find_tcf(struct Qdisc *sch,unsigned long cl)
4123 + struct ingress_qdisc_data *p = PRIV(sch);
4125 + return &p->filter_list;
4129 +/* --------------------------- Qdisc operations ---------------------------- */
4132 +static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
4134 + struct ingress_qdisc_data *p = PRIV(sch);
4135 + struct tcf_result res;
4138 + D2PRINTK("ingress_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
4139 + result = tc_classify(skb, p->filter_list, &res);
4140 + D2PRINTK("result %d class 0x%04x\n", result, res.classid);
4142 + * Unlike normal "enqueue" functions, ingress_enqueue returns a
4143 + * firewall FW_* code.
4145 +#ifdef CONFIG_NET_CLS_POLICE
4147 + case TC_POLICE_SHOT:
4148 + result = FW_BLOCK;
4149 + sch->stats.drops++;
4151 + case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */
4152 + case TC_POLICE_OK:
4153 + case TC_POLICE_UNSPEC:
4155 + sch->stats.packets++;
4156 + sch->stats.bytes += skb->len;
4157 + result = FW_ACCEPT;
4161 + sch->stats.packets++;
4162 + sch->stats.bytes += skb->len;
4165 + skb->tc_index = TC_H_MIN(res.classid);
4170 +static struct sk_buff *ingress_dequeue(struct Qdisc *sch)
4173 + struct ingress_qdisc_data *p = PRIV(sch);
4174 + D2PRINTK("ingress_dequeue(sch %p,[qdisc %p])\n",sch,PRIV(p));
4180 +static int ingress_requeue(struct sk_buff *skb,struct Qdisc *sch)
4183 + struct ingress_qdisc_data *p = PRIV(sch);
4184 + D2PRINTK("ingress_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,PRIV(p));
4189 +static int ingress_drop(struct Qdisc *sch)
4191 +#ifdef DEBUG_INGRESS
4192 + struct ingress_qdisc_data *p = PRIV(sch);
4194 + DPRINTK("ingress_drop(sch %p,[qdisc %p])\n", sch, p);
4199 +int ingress_init(struct Qdisc *sch,struct rtattr *opt)
4201 + struct ingress_qdisc_data *p = PRIV(sch);
4203 + DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
4204 + memset(p, 0, sizeof(*p));
4205 + p->filter_list = NULL;
4206 + p->q = &noop_qdisc;
4207 + MOD_INC_USE_COUNT;
4212 +static void ingress_reset(struct Qdisc *sch)
4214 + struct ingress_qdisc_data *p = PRIV(sch);
4216 + DPRINTK("ingress_reset(sch %p,[qdisc %p])\n", sch, p);
4221 +/* for future use */
4222 + qdisc_reset(p->q);
4229 +static void ingress_destroy(struct Qdisc *sch)
4231 + struct ingress_qdisc_data *p = PRIV(sch);
4232 + struct tcf_proto *tp;
4234 + DPRINTK("ingress_destroy(sch %p,[qdisc %p])\n", sch, p);
4235 + while (p->filter_list) {
4236 + tp = p->filter_list;
4237 + p->filter_list = tp->next;
4238 + tp->ops->destroy(tp);
4240 + memset(p, 0, sizeof(*p));
4241 + p->filter_list = NULL;
4244 +/* for future use */
4245 + qdisc_destroy(p->q);
4248 + MOD_DEC_USE_COUNT;
4253 +static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
4255 + unsigned char *b = skb->tail;
4256 + struct rtattr *rta;
4258 + rta = (struct rtattr *) b;
4259 + RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
4260 + rta->rta_len = skb->tail - b;
4264 + skb_trim(skb, b - skb->data);
4268 +static struct Qdisc_class_ops ingress_class_ops =
4270 + ingress_graft, /* graft */
4271 + ingress_leaf, /* leaf */
4272 + ingress_get, /* get */
4273 + ingress_put, /* put */
4274 + ingress_change, /* change */
4275 + NULL, /* delete */
4276 + ingress_walk, /* walk */
4278 + ingress_find_tcf, /* tcf_chain */
4279 + ingress_bind_filter, /* bind_tcf */
4280 + ingress_put, /* unbind_tcf */
4285 +struct Qdisc_ops ingress_qdisc_ops =
4288 + &ingress_class_ops, /* cl_ops */
4290 + sizeof(struct ingress_qdisc_data),
4292 + ingress_enqueue, /* enqueue */
4293 + ingress_dequeue, /* dequeue */
4294 + ingress_requeue, /* requeue */
4295 + ingress_drop, /* drop */
4297 + ingress_init, /* init */
4298 + ingress_reset, /* reset */
4299 + ingress_destroy, /* destroy */
4300 + NULL, /* change */
4302 + ingress_dump, /* dump */
4307 +int init_module(void)
4311 + if ((ret = register_qdisc(&ingress_qdisc_ops)) < 0) {
4312 + printk("Unable to register Ingress qdisc\n");
4320 +void cleanup_module(void)
4322 + unregister_qdisc(&ingress_qdisc_ops);
4325 diff -urN ../v2.2.21/linux/net/sched/sch_prio.c linux/net/sched/sch_prio.c
4326 --- ../v2.2.21/linux/net/sched/sch_prio.c Sat Oct 21 12:10:50 2000
4327 +++ linux/net/sched/sch_prio.c Fri Jul 5 22:06:27 2002
4329 * 2 of the License, or (at your option) any later version.
4331 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
4332 + * Fixes: 19990609: J Hadi Salim <hadi@nortelnetworks.com>:
4333 + * Init -- EINVAL when opt undefined
4336 #include <linux/config.h>
4339 struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
4340 struct Qdisc *qdisc;
4343 qdisc = q->queues[prio_classify(skb, sch)];
4345 - if (qdisc->enqueue(skb, qdisc) == 1) {
4346 + if ((ret = qdisc->enqueue(skb, qdisc)) == 0) {
4347 sch->stats.bytes += skb->len;
4348 sch->stats.packets++;
4361 struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
4362 struct Qdisc *qdisc;
4365 qdisc = q->queues[prio_classify(skb, sch)];
4367 - if (qdisc->ops->requeue(skb, qdisc) == 1) {
4368 + if ((ret = qdisc->ops->requeue(skb, qdisc)) == 0) {
4383 - start_bh_atomic();
4384 + sch_tree_lock(sch);
4385 q->bands = qopt->bands;
4386 memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
4389 if (child != &noop_qdisc)
4390 qdisc_destroy(child);
4393 + sch_tree_unlock(sch);
4395 for (i=0; i<=TC_PRIO_MAX; i++) {
4396 int band = q->prio2band[i];
4397 @@ -195,11 +199,12 @@
4398 struct Qdisc *child;
4399 child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
4401 + sch_tree_lock(sch);
4402 child = xchg(&q->queues[band], child);
4405 if (child != &noop_qdisc)
4406 qdisc_destroy(child);
4407 + sch_tree_unlock(sch);
4413 static int prio_init(struct Qdisc *sch, struct rtattr *opt)
4415 - static const u8 prio2band[TC_PRIO_MAX+1] =
4416 - { 1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 };
4417 struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
4420 @@ -217,14 +220,7 @@
4421 q->queues[i] = &noop_qdisc;
4425 - memcpy(q->prio2band, prio2band, sizeof(prio2band));
4426 - for (i=0; i<3; i++) {
4427 - struct Qdisc *child;
4428 - child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
4430 - q->queues[i] = child;
4440 -#ifdef CONFIG_RTNETLINK
4441 static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
4443 struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
4445 skb_trim(skb, b - skb->data);
4450 static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
4452 @@ -265,7 +259,11 @@
4456 - *old = xchg(&q->queues[band], new);
4457 + sch_tree_lock(sch);
4458 + *old = q->queues[band];
4459 + q->queues[band] = new;
4460 + qdisc_reset(*old);
4461 + sch_tree_unlock(sch);
4469 -#ifdef CONFIG_RTNETLINK
4470 static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb,
4473 @@ -330,11 +327,11 @@
4475 if (cl - 1 > q->bands)
4477 + tcm->tcm_handle |= TC_H_MIN(cl);
4478 if (q->queues[cl-1])
4479 tcm->tcm_info = q->queues[cl-1]->handle;
4484 static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
4490 -#ifdef CONFIG_RTNETLINK
4495 struct Qdisc_ops prio_qdisc_ops =
4500 -#ifdef CONFIG_RTNETLINK
4510 +MODULE_LICENSE("GPL");
4511 diff -urN ../v2.2.21/linux/net/sched/sch_red.c linux/net/sched/sch_red.c
4512 --- ../v2.2.21/linux/net/sched/sch_red.c Sat Oct 21 12:11:29 2000
4513 +++ linux/net/sched/sch_red.c Fri Aug 2 02:41:03 2002
4517 * J Hadi Salim <hadi@nortel.com> 980914: computation fixes
4518 + * Alexey Makarenko <makar@phoenix.kharkov.ua> 990814: qave on idle link was calculated incorrectly.
4519 + * J Hadi Salim <hadi@nortelnetworks.com> 980816: ECN support
4522 #include <linux/config.h>
4524 #include <net/sock.h>
4525 #include <net/pkt_sched.h>
4527 +#define RED_ECN_ECT 0x02
4528 +#define RED_ECN_CE 0x01
4531 /* Random Early Detection (RED) algorithm.
4532 =======================================
4534 u32 qth_max; /* Max average length threshold: A scaled */
4537 + unsigned char flags;
4538 char Wlog; /* log(W) */
4539 char Plog; /* random number bits */
4541 @@ -148,8 +154,43 @@
4542 u32 qR; /* Cached random number */
4544 psched_time_t qidlestart; /* Start of idle period */
4545 + struct tc_red_xstats st;
4548 +static int red_ecn_mark(struct sk_buff *skb)
4550 + if (skb->nh.raw + 20 > skb->tail)
4553 + switch (skb->protocol) {
4554 + case __constant_htons(ETH_P_IP):
4556 + u8 tos = skb->nh.iph->tos;
4558 + if (!(tos & RED_ECN_ECT))
4561 + if (!(tos & RED_ECN_CE))
4562 + IP_ECN_set_ce(skb->nh.iph);
4567 + case __constant_htons(ETH_P_IPV6):
4569 + u32 label = *(u32*)skb->nh.raw;
4571 + if (!(label & __constant_htonl(RED_ECN_ECT<<20)))
4573 + label |= __constant_htonl(RED_ECN_CE<<20);
4583 red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
4587 if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) {
4591 PSCHED_GET_TIME(now);
4592 us_idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max, 0);
4593 PSCHED_SET_PASTPERFECT(q->qidlestart);
4594 @@ -179,7 +222,25 @@
4595 I believe that a simpler model may be used here,
4596 but it is field for experiments.
4598 - q->qave >>= q->Stab[(us_idle>>q->Scell_log)&0xFF];
4599 + shift = q->Stab[us_idle>>q->Scell_log];
4602 + q->qave >>= shift;
4604 + /* Approximate initial part of exponent
4605 + with linear function:
4606 + (1-W)^m ~= 1-mW + ...
4608 + Seems, it is the best solution to
4609 + problem of too coarce exponent tabulation.
4612 + us_idle = (q->qave * us_idle)>>q->Scell_log;
4613 + if (us_idle < q->qave/2)
4614 + q->qave -= us_idle;
4619 q->qave += sch->stats.backlog - (q->qave >> q->Wlog);
4621 @@ -200,18 +261,26 @@
4622 sch->stats.backlog += skb->len;
4623 sch->stats.bytes += skb->len;
4624 sch->stats.packets++;
4626 + return NET_XMIT_SUCCESS;
4634 + return NET_XMIT_DROP;
4636 if (q->qave >= q->qth_max) {
4638 sch->stats.overlimits++;
4641 + if (!(q->flags&TC_RED_ECN) || !red_ecn_mark(skb)) {
4650 /* The formula used below causes questions.
4652 @@ -234,10 +303,15 @@
4654 q->qR = net_random()&q->Rmask;
4655 sch->stats.overlimits++;
4659 q->qR = net_random()&q->Rmask;
4664 + sch->stats.drops++;
4665 + return NET_XMIT_CN;
4671 __skb_queue_head(&sch->q, skb);
4672 sch->stats.backlog += skb->len;
4677 static struct sk_buff *
4680 sch->stats.backlog -= skb->len;
4686 @@ -287,17 +362,15 @@
4687 static void red_reset(struct Qdisc* sch)
4689 struct red_sched_data *q = (struct red_sched_data *)sch->data;
4690 - struct sk_buff *skb;
4692 - while((skb=__skb_dequeue(&sch->q))!=NULL)
4694 + __skb_queue_purge(&sch->q);
4695 sch->stats.backlog = 0;
4696 PSCHED_SET_PASTPERFECT(q->qidlestart);
4701 -static int red_init(struct Qdisc *sch, struct rtattr *opt)
4702 +static int red_change(struct Qdisc *sch, struct rtattr *opt)
4704 struct red_sched_data *q = (struct red_sched_data *)sch->data;
4705 struct rtattr *tb[TCA_RED_STAB];
4708 ctl = RTA_DATA(tb[TCA_RED_PARMS-1]);
4710 + sch_tree_lock(sch);
4711 + q->flags = ctl->flags;
4712 q->Wlog = ctl->Wlog;
4713 q->Plog = ctl->Plog;
4714 q->Rmask = ctl->Plog < 32 ? ((1<<ctl->Plog) - 1) : ~0UL;
4715 @@ -323,12 +398,34 @@
4716 memcpy(q->Stab, RTA_DATA(tb[TCA_RED_STAB-1]), 256);
4719 - PSCHED_SET_PASTPERFECT(q->qidlestart);
4720 - MOD_INC_USE_COUNT;
4721 + if (skb_queue_len(&sch->q) == 0)
4722 + PSCHED_SET_PASTPERFECT(q->qidlestart);
4723 + sch_tree_unlock(sch);
4727 -#ifdef CONFIG_RTNETLINK
4728 +static int red_init(struct Qdisc* sch, struct rtattr *opt)
4732 + MOD_INC_USE_COUNT;
4734 + if ((err = red_change(sch, opt)) != 0) {
4735 + MOD_DEC_USE_COUNT;
4741 +int red_copy_xstats(struct sk_buff *skb, struct tc_red_xstats *st)
4743 + RTA_PUT(skb, TCA_XSTATS, sizeof(*st), st);
4750 static int red_dump(struct Qdisc *sch, struct sk_buff *skb)
4752 struct red_sched_data *q = (struct red_sched_data *)sch->data;
4753 @@ -344,16 +441,19 @@
4756 opt.Scell_log = q->Scell_log;
4757 + opt.flags = q->flags;
4758 RTA_PUT(skb, TCA_RED_PARMS, sizeof(opt), &opt);
4759 rta->rta_len = skb->tail - b;
4761 + if (red_copy_xstats(skb, &q->st))
4762 + goto rtattr_failure;
4767 skb_trim(skb, b - skb->data);
4772 static void red_destroy(struct Qdisc *sch)
4774 @@ -375,11 +475,9 @@
4778 - NULL /* red_change */,
4781 -#ifdef CONFIG_RTNETLINK
4788 unregister_qdisc(&red_qdisc_ops);
4791 +MODULE_LICENSE("GPL");
4792 diff -urN ../v2.2.21/linux/net/sched/sch_sfq.c linux/net/sched/sch_sfq.c
4793 --- ../v2.2.21/linux/net/sched/sch_sfq.c Sat Oct 21 12:10:57 2000
4794 +++ linux/net/sched/sch_sfq.c Fri Jul 5 22:06:27 2002
4798 unsigned quantum; /* Allotment per round: MUST BE >= MTU */
4802 struct timer_list perturb_timer;
4803 @@ -275,14 +276,14 @@
4807 - if (++sch->q.qlen < SFQ_DEPTH-1) {
4808 + if (++sch->q.qlen < q->limit-1) {
4809 sch->stats.bytes += skb->len;
4810 sch->stats.packets++;
4817 + return NET_XMIT_CN;
4821 @@ -310,12 +311,12 @@
4825 - if (++sch->q.qlen < SFQ_DEPTH-1)
4827 + if (++sch->q.qlen < q->limit - 1)
4833 + return NET_XMIT_CN;
4837 @@ -387,16 +388,21 @@
4838 if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
4841 - start_bh_atomic();
4842 + sch_tree_lock(sch);
4843 q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
4844 q->perturb_period = ctl->perturb_period*HZ;
4846 + q->limit = min_t(u32, ctl->limit, SFQ_DEPTH);
4848 + while (sch->q.qlen >= q->limit-1)
4851 del_timer(&q->perturb_timer);
4852 if (q->perturb_period) {
4853 q->perturb_timer.expires = jiffies + q->perturb_period;
4854 add_timer(&q->perturb_timer);
4857 + sch_tree_unlock(sch);
4862 q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH;
4863 q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH;
4865 + q->limit = SFQ_DEPTH;
4867 q->tail = SFQ_DEPTH;
4873 -#ifdef CONFIG_RTNETLINK
4874 static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
4876 struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data;
4878 opt.quantum = q->quantum;
4879 opt.perturb_period = q->perturb_period/HZ;
4881 - opt.limit = SFQ_DEPTH;
4882 + opt.limit = q->limit;
4883 opt.divisor = SFQ_HASH_DIVISOR;
4884 - opt.flows = SFQ_DEPTH;
4885 + opt.flows = q->limit;
4887 RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
4890 skb_trim(skb, b - skb->data);
4895 struct Qdisc_ops sfq_qdisc_ops =
4899 NULL, /* sfq_change */
4901 -#ifdef CONFIG_RTNETLINK
4908 unregister_qdisc(&sfq_qdisc_ops);
4911 +MODULE_LICENSE("GPL");
4912 diff -urN ../v2.2.21/linux/net/sched/sch_tbf.c linux/net/sched/sch_tbf.c
4913 --- ../v2.2.21/linux/net/sched/sch_tbf.c Sat Oct 21 12:10:47 2000
4914 +++ linux/net/sched/sch_tbf.c Sun Mar 31 03:18:30 2002
4916 N(t+delta) = min{B/R, N(t) + delta}
4918 If the first packet in queue has length S, it may be
4919 - transmited only at the time t_* when S/R <= N(t_*),
4920 + transmitted only at the time t_* when S/R <= N(t_*),
4921 and in this case N(t) jumps:
4923 N(t_* + 0) = N(t_* - 0) - S/R.
4925 if ((sch->stats.backlog += skb->len) <= q->limit) {
4926 sch->stats.bytes += skb->len;
4927 sch->stats.packets++;
4932 /* Drop action: undo the things that we just did,
4934 if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
4938 + return NET_XMIT_DROP;
4944 __skb_queue_head(&sch->q, skb);
4945 sch->stats.backlog += skb->len;
4952 struct Qdisc *sch = (struct Qdisc*)arg;
4954 sch->flags &= ~TCQ_F_THROTTLED;
4955 - qdisc_wakeup(sch->dev);
4956 + netif_schedule(sch->dev);
4959 static struct sk_buff *
4960 @@ -226,15 +226,13 @@
4964 - if (!sch->dev->tbusy) {
4965 - long delay = PSCHED_US2JIFFIE(max(-toks, -ptoks));
4966 + if (!netif_queue_stopped(sch->dev)) {
4967 + long delay = PSCHED_US2JIFFIE(max_t(long, -toks, -ptoks));
4972 - del_timer(&q->wd_timer);
4973 - q->wd_timer.expires = jiffies + delay;
4974 - add_timer(&q->wd_timer);
4975 + mod_timer(&q->wd_timer, jiffies+delay);
4978 /* Maybe we have a shorter packet in the queue,
4980 struct tc_tbf_qopt *qopt;
4981 struct qdisc_rate_table *rtab = NULL;
4982 struct qdisc_rate_table *ptab = NULL;
4986 if (rtattr_parse(tb, TCA_TBF_PTAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
4987 tb[TCA_TBF_PARMS-1] == NULL ||
4988 @@ -297,18 +295,21 @@
4992 - max_size = psched_mtu(sch->dev);
4993 + for (n = 0; n < 256; n++)
4994 + if (rtab->data[n] > qopt->buffer) break;
4995 + max_size = (n << qopt->rate.cell_log)-1;
4997 - int n = max_size>>qopt->peakrate.cell_log;
4998 - while (n>0 && ptab->data[n-1] > qopt->mtu) {
4999 - max_size -= (1<<qopt->peakrate.cell_log);
5004 + for (n = 0; n < 256; n++)
5005 + if (ptab->data[n] > qopt->mtu) break;
5006 + size = (n << qopt->peakrate.cell_log)-1;
5007 + if (size < max_size) max_size = size;
5009 - if (rtab->data[max_size>>qopt->rate.cell_log] > qopt->buffer)
5013 - start_bh_atomic();
5014 + sch_tree_lock(sch);
5015 q->limit = qopt->limit;
5017 q->max_size = max_size;
5019 q->ptokens = q->mtu;
5020 rtab = xchg(&q->R_tab, rtab);
5021 ptab = xchg(&q->P_tab, ptab);
5023 + sch_tree_unlock(sch);
5031 -#ifdef CONFIG_RTNETLINK
5032 static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb)
5034 struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
5036 skb_trim(skb, b - skb->data);
5041 struct Qdisc_ops tbf_qdisc_ops =
5047 -#ifdef CONFIG_RTNETLINK
5054 unregister_qdisc(&tbf_qdisc_ops);
5057 +MODULE_LICENSE("GPL");
5058 diff -urN ../v2.2.21/linux/net/sched/sch_teql.c linux/net/sched/sch_teql.c
5059 --- ../v2.2.21/linux/net/sched/sch_teql.c Sat Oct 21 12:10:47 2000
5060 +++ linux/net/sched/sch_teql.c Sun Aug 4 18:06:40 2002
5062 if (q->q.qlen <= dev->tx_queue_len) {
5063 sch->stats.bytes += skb->len;
5064 sch->stats.packets++;
5069 __skb_unlink(skb, &q->q);
5073 + return NET_XMIT_DROP;
5078 struct teql_sched_data *q = (struct teql_sched_data *)sch->data;
5080 __skb_queue_head(&q->q, skb);
5085 static struct sk_buff *
5087 master->slaves = NEXT_SLAVE(q);
5088 if (q == master->slaves) {
5089 master->slaves = NULL;
5090 + sch_dev_queue_lock(&master->dev);
5091 qdisc_reset(master->dev.qdisc);
5092 + sch_dev_queue_unlock(&master->dev);
5095 skb_queue_purge(&dat->q);
5098 if (dev->hard_header_len > m->dev.hard_header_len)
5101 + if (&m->dev == dev)