]> git.pld-linux.org Git - packages/kernel.git/blob - ds9-2.2.21-2.diff
- fix unresolved symbols in ipv6 netfilter
[packages/kernel.git] / ds9-2.2.21-2.diff
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
4 @@ -268,6 +268,7 @@
5         struct Qdisc            *qdisc;
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 */
10  
11         /* Bridge stuff */
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
15 @@ -143,4 +143,20 @@
16  
17  #define TCA_FW_MAX TCA_FW_POLICE
18  
19 +/* TC index filter */
20 +
21 +enum
22 +{
23 +       TCA_TCINDEX_UNSPEC,
24 +       TCA_TCINDEX_HASH,
25 +       TCA_TCINDEX_MASK,
26 +       TCA_TCINDEX_SHIFT,
27 +       TCA_TCINDEX_FALL_THROUGH,
28 +       TCA_TCINDEX_CLASSID,
29 +       TCA_TCINDEX_POLICE,
30 +};
31 +
32 +#define TCA_TCINDEX_MAX        TCA_TCINDEX_POLICE
33 +
34 +
35  #endif
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
39 @@ -71,6 +71,7 @@
40  
41  #define TC_H_UNSPEC    (0U)
42  #define TC_H_ROOT      (0xFFFFFFFFU)
43 +#define TC_H_INGRESS    (0xFFFFFFF1U)
44  
45  struct tc_ratespec
46  {
47 @@ -188,6 +189,61 @@
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;
52 +#define TC_RED_ECN     1
53 +};
54 +
55 +struct tc_red_xstats
56 +{
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 */
61 +};
62 +
63 +/* GRED section */
64 +
65 +#define MAX_DPs 16
66 +
67 +enum
68 +{
69 +    TCA_GRED_UNSPEC,
70 +    TCA_GRED_PARMS,
71 +    TCA_GRED_STAB,
72 +    TCA_GRED_DPS,
73 +};
74 +
75 +#define TCA_SET_OFF TCA_GRED_PARMS
76 +struct tc_gred_qopt
77 +{
78 +    __u32           limit;          /* HARD maximal queue length (bytes)    
79 +*/
80 +    __u32           qth_min;        /* Min average length threshold (bytes) 
81 +*/
82 +    __u32           qth_max;        /* Max average length threshold (bytes) 
83 +*/
84 +    __u32           DP;             /* upto 2^32 DPs */
85 +    __u32           backlog;        
86 +    __u32           qave;   
87 +    __u32           forced; 
88 +    __u32           early;  
89 +    __u32           other;  
90 +    __u32           pdrop;  
91 +
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 */
96 +    __u32      packets;
97 +    __u32      bytesin;
98 +};
99 +/* gred setup */
100 +struct tc_gred_sopt
101 +{
102 +    __u32           DPs;
103 +    __u32           def_DP;
104 +    __u8            grio;
105 +
106  };
107  
108  /* HTB section */
109 @@ -323,6 +379,20 @@
110  
111  #define TCA_CBQ_MAX    TCA_CBQ_POLICE
112  
113 +
114 +/* dsmark section */
115 +
116 +enum {
117 +       TCA_DSMARK_UNSPEC,
118 +       TCA_DSMARK_INDICES,
119 +       TCA_DSMARK_DEFAULT_INDEX,
120 +       TCA_DSMARK_SET_TC_INDEX,
121 +       TCA_DSMARK_MASK,
122 +       TCA_DSMARK_VALUE
123 +};
124 +
125 +#define TCA_DSMARK_MAX TCA_DSMARK_VALUE
126 +
127  /* ATM  section */
128  
129  enum {
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
133 @@ -115,6 +115,11 @@
134                 __u32   ifield;
135         } private;
136  #endif
137 +
138 +#ifdef CONFIG_NET_SCHED
139 +    __u32           tc_index;               /* traffic control index */
140 +#endif
141 +
142  #if defined(CONFIG_ATM) && !defined(CONFIG_ATM_SKB)
143  
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
148 @@ -0,0 +1,79 @@
149 +/* include/net/dsfield.h - Manipulation of the Differentiated Services field */
150 +
151 +/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
152 +
153 +
154 +#ifndef __NET_DSFIELD_H
155 +#define __NET_DSFIELD_H
156 +
157 +#include <linux/types.h>
158 +#include <linux/ip.h>
159 +#include <linux/ipv6.h>
160 +#include <asm/byteorder.h>
161 +
162 +
163 +extern __inline__ __u8 ipv4_get_dsfield(struct iphdr *iph)
164 +{
165 +       return iph->tos;
166 +}
167 +
168 +
169 +extern __inline__ __u8 ipv6_get_dsfield(struct ipv6hdr *ipv6h)
170 +{
171 +       return ntohs(*(__u16 *) ipv6h) >> 4;
172 +}
173 +
174 +
175 +extern __inline__ void ipv4_change_dsfield(struct iphdr *iph,__u8 mask,
176 +    __u8 value)
177 +{
178 +        __u32 check = ntohs(iph->check);
179 +       __u8 dsfield;
180 +
181 +       dsfield = (iph->tos & mask) | value;
182 +       check += iph->tos;
183 +       if ((check+1) >> 16) check = (check+1) & 0xffff;
184 +       check -= dsfield;
185 +       check += check >> 16; /* adjust carry */
186 +       iph->check = htons(check);
187 +       iph->tos = dsfield;
188 +}
189 +
190 +
191 +extern __inline__ void ipv6_change_dsfield(struct ipv6hdr *ipv6h,__u8 mask,
192 +    __u8 value)
193 +{
194 +        __u16 tmp;
195 +
196 +       tmp = ntohs(*(__u16 *) ipv6h);
197 +       tmp = (tmp & ((mask << 4) | 0xf00f)) | (value << 4);
198 +       *(__u16 *) ipv6h = htons(tmp);
199 +}
200 +
201 +
202 +#if 0 /* put this later into asm-i386 or such ... */
203 +
204 +extern __inline__ void ip_change_dsfield(struct iphdr *iph,__u16 dsfield)
205 +{
206 +       __u16 check;
207 +
208 +       __asm__ __volatile__("
209 +               movw    10(%1),%0
210 +               xchg    %b0,%h0
211 +               addb    1(%1),%b0
212 +               adcb    $0,%h0
213 +               adcw    $1,%0
214 +               cmc
215 +               sbbw    %2,%0
216 +               sbbw    $0,%0
217 +               movb    %b2,1(%1)
218 +               xchg    %b0,%h0
219 +               movw    %0,10(%1)"
220 +           : "=&r" (check)
221 +           : "r" (iph), "r" (dsfield)
222 +           : "cc");
223 +}
224 +
225 +#endif
226 +
227 +#endif
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
231 @@ -77,16 +77,6 @@
232         return -1;
233  }
234  
235 -extern __inline__ unsigned long cls_set_class(unsigned long *clp, unsigned long cl)
236 -{
237 -       unsigned long old_cl; 
238 -
239 -       old_cl = *clp;
240 -       *clp = cl;
241 -       synchronize_bh();
242 -       return old_cl;
243 -}
244 -
245  extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
246  extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
247  
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
251 @@ -8,6 +8,7 @@
252  #define PSCHED_CLOCK_SOURCE    PSCHED_JIFFIES
253  
254  #include <linux/pkt_sched.h>
255 +#include <linux/ip.h>
256  #include <net/pkt_cls.h>
257  
258  struct rtattr;
259 @@ -78,6 +79,7 @@
260         unsigned                flags;
261  #define TCQ_F_BUILTIN  1
262  #define TCQ_F_THROTTLED        2
263 +#define TCQ_F_INGRES   4
264         struct Qdisc_ops        *ops;
265         struct Qdisc            *next;
266         u32                     handle;
267 @@ -106,6 +108,111 @@
268         int             refcnt;
269  };
270  
271 +#ifndef MODULE_LICENSE
272 +#define MODULE_LICENSE(X)
273 +#endif
274 +
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) */
283 +#endif
284 +
285 +#define likely(e)      (e)
286 +#define unlikely(e)    (e)
287 +
288 +#ifndef min_t
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; })
293 +#endif
294 +
295 +static inline void list_del_init(struct list_head *entry)
296 +{
297 +       __list_del(entry->prev, entry->next);
298 +       INIT_LIST_HEAD(entry);
299 +}
300 +
301 +static inline void __skb_queue_purge(struct sk_buff_head *list)
302 +{
303 +       struct sk_buff *skb;
304 +       while ((skb=__skb_dequeue(list))!=NULL)
305 +               kfree_skb(skb);
306 +}
307 +#define del_timer_sync(t) del_timer(t)
308 +
309 +#define netif_schedule qdisc_wakeup
310 +#define netif_queue_stopped(D) (D->tbusy)
311 +#ifndef BUG_TRAP
312 +#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
313 +#endif
314 +
315 +static inline void IP_ECN_set_ce(struct iphdr *iph)
316 +{
317 +       u32 check = iph->check;
318 +       check += __constant_htons(0xFFFE);
319 +       iph->check = check + (check>=0xFFFF);
320 +       iph->tos |= 1;
321 +}
322 +
323 +static inline void sch_tree_lock(struct Qdisc *q)
324 +{
325 +       start_bh_atomic();
326 +}
327 +
328 +static inline void sch_tree_unlock(struct Qdisc *q)
329 +{
330 +       end_bh_atomic();
331 +}
332 +
333 +static inline void tcf_tree_lock(struct tcf_proto *tp)
334 +{
335 +       wmb();
336 +}
337 +
338 +static inline void tcf_tree_unlock(struct tcf_proto *tp)
339 +{
340 +       synchronize_bh();
341 +}
342 +
343 +static inline void sch_dev_queue_lock(struct device *dev)
344 +{
345 +       start_bh_atomic();
346 +}
347 +
348 +static inline void sch_dev_queue_unlock(struct device *dev)
349 +{
350 +       end_bh_atomic();
351 +}
352 +
353 +
354 +static inline unsigned long
355 +cls_set_class(struct tcf_proto *tp, unsigned long *clp, unsigned long cl)
356 +{
357 +       unsigned long old_cl;
358 +
359 +       old_cl = *clp;
360 +       wmb();
361 +       *clp = cl;
362 +       synchronize_bh();
363 +       return old_cl;
364 +}
365 +
366 +static inline unsigned long
367 +__cls_set_class(unsigned long *clp, unsigned long cl)
368 +{
369 +       unsigned long old_cl;
370 +
371 +       old_cl = *clp;
372 +       *clp = cl;
373 +       return old_cl;
374 +}
375 +
376  
377  /* 
378     Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
379 @@ -176,7 +283,7 @@
380  
381  #define PSCHED_EXPORTLIST_2
382  
383 -#if ~0UL == 0xFFFFFFFF
384 +#if BITS_PER_LONG <= 32
385  
386  #define PSCHED_WATCHER unsigned long
387  
388 @@ -207,7 +314,7 @@
389  
390  #define PSCHED_US2JIFFIE(delay) (((delay)+psched_clock_per_hz-1)/psched_clock_per_hz)
391  
392 -#if CPU == 586 || CPU == 686
393 +#ifdef CONFIG_X86_TSC
394  
395  #define PSCHED_GET_TIME(stamp) \
396  ({ u64 __cur; \
397 @@ -313,8 +420,8 @@
398  #define PSCHED_TDIFF(tv1, tv2) (long)((tv1) - (tv2))
399  #define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) \
400  ({ \
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; } \
405            __delta; \
406  })
407  
408 @@ -349,6 +456,7 @@
409         struct tc_stats stats;
410  };
411  
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);
416 @@ -364,6 +472,8 @@
417  extern struct Qdisc_ops noop_qdisc_ops;
418  extern struct Qdisc_ops pfifo_qdisc_ops;
419  extern struct Qdisc_ops bfifo_qdisc_ops;
420 +
421 +extern int call_in_ingress(struct sk_buff *skb);
422  
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
428 @@ -195,6 +195,9 @@
429  #ifdef CONFIG_IP_FIREWALL
430          skb->fwmark = 0;
431  #endif
432 +#ifdef CONFIG_NET_SCHED
433 +        skb->tc_index = 0;
434 +#endif
435         memset(skb->cb, 0, sizeof(skb->cb));
436         skb->priority = 0;
437  }
438 @@ -307,6 +310,9 @@
439  #ifdef CONFIG_IP_FIREWALL
440          n->fwmark = skb->fwmark;
441  #endif
442 +#ifdef CONFIG_NET_SCHED
443 +       n->tc_index = skb->tc_index;
444 +#endif
445         return n;
446  }
447  
448 @@ -355,6 +361,9 @@
449         n->security=skb->security;
450  #ifdef CONFIG_IP_FIREWALL
451          n->fwmark = skb->fwmark;
452 +#endif
453 +#ifdef CONFIG_NET_SCHED
454 +       n->tc_index = skb->tc_index;
455  #endif
456  
457         return n;
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
461 @@ -98,6 +98,7 @@
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
466   *
467   *  
468   *
469 @@ -149,6 +150,11 @@
470  #include <linux/mroute.h>
471  #include <linux/netlink.h>
472  
473 +#ifdef CONFIG_FIREWALL
474 +#if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE)
475 +#include <net/pkt_sched.h>
476 +#endif
477 +#endif
478  /*
479   *     SNMP management statistics
480   */
481 @@ -469,6 +475,11 @@
482         fwres = call_in_firewall(PF_INET, dev, iph, &rport, &skb);
483         if (fwres < FW_ACCEPT && fwres != FW_REJECT)
484                 goto drop;
485 +#if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE)
486 +        if (FW_ACCEPT != call_in_ingress(skb))
487 +                goto drop;
488 +#endif
489 +
490         iph = skb->nh.iph;
491  #endif /* CONFIG_FIREWALL */
492  
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
496 @@ -548,6 +548,7 @@
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);
504 @@ -560,6 +561,9 @@
505  EXPORT_SYMBOL(tcf_police_dump);
506  #endif
507  #endif
508 +#endif
509 +#ifdef CONFIG_NET_SCH_INGRESS
510 +EXPORT_SYMBOL(call_in_ingress);
511  #endif
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
517 @@ -12,12 +12,17 @@
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
524 +
525  bool 'QoS support' CONFIG_NET_QOS
526  if [ "$CONFIG_NET_QOS" = "y" ]; then
527      bool 'Rate estimator' CONFIG_NET_ESTIMATOR
528  fi
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
535 @@ -27,7 +32,7 @@
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
541    fi
542  fi
543  
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
547 @@ -28,6 +28,14 @@
548  
549  endif
550  
551 +ifeq ($(CONFIG_NET_SCH_INGRESS), y)
552 +O_OBJS += sch_ingress.o
553 +else
554 +  ifeq ($(CONFIG_NET_SCH_INGRESS), m)
555 +       M_OBJS += sch_ingress.o
556 +  endif
557 +endif
558 +
559  ifeq ($(CONFIG_NET_SCH_CBQ), y)
560  O_OBJS += sch_cbq.o
561  else
562 @@ -98,6 +106,30 @@
563  else
564    ifeq ($(CONFIG_NET_SCH_TEQL), m)
565         M_OBJS += sch_teql.o
566 +  endif
567 +endif
568 +
569 +ifeq ($(CONFIG_NET_SCH_GRED), y)
570 +O_OBJS += sch_gred.o
571 +else
572 +  ifeq ($(CONFIG_NET_SCH_GRED), m)
573 +       M_OBJS += sch_gred.o
574 +  endif
575 +endif
576 +
577 +ifeq ($(CONFIG_NET_SCH_DSMARK), y)
578 +O_OBJS += sch_dsmark.o
579 +else
580 +  ifeq ($(CONFIG_NET_SCH_DSMARK), m)
581 +       M_OBJS += sch_dsmark.o
582 +  endif
583 +endif
584 +
585 +ifeq ($(CONFIG_NET_CLS_TCINDEX), y)
586 +O_OBJS += cls_tcindex.o
587 +else
588 +  ifeq ($(CONFIG_NET_CLS_TCINDEX), m)
589 +       M_OBJS += cls_tcindex.o
590    endif
591  endif
592  
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
596 @@ -217,8 +217,10 @@
597                         kfree(tp);
598                         goto errout;
599                 }
600 +               sch_dev_queue_lock(dev);
601                 tp->next = *back;
602                 *back = tp;
603 +               sch_dev_queue_unlock(dev);
604         } else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
605                 goto errout;
606  
607 @@ -438,6 +440,9 @@
608  #endif
609  #ifdef CONFIG_NET_CLS_RSVP
610         INIT_TC_FILTER(rsvp);
611 +#endif
612 +#ifdef CONFIG_NET_CLS_TCINDEX
613 +       INIT_TC_FILTER(tcindex);
614  #endif
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
620 @@ -136,7 +136,7 @@
621                         unsigned long cl;
622                         head->ht[h] = f->next;
623  
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 @@
630                 if (*fp == f) {
631                         unsigned long cl;
632  
633 +                       tcf_tree_lock(tp);
634                         *fp = f->next;
635 -                       synchronize_bh();
636 +                       tcf_tree_unlock(tp);
637  
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);
643 @@ -203,7 +204,7 @@
644  
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);
649                         if (cl)
650                                 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
651                 }
652 @@ -211,8 +212,9 @@
653                 if (tb[TCA_FW_POLICE-1]) {
654                         struct tcf_police *police = tcf_police_locate(tb[TCA_FW_POLICE-1], tca[TCA_RATE-1]);
655  
656 +                       tcf_tree_lock(tp);
657                         police = xchg(&f->police, police);
658 -                       synchronize_bh();
659 +                       tcf_tree_unlock(tp);
660  
661                         tcf_police_release(police);
662                 }
663 @@ -229,8 +231,9 @@
664                         return -ENOBUFS;
665                 memset(head, 0, sizeof(*head));
666  
667 +               tcf_tree_lock(tp);
668                 tp->root = head;
669 -               synchronize_bh();
670 +               tcf_tree_unlock(tp);
671         }
672  
673         f = kmalloc(sizeof(struct fw_filter), GFP_KERNEL);
674 @@ -245,7 +248,7 @@
675                 if (RTA_PAYLOAD(tb[TCA_FW_CLASSID-1]) != 4)
676                         goto errout;
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));
680         }
681  
682  #ifdef CONFIG_NET_CLS_POLICE
683 @@ -254,8 +257,9 @@
684  #endif
685  
686         f->next = head->ht[fw_hash(handle)];
687 -       wmb();
688 +       tcf_tree_lock(tp);
689         head->ht[fw_hash(handle)] = f;
690 +       tcf_tree_unlock(tp);
691  
692         *arg = (unsigned long)f;
693         return 0;
694 @@ -294,7 +298,6 @@
695         }
696  }
697  
698 -#ifdef CONFIG_RTNETLINK
699  static int fw_dump(struct tcf_proto *tp, unsigned long fh,
700                    struct sk_buff *skb, struct tcmsg *t)
701  {
702 @@ -335,7 +338,8 @@
703         rta->rta_len = skb->tail - b;
704  #ifdef CONFIG_NET_CLS_POLICE
705         if (f->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;
709         }
710  #endif
711         return skb->len;
712 @@ -344,8 +348,6 @@
713         skb_trim(skb, b - skb->data);
714         return -1;
715  }
716 -#endif
717 -
718  
719  struct tcf_proto_ops cls_fw_ops = {
720         NULL,
721 @@ -359,11 +361,7 @@
722         fw_change,
723         fw_delete,
724         fw_walk,
725 -#ifdef CONFIG_RTNETLINK
726         fw_dump
727 -#else
728 -       NULL
729 -#endif
730  };
731  
732  #ifdef MODULE
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
736 @@ -83,11 +83,11 @@
737         return id&0xF;
738  }
739  
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)
742  {
743 -       start_bh_atomic();
744 +       sch_dev_queue_lock(dev);
745         memset(head->fastmap, 0, sizeof(head->fastmap));
746 -       end_bh_atomic();
747 +       sch_dev_queue_unlock(dev);
748  }
749  
750  static void __inline__
751 @@ -297,7 +297,7 @@
752                                         unsigned long cl;
753  
754                                         b->ht[h2] = f->next;
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 @@
761  {
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;
765 +       unsigned h = 0;
766         struct route4_bucket *b;
767         int i;
768  
769         if (!head || !f)
770                 return -EINVAL;
771  
772 +       h = f->handle;
773         b = f->bkt;
774  
775         for (fp = &b->ht[from_hash(h>>16)]; *fp; fp = &(*fp)->next) {
776                 if (*fp == f) {
777                         unsigned long cl;
778  
779 +                       tcf_tree_lock(tp);
780                         *fp = f->next;
781 -                       synchronize_bh();
782 +                       tcf_tree_unlock(tp);
783  
784 -                       route4_reset_fastmap(head, f->id);
785 +                       route4_reset_fastmap(tp->q->dev, head, f->id);
786  
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);
790  
791  #ifdef CONFIG_NET_CLS_POLICE
792 @@ -349,8 +351,9 @@
793                                         return 0;
794  
795                         /* OK, session has no flows */
796 +                       tcf_tree_lock(tp);
797                         head->table[to_hash(h)] = NULL;
798 -                       synchronize_bh();
799 +                       tcf_tree_unlock(tp);
800  
801                         kfree(b);
802                         return 0;
803 @@ -387,7 +390,7 @@
804                         unsigned long cl;
805  
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));
809                         if (cl)
810                                 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
811                 }
812 @@ -395,8 +398,9 @@
813                 if (tb[TCA_ROUTE4_POLICE-1]) {
814                         struct tcf_police *police = tcf_police_locate(tb[TCA_ROUTE4_POLICE-1], tca[TCA_RATE-1]);
815  
816 +                       tcf_tree_lock(tp);
817                         police = xchg(&f->police, police);
818 -                       synchronize_bh();
819 +                       tcf_tree_unlock(tp);
820  
821                         tcf_police_release(police);
822                 }
823 @@ -412,8 +416,9 @@
824                         return -ENOBUFS;
825                 memset(head, 0, sizeof(struct route4_head));
826  
827 +               tcf_tree_lock(tp);
828                 tp->root = head;
829 -               synchronize_bh();
830 +               tcf_tree_unlock(tp);
831         }
832  
833         f = kmalloc(sizeof(struct route4_filter), GFP_KERNEL);
834 @@ -475,8 +480,9 @@
835                         goto errout;
836                 memset(b, 0, sizeof(*b));
837  
838 +               tcf_tree_lock(tp);
839                 head->table[h1] = b;
840 -               synchronize_bh();
841 +               tcf_tree_unlock(tp);
842         }
843         f->bkt = b;
844  
845 @@ -489,17 +495,18 @@
846                         goto errout;
847         }
848  
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]);
854  #endif
855  
856         f->next = f1;
857 -       wmb();
858 +       tcf_tree_lock(tp);
859         *ins_f = f;
860 +       tcf_tree_unlock(tp);
861  
862 -       route4_reset_fastmap(head, f->id);
863 +       route4_reset_fastmap(tp->q->dev, head, f->id);
864         *arg = (unsigned long)f;
865         return 0;
866  
867 @@ -543,7 +550,6 @@
868         }
869  }
870  
871 -#ifdef CONFIG_RTNETLINK
872  static int route4_dump(struct tcf_proto *tp, unsigned long fh,
873                        struct sk_buff *skb, struct tcmsg *t)
874  {
875 @@ -589,7 +595,8 @@
876         rta->rta_len = skb->tail - b;
877  #ifdef CONFIG_NET_CLS_POLICE
878         if (f->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;
882         }
883  #endif
884         return skb->len;
885 @@ -598,7 +605,6 @@
886         skb_trim(skb, b - skb->data);
887         return -1;
888  }
889 -#endif
890  
891  struct tcf_proto_ops cls_route4_ops = {
892         NULL,
893 @@ -612,11 +618,7 @@
894         route4_change,
895         route4_delete,
896         route4_walk,
897 -#ifdef CONFIG_RTNETLINK
898         route4_dump
899 -#else
900 -       NULL
901 -#endif
902  };
903  
904  #ifdef MODULE
905 @@ -630,3 +632,4 @@
906         unregister_tcf_proto_ops(&cls_route4_ops);
907  }
908  #endif
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
913 @@ -39,3 +39,4 @@
914  #define RSVP_OPS       cls_rsvp_ops
915  
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
921 @@ -282,7 +282,7 @@
922                                         unsigned long cl;
923  
924                                         s->ht[h2] = f->next;
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 @@
931                         unsigned long cl;
932  
933  
934 +                       tcf_tree_lock(tp);
935                         *fp = f->next;
936 -                       synchronize_bh();
937 +                       tcf_tree_unlock(tp);
938  
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);
942  
943  #ifdef CONFIG_NET_CLS_POLICE
944 @@ -332,8 +333,9 @@
945                         for (sp = &((struct rsvp_head*)tp->root)->ht[h&0xFF];
946                              *sp; sp = &(*sp)->next) {
947                                 if (*sp == s) {
948 +                                       tcf_tree_lock(tp);
949                                         *sp = s->next;
950 -                                       synchronize_bh();
951 +                                       tcf_tree_unlock(tp);
952  
953                                         kfree(s);
954                                         return 0;
955 @@ -446,7 +448,7 @@
956                         unsigned long cl;
957  
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));
961                         if (cl)
962                                 tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
963                 }
964 @@ -454,8 +456,9 @@
965                 if (tb[TCA_RSVP_POLICE-1]) {
966                         struct tcf_police *police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]);
967  
968 +                       tcf_tree_lock(tp);
969                         police = xchg(&f->police, police);
970 -                       synchronize_bh();
971 +                       tcf_tree_unlock(tp);
972  
973                         tcf_police_release(police);
974                 }
975 @@ -536,7 +539,7 @@
976  
977                         f->sess = s;
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]);
984 @@ -612,7 +615,6 @@
985         }
986  }
987  
988 -#ifdef CONFIG_RTNETLINK
989  static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
990                      struct sk_buff *skb, struct tcmsg *t)
991  {
992 @@ -659,7 +661,8 @@
993         rta->rta_len = skb->tail - b;
994  #ifdef CONFIG_NET_CLS_POLICE
995         if (f->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;
999         }
1000  #endif
1001         return skb->len;
1002 @@ -668,7 +671,6 @@
1003         skb_trim(skb, b - skb->data);
1004         return -1;
1005  }
1006 -#endif
1007  
1008  struct tcf_proto_ops RSVP_OPS = {
1009         NULL,
1010 @@ -682,11 +684,7 @@
1011         rsvp_change,
1012         rsvp_delete,
1013         rsvp_walk,
1014 -#ifdef CONFIG_RTNETLINK
1015         rsvp_dump
1016 -#else
1017 -       NULL
1018 -#endif
1019  };
1020  
1021  #ifdef MODULE
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
1025 @@ -40,3 +40,4 @@
1026  #define RSVP_OPS       cls_rsvp6_ops
1027  
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
1033 @@ -0,0 +1,509 @@
1034 +/*
1035 + * net/sched/cls_tcindex.c     Packet classifier for skb->tc_index
1036 + *
1037 + * Written 1998,1999 by Werner Almesberger, EPFL ICA
1038 + */
1039 +
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>
1050 +
1051 +
1052 +/*
1053 + * Not quite sure if we need all the xchgs Alexey uses when accessing things.
1054 + * Can always add them later ... :)
1055 + */
1056 +
1057 +/*
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.
1061 + */
1062 +
1063 +#define PERFECT_HASH_THRESHOLD 64      /* use perfect hash if not bigger */
1064 +#define DEFAULT_HASH_SIZE      64      /* optimized for diffserv */
1065 +
1066 +
1067 +#if 1 /* control */
1068 +#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
1069 +#else
1070 +#define DPRINTK(format,args...)
1071 +#endif
1072 +
1073 +#if 0 /* data */
1074 +#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
1075 +#else
1076 +#define D2PRINTK(format,args...)
1077 +#endif
1078 +
1079 +
1080 +#define        PRIV(tp)        ((struct tcindex_data *) (tp)->root)
1081 +
1082 +
1083 +struct tcindex_filter_result {
1084 +       struct tcf_police *police;
1085 +       struct tcf_result res;
1086 +};
1087 +
1088 +struct tcindex_filter {
1089 +       __u16 key;
1090 +       struct tcindex_filter_result result;
1091 +       struct tcindex_filter *next;
1092 +};
1093 +
1094 +
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;
1098 +                                     NULL if unused */
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 */
1104 +};
1105 +
1106 +
1107 +static struct tcindex_filter_result *lookup(struct tcindex_data *p,__u16 key)
1108 +{
1109 +       struct tcindex_filter *f;
1110 +
1111 +       if (p->perfect)
1112 +               return p->perfect[key].res.class ? p->perfect+key : NULL;
1113 +       if (!p->h)
1114 +               return NULL;
1115 +       for (f = p->h[key % p->hash]; f; f = f->next) {
1116 +               if (f->key == key)
1117 +                       return &f->result;
1118 +       }
1119 +       return NULL;
1120 +}
1121 +
1122 +
1123 +static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
1124 +                         struct tcf_result *res)
1125 +{
1126 +       struct tcindex_data *p = PRIV(tp);
1127 +       struct tcindex_filter_result *f;
1128 +
1129 +       D2PRINTK("tcindex_classify(skb %p,tp %p,res %p),p %p\n",skb,tp,res,p);
1130 +
1131 +       f = lookup(p,(skb->tc_index & p->mask) >> p->shift);
1132 +       if (!f) {
1133 +               if (!p->fall_through)
1134 +                       return -1;
1135 +               res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle),
1136 +                   (skb->tc_index& p->mask) >> p->shift);
1137 +               res->class = 0;
1138 +               D2PRINTK("alg 0x%x\n",res->classid);
1139 +               return 0;
1140 +       }
1141 +       *res = f->res;
1142 +       D2PRINTK("map 0x%x\n",res->classid);
1143 +#ifdef CONFIG_NET_CLS_POLICE
1144 +       if (f->police) {
1145 +               int result;
1146 +
1147 +               result = tcf_police(skb,f->police);
1148 +               D2PRINTK("police %d\n",res);
1149 +               return result;
1150 +       }
1151 +#endif
1152 +       return 0;
1153 +}
1154 +
1155 +
1156 +static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
1157 +{
1158 +       struct tcindex_data *p = PRIV(tp);
1159 +       struct tcindex_filter_result *r;
1160 +
1161 +       DPRINTK("tcindex_get(tp %p,handle 0x%08x)\n",tp,handle);
1162 +       if (p->perfect && handle >= p->alloc_hash)
1163 +               return 0;
1164 +       r = lookup(PRIV(tp),handle);
1165 +       return r && r->res.class ? (unsigned long) r : 0;
1166 +}
1167 +
1168 +
1169 +static void tcindex_put(struct tcf_proto *tp, unsigned long f)
1170 +{
1171 +       DPRINTK("tcindex_put(tp %p,f 0x%lx)\n",tp,f);
1172 +}
1173 +
1174 +
1175 +static int tcindex_init(struct tcf_proto *tp)
1176 +{
1177 +       struct tcindex_data *p;
1178 +
1179 +       DPRINTK("tcindex_init(tp %p)\n",tp);
1180 +       MOD_INC_USE_COUNT;
1181 +       p = kmalloc(sizeof(struct tcindex_data),GFP_KERNEL);
1182 +       if (!p) {
1183 +               MOD_DEC_USE_COUNT;
1184 +               return -ENOMEM;
1185 +       }
1186 +       tp->root = p;
1187 +       p->perfect = NULL;
1188 +       p->h = NULL;
1189 +       p->hash = 0;
1190 +       p->mask = 0xffff;
1191 +       p->shift = 0;
1192 +       p->fall_through = 1;
1193 +       return 0;
1194 +}
1195 +
1196 +
1197 +static int tcindex_delete(struct tcf_proto *tp, unsigned long arg)
1198 +{
1199 +       struct tcindex_data *p = PRIV(tp);
1200 +       struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg;
1201 +       struct tcindex_filter *f = NULL;
1202 +       unsigned long cl;
1203 +
1204 +       DPRINTK("tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n",tp,arg,p,f);
1205 +       if (p->perfect) {
1206 +               if (!r->res.class)
1207 +                       return -ENOENT;
1208 +       } else {
1209 +               int i;
1210 +               struct tcindex_filter **walk = NULL;
1211 +
1212 +               for (i = 0; i < p->hash; i++)
1213 +                       for (walk = p->h+i; *walk; walk = &(*walk)->next)
1214 +                               if (&(*walk)->result == r)
1215 +                                       goto found;
1216 +               return -ENOENT;
1217 +
1218 +found:
1219 +               f = *walk;
1220 +               tcf_tree_lock(tp); 
1221 +               *walk = f->next;
1222 +               tcf_tree_unlock(tp);
1223 +       }
1224 +       cl = __cls_set_class(&r->res.class,0);
1225 +       if (cl)
1226 +               tp->q->ops->cl_ops->unbind_tcf(tp->q,cl);
1227 +#ifdef CONFIG_NET_CLS_POLICE
1228 +       tcf_police_release(r->police);
1229 +#endif
1230 +       if (f)
1231 +               kfree(f);
1232 +       return 0;
1233 +}
1234 +
1235 +
1236 +/*
1237 + * There are no parameters for tcindex_init, so we overload tcindex_change
1238 + */
1239 +
1240 +
1241 +static int tcindex_change(struct tcf_proto *tp,unsigned long base,u32 handle,
1242 +    struct rtattr **tca,unsigned long *arg)
1243 +{
1244 +       struct tcindex_filter_result new_filter_result = {
1245 +               NULL,           /* no policing */
1246 +               { 0,0 },        /* no classification */
1247 +       };
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;
1254 +       int hash,shift;
1255 +       __u16 mask;
1256 +
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);
1259 +       if (arg)
1260 +               DPRINTK("*arg = 0x%lx\n",*arg);
1261 +       if (!opt)
1262 +               return 0;
1263 +       if (rtattr_parse(tb,TCA_TCINDEX_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0)
1264 +               return -EINVAL;
1265 +       if (!tb[TCA_TCINDEX_HASH-1]) {
1266 +               hash = p->hash;
1267 +       } else {
1268 +               if (RTA_PAYLOAD(tb[TCA_TCINDEX_HASH-1]) < sizeof(int))
1269 +                       return -EINVAL;
1270 +               hash = *(int *) RTA_DATA(tb[TCA_TCINDEX_HASH-1]);
1271 +       }
1272 +       if (!tb[TCA_TCINDEX_MASK-1]) {
1273 +               mask = p->mask;
1274 +       } else {
1275 +               if (RTA_PAYLOAD(tb[TCA_TCINDEX_MASK-1]) < sizeof(__u16))
1276 +                       return -EINVAL;
1277 +               mask = *(__u16 *) RTA_DATA(tb[TCA_TCINDEX_MASK-1]);
1278 +       }
1279 +       if (!tb[TCA_TCINDEX_SHIFT-1])
1280 +               shift = p->shift;
1281 +       else {
1282 +               if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(__u16))
1283 +                       return -EINVAL;
1284 +               shift = *(int *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]);
1285 +       }
1286 +       if (p->perfect && hash <= (mask >> shift))
1287 +               return -EBUSY;
1288 +       if (p->perfect && hash > p->alloc_hash)
1289 +               return -EBUSY;
1290 +       if (p->h && hash != p->alloc_hash)
1291 +               return -EBUSY;
1292 +       p->hash = hash;
1293 +       p->mask = mask;
1294 +       p->shift = shift;
1295 +       if (tb[TCA_TCINDEX_FALL_THROUGH-1]) {
1296 +               if (RTA_PAYLOAD(tb[TCA_TCINDEX_FALL_THROUGH-1]) < sizeof(int))
1297 +                       return -EINVAL;
1298 +               p->fall_through =
1299 +                   *(int *) RTA_DATA(tb[TCA_TCINDEX_FALL_THROUGH-1]);
1300 +       }
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])
1304 +               return 0;
1305 +       if (!hash) {
1306 +               if ((mask >> shift) < PERFECT_HASH_THRESHOLD) {
1307 +                       p->hash = (mask >> shift)+1;
1308 +               } else {
1309 +                       p->hash = DEFAULT_HASH_SIZE;
1310 +               }
1311 +       }
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);
1318 +                       if (!p->perfect)
1319 +                               return -ENOMEM;
1320 +                       memset(p->perfect, 0,
1321 +                              p->hash * sizeof(struct tcindex_filter_result));
1322 +               } else {
1323 +                       p->h = kmalloc(p->hash*sizeof(struct tcindex_filter *),
1324 +                           GFP_KERNEL);
1325 +                       if (!p->h)
1326 +                               return -ENOMEM;
1327 +                       memset(p->h, 0, p->hash*sizeof(struct tcindex_filter *));
1328 +               }
1329 +       }
1330 +       /*
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).
1337 +        */
1338 +       if (p->perfect && handle >= p->alloc_hash)
1339 +               return -EINVAL;
1340 +       if (p->perfect) {
1341 +               r = p->perfect+handle;
1342 +       } else {
1343 +               r = lookup(p,handle);
1344 +               DPRINTK("r=%p\n",r);
1345 +               if (!r)
1346 +                       r = &new_filter_result;
1347 +       }
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);
1351 +
1352 +               if (cl)
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,
1356 +                                                           r->res.classid);
1357 +               if (!r->res.class) {
1358 +                       r->res.classid = 0;
1359 +                       return -ENOENT;
1360 +               }
1361 +        }
1362 +#ifdef CONFIG_NET_CLS_POLICE
1363 +       {
1364 +               struct tcf_police *police;
1365 +
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);
1372 +       }
1373 +#endif
1374 +       if (r != &new_filter_result)
1375 +               return 0;
1376 +       f = kmalloc(sizeof(struct tcindex_filter),GFP_KERNEL);
1377 +       if (!f)
1378 +               return -ENOMEM;
1379 +       f->key = handle;
1380 +       f->result = new_filter_result;
1381 +       f->next = NULL;
1382 +       for (walk = p->h+(handle % p->hash); *walk; walk = &(*walk)->next)
1383 +               /* nothing */;
1384 +       wmb();
1385 +       *walk = f;
1386 +       return 0;
1387 +}
1388 +
1389 +
1390 +static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
1391 +{
1392 +       struct tcindex_data *p = PRIV(tp);
1393 +       struct tcindex_filter *f,*next;
1394 +       int i;
1395 +
1396 +       DPRINTK("tcindex_walk(tp %p,walker %p),p %p\n",tp,walker,p);
1397 +       if (p->perfect) {
1398 +               for (i = 0; i < p->hash; i++) {
1399 +                       if (!p->perfect[i].res.class)
1400 +                               continue;
1401 +                       if (walker->count >= walker->skip) {
1402 +                               if (walker->fn(tp,
1403 +                                   (unsigned long) (p->perfect+i), walker)
1404 +                                    < 0) {
1405 +                                       walker->stop = 1;
1406 +                                       return;
1407 +                               }
1408 +                       }
1409 +                       walker->count++;
1410 +               }
1411 +       }
1412 +       if (!p->h)
1413 +               return;
1414 +       for (i = 0; i < p->hash; i++) {
1415 +               for (f = p->h[i]; f; f = next) {
1416 +                       next = f->next;
1417 +                       if (walker->count >= walker->skip) {
1418 +                               if (walker->fn(tp,(unsigned long) &f->result,
1419 +                                   walker) < 0) {
1420 +                                       walker->stop = 1;
1421 +                                       return;
1422 +                               }
1423 +                       }
1424 +                       walker->count++;
1425 +               }
1426 +       }
1427 +}
1428 +
1429 +
1430 +static int tcindex_destroy_element(struct tcf_proto *tp,
1431 +    unsigned long arg, struct tcf_walker *walker)
1432 +{
1433 +       return tcindex_delete(tp,arg);
1434 +}
1435 +
1436 +
1437 +static void tcindex_destroy(struct tcf_proto *tp)
1438 +{
1439 +       struct tcindex_data *p = PRIV(tp);
1440 +       struct tcf_walker walker;
1441 +
1442 +       DPRINTK("tcindex_destroy(tp %p),p %p\n",tp,p);
1443 +       walker.count = 0;
1444 +       walker.skip = 0;
1445 +       walker.fn = &tcindex_destroy_element;
1446 +       tcindex_walk(tp,&walker);
1447 +       if (p->perfect)
1448 +               kfree(p->perfect);
1449 +       if (p->h)
1450 +               kfree(p->h);
1451 +       kfree(p);
1452 +       tp->root = NULL;
1453 +       MOD_DEC_USE_COUNT;
1454 +}
1455 +
1456 +
1457 +static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
1458 +    struct sk_buff *skb, struct tcmsg *t)
1459 +{
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;
1464 +
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);
1470 +       if (!fh) {
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);
1477 +       } else {
1478 +               if (p->perfect) {
1479 +                       t->tcm_handle = r-p->perfect;
1480 +               } else {
1481 +                       struct tcindex_filter *f;
1482 +                       int i;
1483 +
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;
1487 +                                    f = f->next) {
1488 +                                       if (&f->result == r)
1489 +                                               t->tcm_handle = f->key;
1490 +                               }
1491 +                       }
1492 +               }
1493 +               DPRINTK("handle = %d\n",t->tcm_handle);
1494 +               if (r->res.class)
1495 +                       RTA_PUT(skb, TCA_TCINDEX_CLASSID, 4, &r->res.classid);
1496 +#ifdef CONFIG_NET_CLS_POLICE
1497 +               if (r->police) {
1498 +                       struct rtattr *p_rta = (struct rtattr *) skb->tail;
1499 +
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;
1504 +               }
1505 +#endif
1506 +       }
1507 +       rta->rta_len = skb->tail-b;
1508 +       return skb->len;
1509 +
1510 +rtattr_failure:
1511 +       skb_trim(skb, b - skb->data);
1512 +       return -1;
1513 +}
1514 +
1515 +struct tcf_proto_ops cls_tcindex_ops = {
1516 +       NULL,
1517 +       "tcindex",
1518 +       tcindex_classify,
1519 +       tcindex_init,
1520 +       tcindex_destroy,
1521 +
1522 +       tcindex_get,
1523 +       tcindex_put,
1524 +       tcindex_change,
1525 +       tcindex_delete,
1526 +       tcindex_walk,
1527 +       tcindex_dump
1528 +};
1529 +
1530 +
1531 +#ifdef MODULE
1532 +int init_module(void)
1533 +{
1534 +       return register_tcf_proto_ops(&cls_tcindex_ops);
1535 +}
1536 +
1537 +void cleanup_module(void) 
1538 +{
1539 +       unregister_tcf_proto_ops(&cls_tcindex_ops);
1540 +}
1541 +#endif
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
1546 @@ -52,8 +52,6 @@
1547  #include <net/sock.h>
1548  #include <net/pkt_sched.h>
1549  
1550 -#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
1551 -
1552  
1553  struct tc_u_knode
1554  {
1555 @@ -164,7 +162,7 @@
1556                 if (!(n->sel.flags&(TC_U32_VAROFFSET|TC_U32_OFFSET|TC_U32_EAT)))
1557                         goto next_ht;
1558  
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;
1564 @@ -307,7 +305,7 @@
1565  {
1566         unsigned long cl;
1567  
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);
1573 @@ -326,8 +324,9 @@
1574         if (ht) {
1575                 for (kp = &ht->ht[TC_U32_HASH(key->handle)]; *kp; kp = &(*kp)->next) {
1576                         if (*kp == key) {
1577 +                               tcf_tree_lock(tp);
1578                                 *kp = key->next;
1579 -                               synchronize_bh();
1580 +                               tcf_tree_unlock(tp);
1581  
1582                                 u32_destroy_key(tp, key);
1583                                 return 0;
1584 @@ -346,7 +345,6 @@
1585         for (h=0; h<=ht->divisor; h++) {
1586                 while ((n = ht->ht[h]) != NULL) {
1587                         ht->ht[h] = n->next;
1588 -                       synchronize_bh();
1589  
1590                         u32_destroy_key(tp, n);
1591                 }
1592 @@ -465,8 +463,9 @@
1593                         ht_down->refcnt++;
1594                 }
1595  
1596 +               sch_tree_lock(q);
1597                 ht_down = xchg(&n->ht_down, ht_down);
1598 -               synchronize_bh();
1599 +               sch_tree_unlock(q);
1600  
1601                 if (ht_down)
1602                         ht_down->refcnt--;
1603 @@ -475,7 +474,9 @@
1604                 unsigned long cl;
1605  
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));
1608 +               sch_tree_lock(q);
1609 +               cl = __cls_set_class(&n->res.class, q->ops->cl_ops->bind_tcf(q, base, n->res.classid));
1610 +               sch_tree_unlock(q);
1611                 if (cl)
1612                         q->ops->cl_ops->unbind_tcf(q, cl);
1613         }
1614 @@ -483,8 +484,9 @@
1615         if (tb[TCA_U32_POLICE-1]) {
1616                 struct tcf_police *police = tcf_police_locate(tb[TCA_U32_POLICE-1], est);
1617  
1618 +               sch_tree_lock(q);
1619                 police = xchg(&n->police, police);
1620 -               synchronize_bh();
1621 +               sch_tree_unlock(q);
1622  
1623                 tcf_police_release(police);
1624         }
1625 @@ -633,7 +635,6 @@
1626         }
1627  }
1628  
1629 -#ifdef CONFIG_RTNETLINK
1630  static int u32_dump(struct tcf_proto *tp, unsigned long fh,
1631                      struct sk_buff *skb, struct tcmsg *t)
1632  {
1633 @@ -682,7 +683,8 @@
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;
1640         }
1641  #endif
1642         return skb->len;
1643 @@ -691,7 +693,6 @@
1644         skb_trim(skb, b - skb->data);
1645         return -1;
1646  }
1647 -#endif
1648  
1649  struct tcf_proto_ops cls_u32_ops = {
1650         NULL,
1651 @@ -705,11 +706,7 @@
1652         u32_change,
1653         u32_delete,
1654         u32_walk,
1655 -#ifdef CONFIG_RTNETLINK
1656         u32_dump
1657 -#else
1658 -       NULL
1659 -#endif
1660  };
1661  
1662  #ifdef MODULE
1663 @@ -723,3 +720,4 @@
1664         unregister_tcf_proto_ops(&cls_u32_ops);
1665  }
1666  #endif
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
1671 @@ -31,8 +31,6 @@
1672  #include <net/sock.h>
1673  #include <net/pkt_sched.h>
1674  
1675 -#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
1676 -
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])
1679  
1680 @@ -74,6 +72,7 @@
1681         for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) {
1682                 if (*p1p == p) {
1683                         *p1p = p->next;
1684 +                       synchronize_bh();
1685  #ifdef CONFIG_NET_ESTIMATOR
1686                         qdisc_kill_estimator(&p->stats);
1687  #endif
1688 @@ -145,7 +144,9 @@
1689  #endif
1690         h = tcf_police_hash(p->index);
1691         p->next = tcf_police_ht[h];
1692 +       wmb();
1693         tcf_police_ht[h] = p;
1694 +       synchronize_bh();
1695         return p;
1696  
1697  failure:
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
1701 @@ -11,7 +11,10 @@
1702   * Fixes:
1703   *
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
1706 + *
1707   * Eduardo J. Blanco <ejbs@netlabs.com.uy> :990222: kmod support
1708 + * Jamal Hadi Salim <hadi@nortelnetworks.com>: 990501: ingress support
1709   */
1710  
1711  #include <linux/config.h>
1712 @@ -31,6 +34,7 @@
1713  #include <linux/init.h>
1714  #include <linux/proc_fs.h>
1715  #include <linux/kmod.h>
1716 +#include <linux/firewall.h>
1717  
1718  #include <net/sock.h>
1719  #include <net/pkt_sched.h>
1720 @@ -40,8 +44,6 @@
1721  #include <asm/system.h>
1722  #include <asm/bitops.h>
1723  
1724 -#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
1725 -
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);
1729 @@ -95,9 +97,15 @@
1730  
1731     ---enqueue
1732  
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.
1745  
1746     Auxiliary routines:
1747  
1748 @@ -139,9 +147,11 @@
1749  {
1750         struct Qdisc_ops *q, **qp;
1751  
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) {
1756                         return -EEXIST;
1757 +               }
1758 +       }
1759  
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)
1764  {
1765         struct Qdisc_ops *q, **qp;
1766 +       int err = -ENOENT;
1767 +
1768         for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next)
1769                 if (q == qops)
1770                         break;
1771 -       if (!q)
1772 -               return -ENOENT;
1773 -       *qp = q->next;
1774 -       q->next = NULL;
1775 -       return 0;
1776 +       if (q) {
1777 +               *qp = q->next;
1778 +               q->next = NULL;
1779 +               err = 0;
1780 +       }
1781 +       return err;
1782  }
1783  
1784  /* We know handle. Find qdisc among all qdisc's attached to device
1785 @@ -192,6 +205,7 @@
1786         if (cops == NULL)
1787                 return NULL;
1788         cl = cops->get(p, classid);
1789 +
1790         if (cl == 0)
1791                 return NULL;
1792         leaf = cops->leaf(p, cl);
1793 @@ -203,15 +217,15 @@
1794  
1795  struct Qdisc_ops *qdisc_lookup_ops(struct rtattr *kind)
1796  {
1797 -       struct Qdisc_ops *q;
1798 +       struct Qdisc_ops *q = NULL;
1799  
1800         if (kind) {
1801                 for (q = qdisc_base; q; q = q->next) {
1802                         if (rtattr_strcmp(kind, q->id) == 0)
1803 -                               return q;
1804 +                               break;
1805                 }
1806         }
1807 -       return NULL;
1808 +       return q;
1809  }
1810  
1811  static struct qdisc_rate_table *qdisc_rtab_list;
1812 @@ -285,17 +299,32 @@
1813                 dev_deactivate(dev);
1814  
1815         start_bh_atomic();
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) {
1821 +                       /* delete */
1822 +                       qdisc_reset(oqdisc);
1823 +                       dev->qdisc_ingress = NULL;
1824 +               } else {  /* new */
1825 +                       dev->qdisc_ingress = qdisc;
1826 +               }
1827 +
1828 +       } else {
1829 +
1830 +               oqdisc = dev->qdisc_sleeping;
1831 +
1832 +               /* Prune old scheduler */
1833 +               if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
1834 +                       qdisc_reset(oqdisc);
1835 +
1836 +               /* ... and graft new one */
1837 +               if (qdisc == NULL)
1838 +                       qdisc = &noop_qdisc;
1839 +               dev->qdisc_sleeping = qdisc;
1840 +               dev->qdisc = &noop_qdisc;
1841 +       }
1842  
1843 -       /* Prune old scheduler */
1844 -       if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
1845 -               qdisc_reset(oqdisc);
1846 -
1847 -       /* ... and graft new one */
1848 -       if (qdisc == NULL)
1849 -               qdisc = &noop_qdisc;
1850 -       dev->qdisc_sleeping = qdisc;
1851 -       dev->qdisc = &noop_qdisc;
1852         end_bh_atomic();
1853  
1854         if (dev->flags & IFF_UP)
1855 @@ -315,9 +344,15 @@
1856                 struct Qdisc *new, struct Qdisc **old)
1857  {
1858         int err = 0;
1859 +       struct Qdisc *q = *old;
1860 +
1861  
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);
1867 +               } else {
1868 +                       *old = dev_graft_qdisc(dev, new);
1869 +               }
1870         } else {
1871                 struct Qdisc_class_ops *cops = parent->ops->cl_ops;
1872  
1873 @@ -334,8 +369,6 @@
1874         return err;
1875  }
1876  
1877 -#ifdef CONFIG_RTNETLINK
1878 -
1879  /*
1880     Allocate and initialize new qdisc.
1881  
1882 @@ -376,7 +409,7 @@
1883                 goto err_out;
1884  
1885         /* Grrr... Resolve race condition with module unload */
1886 -       
1887 +
1888         err = -EINVAL;
1889         if (ops != qdisc_lookup_ops(kind))
1890                 goto err_out;
1891 @@ -384,6 +417,10 @@
1892         memset(sch, 0, size);
1893  
1894         skb_queue_head_init(&sch->q);
1895 +
1896 +       if (handle == TC_H_INGRESS)
1897 +               sch->flags |= TCQ_F_INGRES;
1898 +
1899         sch->ops = ops;
1900         sch->enqueue = ops->enqueue;
1901         sch->dequeue = ops->dequeue;
1902 @@ -395,7 +432,11 @@
1903                 if (handle == 0)
1904                         goto err_out;
1905         }
1906 -       sch->handle = handle;
1907 +
1908 +       if (handle == TC_H_INGRESS)
1909 +                sch->handle =TC_H_MAKE(TC_H_INGRESS, 0);
1910 +        else
1911 +                sch->handle = handle;
1912  
1913         if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
1914                 sch->next = dev->qdisc_list;
1915 @@ -493,12 +534,16 @@
1916  
1917         if (clid) {
1918                 if (clid != TC_H_ROOT) {
1919 -                       if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
1920 -                               return -ENOENT;
1921 -                       q = qdisc_leaf(p, clid);
1922 -               } else
1923 +                       if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {
1924 +                               if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
1925 +                                       return -ENOENT;
1926 +                               q = qdisc_leaf(p, clid);
1927 +                       } else { /* ingress */
1928 +                               q = dev->qdisc_ingress;
1929 +                        }
1930 +               } else {
1931                         q = dev->qdisc_sleeping;
1932 -
1933 +               }
1934                 if (!q)
1935                         return -ENOENT;
1936  
1937 @@ -521,7 +566,9 @@
1938                         return err;
1939                 if (q) {
1940                         qdisc_notify(skb, n, clid, q, NULL);
1941 +                       sch_dev_queue_lock(dev);
1942                         qdisc_destroy(q);
1943 +                       sch_dev_queue_unlock(dev);
1944                 }
1945         } else {
1946                 qdisc_notify(skb, n, clid, NULL, q);
1947 @@ -548,9 +595,13 @@
1948  
1949         if (clid) {
1950                 if (clid != TC_H_ROOT) {
1951 -                       if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
1952 -                               return -ENOENT;
1953 -                       q = qdisc_leaf(p, clid);
1954 +                       if (clid != TC_H_INGRESS) {
1955 +                               if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
1956 +                                       return -ENOENT;
1957 +                               q = qdisc_leaf(p, clid);
1958 +                       } else { /*ingress */
1959 +                               q = dev->qdisc_ingress;
1960 +                       }
1961                 } else {
1962                         q = dev->qdisc_sleeping;
1963                 }
1964 @@ -628,7 +679,10 @@
1965  create_n_graft:
1966         if (!(n->nlmsg_flags&NLM_F_CREATE))
1967                 return -ENOENT;
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);
1971 +        else
1972 +               q = qdisc_create(dev, tcm->tcm_handle, tca, &err);
1973         if (q == NULL)
1974                 return err;
1975  
1976 @@ -637,17 +691,36 @@
1977                 struct Qdisc *old_q = NULL;
1978                 err = qdisc_graft(dev, p, clid, q, &old_q);
1979                 if (err) {
1980 -                       if (q)
1981 +                       if (q) {
1982 +                               sch_dev_queue_lock(dev);
1983                                 qdisc_destroy(q);
1984 +                               sch_dev_queue_unlock(dev);
1985 +                       }
1986                         return err;
1987                 }
1988                 qdisc_notify(skb, n, clid, old_q, q);
1989 -               if (old_q)
1990 +               if (old_q) {
1991 +                       sch_dev_queue_lock(dev);
1992                         qdisc_destroy(old_q);
1993 +                       sch_dev_queue_unlock(dev);
1994 +               }
1995         }
1996         return 0;
1997  }
1998  
1999 +int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st)
2000 +{
2001 +       start_bh_atomic();
2002 +       RTA_PUT(skb, TCA_STATS, sizeof(*st), st);
2003 +       end_bh_atomic();
2004 +       return 0;
2005 +
2006 +rtattr_failure:
2007 +       end_bh_atomic();
2008 +       return -1;
2009 +}
2010 +
2011 +
2012  static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
2013                          u32 pid, u32 seq, unsigned flags, int event)
2014  {
2015 @@ -667,7 +740,8 @@
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;
2023         return skb->len;
2024  
2025 @@ -723,8 +797,9 @@
2026                         if (q_idx < s_q_idx)
2027                                 continue;
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) {
2031                                 goto done;
2032 +                       }
2033                 }
2034         }
2035  
2036 @@ -956,6 +1031,13 @@
2037  
2038         return skb->len;
2039  }
2040 +
2041 +#if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE)
2042 +int call_in_ingress(struct sk_buff *skb)
2043 +{
2044 +       if (!skb->dev->qdisc_ingress) return FW_ACCEPT;
2045 +       return skb->dev->qdisc_ingress->enqueue(skb,skb->dev->qdisc_ingress);
2046 +}
2047  #endif
2048  
2049  int psched_us_per_tick = 1;
2050 @@ -967,8 +1049,9 @@
2051  {
2052         int len;
2053  
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,
2058 +                     1000000, HZ);
2059  
2060         len -= offset;
2061  
2062 @@ -1011,7 +1094,7 @@
2063  static void psched_tick(unsigned long);
2064  
2065  static struct timer_list psched_timer =
2066 -       { NULL, NULL, 0, 0L, psched_tick };
2067 +       { function: psched_tick };
2068  
2069  static void psched_tick(unsigned long dummy)
2070  {
2071 @@ -1022,7 +1105,7 @@
2072         psched_timer.expires = jiffies + 1*HZ;
2073  #else
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;
2079  #endif
2080 @@ -1072,9 +1155,7 @@
2081  
2082  __initfunc(int pktsched_init(void))
2083  {
2084 -#ifdef CONFIG_RTNETLINK
2085         struct rtnetlink_link *link_p;
2086 -#endif
2087  #ifdef CONFIG_PROC_FS
2088         struct proc_dir_entry *ent;
2089  #endif
2090 @@ -1090,7 +1171,6 @@
2091  #endif
2092  #endif
2093  
2094 -#ifdef CONFIG_RTNETLINK
2095         link_p = rtnetlink_links[PF_UNSPEC];
2096  
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;
2101         }
2102 -#endif
2103  
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);       \
2108         }
2109  
2110         INIT_QDISC(pfifo);
2111 @@ -1134,6 +1213,9 @@
2112  #endif
2113  #ifdef CONFIG_NET_SCH_GRED
2114         INIT_QDISC(gred);
2115 +#endif
2116 +#ifdef CONFIG_NET_SCH_INGRESS
2117 +       INIT_QDISC(ingress);
2118  #endif
2119  #ifdef CONFIG_NET_SCH_DSMARK
2120         INIT_QDISC(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
2124 @@ -192,8 +192,6 @@
2125  
2126  #define L2T(cl,len)    ((cl)->R_tab->data[(len)>>(cl)->R_tab->rate.cell_log])
2127  
2128 -#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
2129 -
2130  
2131  static __inline__ unsigned cbq_hash(u32 h)
2132  {
2133 @@ -284,6 +282,7 @@
2134                 case TC_POLICE_SHOT:
2135                         return NULL;
2136                 default:
2137 +                       break;
2138                 }
2139  #endif
2140                 if (cl->level == 0)
2141 @@ -397,6 +396,7 @@
2142         struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
2143         struct cbq_class *cl = cbq_classify(skb, sch);
2144         int len = skb->len;
2145 +       int ret = NET_XMIT_POLICED;
2146  
2147  #ifdef CONFIG_NET_CLS_POLICE
2148         q->rx_class = cl;
2149 @@ -405,14 +405,14 @@
2150  #ifdef CONFIG_NET_CLS_POLICE
2151                 cl->q->__parent = sch;
2152  #endif
2153 -               if (cl->q->enqueue(skb, cl->q) == 1) {
2154 +               if ((ret = cl->q->enqueue(skb, cl->q)) == 0) {
2155                         sch->q.qlen++;
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);
2161 -                       return 1;
2162 +                       return 0;
2163                 }
2164         }
2165  
2166 @@ -423,7 +423,7 @@
2167                 cbq_mark_toplevel(q, cl);
2168                 cl->stats.drops++;
2169         }
2170 -       return 0;
2171 +       return ret;
2172  }
2173  
2174  static int
2175 @@ -431,11 +431,12 @@
2176  {
2177         struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
2178         struct cbq_class *cl;
2179 +       int ret;
2180  
2181         if ((cl = q->tx_class) == NULL) {
2182                 kfree_skb(skb);
2183                 sch->stats.drops++;
2184 -               return 0;
2185 +               return NET_XMIT_CN;
2186         }
2187         q->tx_class = NULL;
2188  
2189 @@ -445,15 +446,15 @@
2190         q->rx_class = cl;
2191         cl->q->__parent = sch;
2192  #endif
2193 -       if (cl->q->ops->requeue(skb, cl->q) == 1) {
2194 +       if ((ret = cl->q->ops->requeue(skb, cl->q)) == 0) {
2195                 sch->q.qlen++;
2196                 if (!cl->next_alive)
2197                         cbq_activate_class(cl);
2198 -               return 1;
2199 +               return 0;
2200         }
2201         sch->stats.drops++;
2202         cl->stats.drops++;
2203 -       return 0;
2204 +       return ret;
2205  }
2206  
2207  /* Overlimit actions */
2208 @@ -597,8 +598,9 @@
2209  static void cbq_watchdog(unsigned long arg)
2210  {
2211         struct Qdisc *sch = (struct Qdisc*)arg;
2212 +
2213         sch->flags &= ~TCQ_F_THROTTLED;
2214 -       qdisc_wakeup(sch->dev);
2215 +       netif_schedule(sch->dev);
2216  }
2217  
2218  static unsigned long cbq_undelay_prio(struct cbq_sched_data *q, int prio)
2219 @@ -666,7 +668,7 @@
2220         }
2221  
2222         sch->flags &= ~TCQ_F_THROTTLED;
2223 -       qdisc_wakeup(sch->dev);
2224 +       netif_schedule(sch->dev);
2225  }
2226  
2227  
2228 @@ -688,7 +690,7 @@
2229                 q->rx_class = cl;
2230                 cl->q->__parent = sch;
2231  
2232 -               if (cl->q->enqueue(skb, cl->q) == 1) {
2233 +               if (cl->q->enqueue(skb, cl->q) == 0) {
2234                         sch->q.qlen++;
2235                         sch->stats.packets++;
2236                         sch->stats.bytes+=len;
2237 @@ -877,7 +879,7 @@
2238  
2239                 /* Start round */
2240                 do {
2241 -                       struct cbq_class *borrow = NULL;
2242 +                       struct cbq_class *borrow = cl;
2243  
2244                         if (cl->q->q.qlen &&
2245                             (borrow = cbq_under_limit(cl)) == NULL)
2246 @@ -1052,16 +1054,11 @@
2247  
2248         if (sch->q.qlen) {
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);
2254                         if (delay <= 0)
2255                                 delay = 1;
2256 -                       if (delay > 10*HZ) {
2257 -                               if (net_ratelimit())
2258 -                                       printk(KERN_DEBUG "CBQ delay %ld > 10sec\n", delay);
2259 -                               delay = 10*HZ;
2260 -                       }
2261                         q->wd_timer.expires = jiffies + delay;
2262                         add_timer(&q->wd_timer);
2263                         sch->flags |= TCQ_F_THROTTLED;
2264 @@ -1248,8 +1245,10 @@
2265  
2266                 cl = cl_head;
2267                 do {
2268 -                       if (cl->q->ops->drop && cl->q->ops->drop(cl->q))
2269 +                       if (cl->q->ops->drop && cl->q->ops->drop(cl->q)) {
2270 +                               sch->q.qlen--;
2271                                 return 1;
2272 +                       }
2273                 } while ((cl = cl->next_alive) != cl_head);
2274         }
2275         return 0;
2276 @@ -1457,8 +1456,6 @@
2277         return 0;
2278  }
2279  
2280 -#ifdef CONFIG_RTNETLINK
2281 -
2282  static __inline__ int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl)
2283  {
2284         unsigned char    *b = skb->tail;
2285 @@ -1580,6 +1577,16 @@
2286         return 0;
2287  }
2288  
2289 +int cbq_copy_xstats(struct sk_buff *skb, struct tc_cbq_xstats *st)
2290 +{
2291 +       RTA_PUT(skb, TCA_XSTATS, sizeof(*st), st);
2292 +       return 0;
2293 +
2294 +rtattr_failure:
2295 +       return -1;
2296 +}
2297 +
2298 +
2299  static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb)
2300  {
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;
2312 +       }
2313 +       sch_dev_queue_unlock(sch->dev);
2314         return skb->len;
2315  
2316  rtattr_failure:
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;
2334 +       }
2335 +       sch_dev_queue_unlock(sch->dev);
2336  
2337         return skb->len;
2338  
2339 @@ -1636,8 +1655,6 @@
2340         return -1;
2341  }
2342  
2343 -#endif
2344 -
2345  static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
2346                      struct Qdisc **old)
2347  {
2348 @@ -1653,8 +1670,11 @@
2349                                 new->reshape_fail = cbq_reshape_fail;
2350  #endif
2351                 }
2352 -               if ((*old = xchg(&cl->q, new)) != NULL)
2353 -                       qdisc_reset(*old);
2354 +               sch_tree_lock(sch);
2355 +               *old = cl->q;
2356 +               cl->q = new;
2357 +               qdisc_reset(*old);
2358 +               sch_tree_unlock(sch);
2359  
2360                 return 0;
2361         }
2362 @@ -1718,9 +1738,13 @@
2363         }
2364  
2365         for (h = 0; h < 16; h++) {
2366 -               for (cl = q->classes[h]; cl; cl = cl->next)
2367 +               struct cbq_class *next;
2368 +
2369 +               for (cl = q->classes[h]; cl; cl = next) {
2370 +                       next = cl->next;
2371                         if (cl != &q->link)
2372                                 cbq_destroy_class(cl);
2373 +               }
2374         }
2375  
2376         qdisc_put_rtab(q->link.R_tab);
2377 @@ -1729,19 +1753,20 @@
2378  
2379  static void cbq_put(struct Qdisc *sch, unsigned long arg)
2380  {
2381 -       struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
2382         struct cbq_class *cl = (struct cbq_class*)arg;
2383  
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;
2388 +
2389 +               sch_dev_queue_lock(sch->dev);
2390                 if (q->rx_class == cl)
2391                         q->rx_class = NULL;
2392 +               sch_dev_queue_unlock(sch->dev);
2393  #endif
2394 +
2395                 cbq_destroy_class(cl);
2396         }
2397 -       end_bh_atomic();
2398 -       return;
2399  }
2400  
2401  static int
2402 @@ -1802,7 +1827,7 @@
2403                 }
2404  
2405                 /* Change class parameters */
2406 -               start_bh_atomic();
2407 +               sch_tree_lock(sch);
2408  
2409                 if (cl->next_alive != NULL)
2410                         cbq_deactivate_class(cl);
2411 @@ -1834,7 +1859,7 @@
2412                 if (cl->q->q.qlen)
2413                         cbq_activate_class(cl);
2414  
2415 -               end_bh_atomic();
2416 +               sch_tree_unlock(sch);
2417  
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;
2423  
2424 -       start_bh_atomic();
2425 +       sch_tree_lock(sch);
2426         cbq_link_class(cl);
2427         cl->borrow = cl->tparent;
2428         if (cl->tparent != &q->link)
2429 @@ -1925,7 +1950,7 @@
2430  #endif
2431         if (tb[TCA_CBQ_FOPT-1])
2432                 cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1]));
2433 -       end_bh_atomic();
2434 +       sch_tree_unlock(sch);
2435  
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)
2440                 return -EBUSY;
2441  
2442 -       start_bh_atomic();
2443 +       sch_tree_lock(sch);
2444  
2445         if (cl->next_alive)
2446                 cbq_deactivate_class(cl);
2447 @@ -1970,12 +1995,11 @@
2448         cbq_sync_defmap(cl);
2449  
2450         cbq_rmprio(q, cl);
2451 +       sch_tree_unlock(sch);
2452  
2453         if (--cl->refcnt == 0)
2454                 cbq_destroy_class(cl);
2455  
2456 -       end_bh_atomic();
2457 -
2458         return 0;
2459  }
2460  
2461 @@ -2052,9 +2076,7 @@
2462         cbq_bind_filter,
2463         cbq_unbind_filter,
2464  
2465 -#ifdef CONFIG_RTNETLINK
2466         cbq_dump_class,
2467 -#endif
2468  };
2469  
2470  struct Qdisc_ops cbq_qdisc_ops =
2471 @@ -2074,9 +2096,7 @@
2472         cbq_destroy,
2473         NULL /* cbq_change */,
2474  
2475 -#ifdef CONFIG_RTNETLINK
2476         cbq_dump,
2477 -#endif
2478  };
2479  
2480  #ifdef MODULE
2481 @@ -2090,3 +2110,4 @@
2482         unregister_qdisc(&cbq_qdisc_ops);
2483  }
2484  #endif
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
2489 @@ -477,7 +477,7 @@
2490         if (this->q.qlen >= this->limit || this->L_tab == NULL) {
2491                 sch->stats.drops++;
2492                 kfree_skb(skb);
2493 -               return 0;
2494 +               return NET_XMIT_DROP;
2495         }
2496  
2497         R = csz_update(sch);
2498 @@ -505,7 +505,7 @@
2499         sch->q.qlen++;
2500         sch->stats.bytes += skb->len;
2501         sch->stats.packets++;
2502 -       return 1;
2503 +       return 0;
2504  }
2505  
2506  static __inline__ struct sk_buff *
2507 @@ -795,7 +795,6 @@
2508         return 0;
2509  }
2510  
2511 -#ifdef CONFIG_RTNETLINK
2512  static int csz_dump(struct Qdisc *sch, struct sk_buff *skb)
2513  {
2514         struct csz_sched_data *q = (struct csz_sched_data *)sch->data;
2515 @@ -817,8 +816,6 @@
2516         skb_trim(skb, b - skb->data);
2517         return -1;
2518  }
2519 -#endif
2520 -
2521  
2522  static int csz_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,
2523                      struct Qdisc **old)
2524 @@ -885,7 +882,7 @@
2525  
2526                 a = &q->flow[cl];
2527  
2528 -               start_bh_atomic();      
2529 +               sch_dev_queue_lock(sch->dev);
2530  #if 0
2531                 a->rate_log = copt->rate_log;
2532  #endif
2533 @@ -899,7 +896,7 @@
2534                 if (tb[TCA_CSZ_RTAB-1])
2535                         memcpy(a->L_tab, RTA_DATA(tb[TCA_CSZ_RTAB-1]), 1024);
2536  
2537 -               end_bh_atomic();
2538 +               sch_dev_queue_unlock(sch->dev);
2539                 return 0;
2540         }
2541         /* NI */
2542 @@ -920,19 +917,18 @@
2543  
2544         a = &q->flow[cl];
2545  
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));
2554 -       end_bh_atomic();
2555 +       sch_dev_queue_unlock(sch->dev);
2556  
2557         return 0;
2558  }
2559  
2560 -#ifdef CONFIG_RTNETLINK
2561  static int csz_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, struct tcmsg *tcm)
2562  {
2563         struct csz_sched_data *q = (struct csz_sched_data *)sch->data;
2564 @@ -978,7 +974,6 @@
2565         skb_trim(skb, b - skb->data);
2566         return -1;
2567  }
2568 -#endif
2569  
2570  static void csz_walk(struct Qdisc *sch, struct qdisc_walker *arg)
2571  {
2572 @@ -1030,9 +1025,7 @@
2573         csz_bind,
2574         csz_put,
2575  
2576 -#ifdef CONFIG_RTNETLINK
2577         csz_dump_class,
2578 -#endif
2579  };
2580  
2581  struct Qdisc_ops csz_qdisc_ops =
2582 @@ -1052,9 +1045,7 @@
2583         csz_destroy,
2584         NULL /* csz_change */,
2585  
2586 -#ifdef CONFIG_RTNETLINK
2587         csz_dump,
2588 -#endif
2589  };
2590  
2591  
2592 @@ -1069,3 +1060,4 @@
2593         unregister_qdisc(&csz_qdisc_ops);
2594  }
2595  #endif
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
2600 @@ -0,0 +1,484 @@
2601 +/* net/sched/sch_dsmark.c - Differentiated Services field marker */
2602 +
2603 +/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
2604 +
2605 +
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>
2617 +
2618 +
2619 +#if 1 /* control */
2620 +#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
2621 +#else
2622 +#define DPRINTK(format,args...)
2623 +#endif
2624 +
2625 +#if 0 /* data */
2626 +#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
2627 +#else
2628 +#define D2PRINTK(format,args...)
2629 +#endif
2630 +
2631 +
2632 +#define PRIV(sch) ((struct dsmark_qdisc_data *) (sch)->data)
2633 +
2634 +
2635 +/*
2636 + * classid     class           marking
2637 + * -------     -----           -------
2638 + *   n/a         0             n/a
2639 + *   x:0         1             use entry [0]
2640 + *   ...        ...            ...
2641 + *   x:y y>0    y+1            use entry [y]
2642 + *   ...        ...            ...
2643 + * x:indices-1 indices         use entry [indices-1]
2644 + *   ...        ...            ...
2645 + *   x:y        y+1            use entry [y & (indices-1)]
2646 + *   ...        ...            ...
2647 + * 0xffff      0x10000         use entry [indices-1]
2648 + */
2649 +
2650 +
2651 +#define NO_DEFAULT_INDEX       (1 << 16)
2652 +
2653 +struct dsmark_qdisc_data {
2654 +       struct Qdisc            *q;
2655 +       struct tcf_proto        *filter_list;
2656 +       __u8                    *mask;  /* "owns" the array */
2657 +       __u8                    *value;
2658 +       __u16                   indices;
2659 +       __u32                   default_index;  /* index range is 0...0xffff */
2660 +       int                     set_tc_index;
2661 +};
2662 +
2663 +
2664 +/* ------------------------- Class/flow operations ------------------------- */
2665 +
2666 +
2667 +static int dsmark_graft(struct Qdisc *sch,unsigned long arg,
2668 +    struct Qdisc *new,struct Qdisc **old)
2669 +{
2670 +       struct dsmark_qdisc_data *p = PRIV(sch);
2671 +
2672 +       DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",sch,p,new,
2673 +           old);
2674 +       if (!new)
2675 +               new = &noop_qdisc;
2676 +       sch_tree_lock(sch);
2677 +       *old = xchg(&p->q,new);
2678 +       if (*old)
2679 +               qdisc_reset(*old);
2680 +       sch_tree_unlock(sch); /* @@@ move up ? */
2681 +        return 0;
2682 +}
2683 +
2684 +
2685 +static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
2686 +{
2687 +       struct dsmark_qdisc_data *p = PRIV(sch);
2688 +
2689 +       return p->q;
2690 +}
2691 +
2692 +
2693 +static unsigned long dsmark_get(struct Qdisc *sch,u32 classid)
2694 +{
2695 +       struct dsmark_qdisc_data *p __attribute__((unused)) = PRIV(sch);
2696 +
2697 +       DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
2698 +       return TC_H_MIN(classid)+1;
2699 +}
2700 +
2701 +
2702 +static unsigned long dsmark_bind_filter(struct Qdisc *sch,
2703 +    unsigned long parent, u32 classid)
2704 +{
2705 +       return dsmark_get(sch,classid);
2706 +}
2707 +
2708 +
2709 +static void dsmark_put(struct Qdisc *sch, unsigned long cl)
2710 +{
2711 +}
2712 +
2713 +
2714 +static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
2715 +    struct rtattr **tca, unsigned long *arg)
2716 +{
2717 +       struct dsmark_qdisc_data *p = PRIV(sch);
2718 +       struct rtattr *opt = tca[TCA_OPTIONS-1];
2719 +       struct rtattr *tb[TCA_DSMARK_MAX];
2720 +
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)
2724 +               return -ENOENT;
2725 +       if (!opt || rtattr_parse(tb, TCA_DSMARK_MAX, RTA_DATA(opt),
2726 +                                RTA_PAYLOAD(opt)))
2727 +               return -EINVAL;
2728 +       if (tb[TCA_DSMARK_MASK-1]) {
2729 +               if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK-1]))
2730 +                       return -EINVAL;
2731 +               p->mask[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_MASK-1]);
2732 +       }
2733 +       if (tb[TCA_DSMARK_VALUE-1]) {
2734 +               if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE-1]))
2735 +                       return -EINVAL;
2736 +               p->value[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_VALUE-1]);
2737 +       }
2738 +       return 0;
2739 +}
2740 +
2741 +
2742 +static int dsmark_delete(struct Qdisc *sch,unsigned long arg)
2743 +{
2744 +       struct dsmark_qdisc_data *p = PRIV(sch);
2745 +
2746 +       if (!arg || arg > p->indices)
2747 +               return -EINVAL;
2748 +       p->mask[arg-1] = 0xff;
2749 +       p->value[arg-1] = 0;
2750 +       return 0;
2751 +}
2752 +
2753 +
2754 +static void dsmark_walk(struct Qdisc *sch,struct qdisc_walker *walker)
2755 +{
2756 +       struct dsmark_qdisc_data *p = PRIV(sch);
2757 +       int i;
2758 +
2759 +       DPRINTK("dsmark_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker);
2760 +       if (walker->stop)
2761 +               return;
2762 +       for (i = 0; i < p->indices; i++) {
2763 +               if (p->mask[i] == 0xff && !p->value[i])
2764 +                       continue;
2765 +               if (walker->count >= walker->skip) {
2766 +                       if (walker->fn(sch, i+1, walker) < 0) {
2767 +                               walker->stop = 1;
2768 +                               break;
2769 +                       }
2770 +               }
2771 +                walker->count++;
2772 +        }
2773 +}
2774 +
2775 +
2776 +static struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch,unsigned long cl)
2777 +{
2778 +       struct dsmark_qdisc_data *p = PRIV(sch);
2779 +
2780 +       return &p->filter_list;
2781 +}
2782 +
2783 +
2784 +/* --------------------------- Qdisc operations ---------------------------- */
2785 +
2786 +
2787 +static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
2788 +{
2789 +       struct dsmark_qdisc_data *p = PRIV(sch);
2790 +       struct tcf_result res;
2791 +       int result;
2792 +       int ret = NET_XMIT_POLICED;
2793 +
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);
2799 +                               break;
2800 +                       case __constant_htons(ETH_P_IPV6):
2801 +                               skb->tc_index = ipv6_get_dsfield(skb->nh.ipv6h);
2802 +                               break;
2803 +                       default:
2804 +                               skb->tc_index = 0;
2805 +                               break;
2806 +               };
2807 +       }
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);
2811 +       } else {
2812 +               result = tc_classify(skb,p->filter_list,&res);
2813 +               D2PRINTK("result %d class 0x%04x\n",result,res.classid);
2814 +               switch (result) {
2815 +#ifdef CONFIG_NET_CLS_POLICE
2816 +                       case TC_POLICE_SHOT:
2817 +                               kfree_skb(skb);
2818 +                               break;
2819 +#if 0
2820 +                       case TC_POLICE_RECLASSIFY:
2821 +                               /* FIXME: what to do here ??? */
2822 +#endif
2823 +#endif
2824 +                       case TC_POLICE_OK:
2825 +                               skb->tc_index = TC_H_MIN(res.classid);
2826 +                               break;
2827 +                       case TC_POLICE_UNSPEC:
2828 +                               /* fall through */
2829 +                       default:
2830 +                               if (p->default_index != NO_DEFAULT_INDEX)
2831 +                                       skb->tc_index = p->default_index;
2832 +                               break;
2833 +               };
2834 +       }
2835 +       if (
2836 +#ifdef CONFIG_NET_CLS_POLICE
2837 +           result == TC_POLICE_SHOT ||
2838 +#endif
2839 +
2840 +           ((ret = p->q->enqueue(skb,p->q)) != 0)) {
2841 +               sch->stats.drops++;
2842 +               return ret;
2843 +       }
2844 +       sch->stats.bytes += skb->len;
2845 +       sch->stats.packets++;
2846 +       sch->q.qlen++;
2847 +       return ret;
2848 +}
2849 +
2850 +
2851 +static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
2852 +{
2853 +       struct dsmark_qdisc_data *p = PRIV(sch);
2854 +       struct sk_buff *skb;
2855 +       int index;
2856 +
2857 +       D2PRINTK("dsmark_dequeue(sch %p,[qdisc %p])\n",sch,p);
2858 +       skb = p->q->ops->dequeue(p->q);
2859 +       if (!skb)
2860 +               return NULL;
2861 +       sch->q.qlen--;
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]);
2868 +                       break;
2869 +               case __constant_htons(ETH_P_IPV6):
2870 +                       ipv6_change_dsfield(skb->nh.ipv6h,
2871 +                           p->mask[index],p->value[index]);
2872 +                       break;
2873 +               default:
2874 +                       /*
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.
2878 +                        */
2879 +                       if (p->mask[index] != 0xff || p->value[index])
2880 +                               printk(KERN_WARNING "dsmark_dequeue: "
2881 +                                      "unsupported protocol %d\n",
2882 +                                      htons(skb->protocol));
2883 +                       break;
2884 +       };
2885 +       return skb;
2886 +}
2887 +
2888 +
2889 +static int dsmark_requeue(struct sk_buff *skb,struct Qdisc *sch)
2890 +{
2891 +       int ret;
2892 +       struct dsmark_qdisc_data *p = PRIV(sch);
2893 +
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) {
2896 +               sch->q.qlen++;
2897 +               return 0;
2898 +       }
2899 +       sch->stats.drops++;
2900 +       return ret;
2901 +}
2902 +
2903 +
2904 +static int dsmark_drop(struct Qdisc *sch)
2905 +{
2906 +       struct dsmark_qdisc_data *p = PRIV(sch);
2907 +
2908 +       DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
2909 +       if (!p->q->ops->drop)
2910 +               return 0;
2911 +       if (!p->q->ops->drop(p->q))
2912 +               return 0;
2913 +       sch->q.qlen--;
2914 +       return 1;
2915 +}
2916 +
2917 +
2918 +int dsmark_init(struct Qdisc *sch,struct rtattr *opt)
2919 +{
2920 +       struct dsmark_qdisc_data *p = PRIV(sch);
2921 +       struct rtattr *tb[TCA_DSMARK_MAX];
2922 +       __u16 tmp;
2923 +
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))
2928 +                return -EINVAL;
2929 +       memset(p,0,sizeof(*p));
2930 +       p->filter_list = NULL;
2931 +       p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
2932 +       if (!p->indices)
2933 +               return -EINVAL;
2934 +       for (tmp = p->indices; tmp != 1; tmp >>= 1) {
2935 +               if (tmp & 1)
2936 +                       return -EINVAL;
2937 +       }
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))
2941 +                       return -EINVAL;
2942 +               p->default_index =
2943 +                   *(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
2944 +       }
2945 +       p->set_tc_index = !!tb[TCA_DSMARK_SET_TC_INDEX-1];
2946 +       p->mask = kmalloc(p->indices*2,GFP_KERNEL);
2947 +       if (!p->mask)
2948 +               return -ENOMEM;
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;
2956 +       return 0;
2957 +}
2958 +
2959 +
2960 +static void dsmark_reset(struct Qdisc *sch)
2961 +{
2962 +       struct dsmark_qdisc_data *p = PRIV(sch);
2963 +
2964 +       DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
2965 +       qdisc_reset(p->q);
2966 +       sch->q.qlen = 0;
2967 +}
2968 +
2969 +
2970 +static void dsmark_destroy(struct Qdisc *sch)
2971 +{
2972 +       struct dsmark_qdisc_data *p = PRIV(sch);
2973 +       struct tcf_proto *tp;
2974 +
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);
2980 +       }
2981 +       qdisc_destroy(p->q);
2982 +       p->q = &noop_qdisc;
2983 +       kfree(p->mask);
2984 +       MOD_DEC_USE_COUNT;
2985 +}
2986 +
2987 +
2988 +static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
2989 +    struct sk_buff *skb, struct tcmsg *tcm)
2990 +{
2991 +       struct dsmark_qdisc_data *p = PRIV(sch);
2992 +       unsigned char *b = skb->tail;
2993 +       struct rtattr *rta;
2994 +
2995 +       DPRINTK("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n",sch,p,cl);
2996 +       if (!cl || cl > p->indices)
2997 +               return -EINVAL;
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;
3004 +       return skb->len;
3005 +
3006 +rtattr_failure:
3007 +       skb_trim(skb,b-skb->data);
3008 +       return -1;
3009 +}
3010 +
3011 +static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb)
3012 +{
3013 +       struct dsmark_qdisc_data *p = PRIV(sch);
3014 +       unsigned char *b = skb->tail;
3015 +       struct rtattr *rta;
3016 +
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;
3022 +
3023 +               RTA_PUT(skb,TCA_DSMARK_DEFAULT_INDEX, sizeof(__u16), &tmp);
3024 +       }
3025 +       if (p->set_tc_index)
3026 +               RTA_PUT(skb, TCA_DSMARK_SET_TC_INDEX, 0, NULL);
3027 +       rta->rta_len = skb->tail-b;
3028 +       return skb->len;
3029 +
3030 +rtattr_failure:
3031 +       skb_trim(skb,b-skb->data);
3032 +       return -1;
3033 +}
3034 +
3035 +static struct Qdisc_class_ops dsmark_class_ops =
3036 +{
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 */
3044 +
3045 +       dsmark_find_tcf,                /* tcf_chain */
3046 +       dsmark_bind_filter,             /* bind_tcf */
3047 +       dsmark_put,                     /* unbind_tcf */
3048 +
3049 +       dsmark_dump_class,              /* dump */
3050 +};
3051 +
3052 +struct Qdisc_ops dsmark_qdisc_ops =
3053 +{
3054 +       NULL,                           /* next */
3055 +       &dsmark_class_ops,              /* cl_ops */
3056 +       "dsmark",
3057 +       sizeof(struct dsmark_qdisc_data),
3058 +
3059 +       dsmark_enqueue,                 /* enqueue */
3060 +       dsmark_dequeue,                 /* dequeue */
3061 +       dsmark_requeue,                 /* requeue */
3062 +       dsmark_drop,                    /* drop */
3063 +
3064 +       dsmark_init,                    /* init */
3065 +       dsmark_reset,                   /* reset */
3066 +       dsmark_destroy,                 /* destroy */
3067 +       NULL,                           /* change */
3068 +
3069 +       dsmark_dump                     /* dump */
3070 +};
3071 +
3072 +#ifdef MODULE
3073 +int init_module(void)
3074 +{
3075 +       return register_qdisc(&dsmark_qdisc_ops);
3076 +}
3077 +
3078 +
3079 +void cleanup_module(void) 
3080 +{
3081 +       unregister_qdisc(&dsmark_qdisc_ops);
3082 +}
3083 +#endif
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
3088 @@ -51,14 +51,14 @@
3089                 sch->stats.backlog += skb->len;
3090                 sch->stats.bytes += skb->len;
3091                 sch->stats.packets++;
3092 -               return 1;
3093 +               return 0;
3094         }
3095         sch->stats.drops++;
3096  #ifdef CONFIG_NET_CLS_POLICE
3097         if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
3098  #endif
3099                 kfree_skb(skb);
3100 -       return 0;
3101 +       return NET_XMIT_DROP;
3102  }
3103  
3104  static int
3105 @@ -66,7 +66,7 @@
3106  {
3107         __skb_queue_head(&sch->q, skb);
3108         sch->stats.backlog += skb->len;
3109 -       return 1;
3110 +       return 0;
3111  }
3112  
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++;
3118 -               return 1;
3119 +               return 0;
3120         }
3121         sch->stats.drops++;
3122  #ifdef CONFIG_NET_CLS_POLICE
3123         if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
3124  #endif
3125                 kfree_skb(skb);
3126 -       return 0;
3127 +       return NET_XMIT_DROP;
3128  }
3129  
3130  static int
3131  pfifo_requeue(struct sk_buff *skb, struct Qdisc* sch)
3132  {
3133         __skb_queue_head(&sch->q, skb);
3134 -       return 1;
3135 +       return 0;
3136  }
3137  
3138  
3139 @@ -152,7 +152,6 @@
3140         return 0;
3141  }
3142  
3143 -#ifdef CONFIG_RTNETLINK
3144  static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
3145  {
3146         struct fifo_sched_data *q = (void*)sch->data;
3147 @@ -168,7 +167,6 @@
3148         skb_trim(skb, b - skb->data);
3149         return -1;
3150  }
3151 -#endif
3152  
3153  struct Qdisc_ops pfifo_qdisc_ops =
3154  {
3155 @@ -187,9 +185,7 @@
3156         NULL,
3157         fifo_init,
3158  
3159 -#ifdef CONFIG_RTNETLINK
3160         fifo_dump,
3161 -#endif
3162  };
3163  
3164  struct Qdisc_ops bfifo_qdisc_ops =
3165 @@ -208,7 +204,5 @@
3166         fifo_reset,
3167         NULL,
3168         fifo_init,
3169 -#ifdef CONFIG_RTNETLINK
3170         fifo_dump,
3171 -#endif
3172  };
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
3176 @@ -7,6 +7,8 @@
3177   *             2 of the License, or (at your option) any later version.
3178   *
3179   * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
3180 + *             Jamal Hadi Salim, <hadi@nortelnetworks.com>
3181 + *             - Ingress support
3182   */
3183  
3184  #include <asm/uaccess.h>
3185 @@ -30,8 +32,6 @@
3186  #include <net/sock.h>
3187  #include <net/pkt_sched.h>
3188  
3189 -#define BUG_TRAP(x) if (!(x)) { printk("Assertion (" #x ") failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); }
3190 -
3191  /* Main transmission queue. */
3192  
3193  struct Qdisc_head qdisc_head = { &qdisc_head };
3194 @@ -149,7 +149,7 @@
3195  noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc)
3196  {
3197         kfree_skb(skb);
3198 -       return 0;
3199 +       return NET_XMIT_CN;
3200  }
3201  
3202  static struct sk_buff *
3203 @@ -164,7 +164,7 @@
3204         if (net_ratelimit())
3205                 printk(KERN_DEBUG "%s deferred output. It is buggy.\n", skb->dev->name);
3206         kfree_skb(skb);
3207 -       return 0;
3208 +       return NET_XMIT_CN;
3209  }
3210  
3211  struct Qdisc_ops noop_qdisc_ops =
3212 @@ -206,7 +206,7 @@
3213  {
3214          { NULL }, 
3215         NULL,
3216 -       NULL,
3217 +       noop_dequeue,
3218         TCQ_F_BUILTIN,
3219         &noqueue_qdisc_ops,
3220  };
3221 @@ -227,14 +227,14 @@
3222         list = ((struct sk_buff_head*)qdisc->data) +
3223                 prio2band[skb->priority&TC_PRIO_MAX];
3224  
3225 -       if (list->qlen <= skb->dev->tx_queue_len) {
3226 +       if (list->qlen <= qdisc->dev->tx_queue_len) {
3227                 __skb_queue_tail(list, skb);
3228                 qdisc->q.qlen++;
3229 -               return 1;
3230 +               return 0;
3231         }
3232         qdisc->stats.drops++;
3233         kfree_skb(skb);
3234 -       return 0;
3235 +       return NET_XMIT_DROP;
3236  }
3237  
3238  static struct sk_buff *
3239 @@ -264,7 +264,7 @@
3240  
3241         __skb_queue_head(list, skb);
3242         qdisc->q.qlen++;
3243 -       return 1;
3244 +       return 0;
3245  }
3246  
3247  static void
3248 @@ -333,39 +333,39 @@
3249  void qdisc_reset(struct Qdisc *qdisc)
3250  {
3251         struct Qdisc_ops *ops = qdisc->ops;
3252 -       start_bh_atomic();
3253 +
3254         if (ops->reset)
3255                 ops->reset(qdisc);
3256 -       end_bh_atomic();
3257  }
3258  
3259  void qdisc_destroy(struct Qdisc *qdisc)
3260  {
3261         struct Qdisc_ops *ops = qdisc->ops;
3262 +       struct device *dev;
3263  
3264         if (!atomic_dec_and_test(&qdisc->refcnt))
3265                 return;
3266  
3267 +       dev = qdisc->dev;
3268 +
3269  #ifdef CONFIG_NET_SCHED
3270 -       if (qdisc->dev) {
3271 +       if (dev) {
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) {
3275                         if (q == qdisc) {
3276                                 *qp = q->next;
3277 -                               q->next = NULL;
3278                                 break;
3279                         }
3280 +               }
3281         }
3282  #ifdef CONFIG_NET_ESTIMATOR
3283         qdisc_kill_estimator(&qdisc->stats);
3284  #endif
3285  #endif
3286 -       start_bh_atomic();
3287         if (ops->reset)
3288                 ops->reset(qdisc);
3289         if (ops->destroy)
3290                 ops->destroy(qdisc);
3291 -       end_bh_atomic();
3292         if (!(qdisc->flags&TCQ_F_BUILTIN))
3293                 kfree(qdisc);
3294  }
3295 @@ -380,19 +380,20 @@
3296          */
3297  
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);
3305                                 return;
3306                         }
3307 -                       dev->qdisc_sleeping = qdisc;
3308 -               } else
3309 -                       dev->qdisc_sleeping = &noqueue_qdisc;
3310 +               } else {
3311 +                       qdisc =  &noqueue_qdisc;
3312 +               }
3313 +               dev->qdisc_sleeping = qdisc;
3314         }
3315  
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);
3324         }
3325 -       end_bh_atomic();
3326 +       sch_dev_queue_unlock(dev);
3327  }
3328  
3329  void dev_deactivate(struct device *dev)
3330  {
3331         struct Qdisc *qdisc;
3332  
3333 -       start_bh_atomic();
3334 +       sch_dev_queue_lock(dev);
3335  
3336 -       qdisc = xchg(&dev->qdisc, &noop_qdisc);
3337 +       qdisc = dev->qdisc;
3338 +       dev->qdisc = &noop_qdisc;
3339  
3340         qdisc_reset(qdisc);
3341  
3342 @@ -425,7 +427,7 @@
3343                 }
3344         }
3345  
3346 -       end_bh_atomic();
3347 +       sch_dev_queue_unlock(dev);
3348  }
3349  
3350  void dev_init_scheduler(struct device *dev)
3351 @@ -439,13 +441,16 @@
3352  {
3353         struct Qdisc *qdisc;
3354  
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);
3364 +        }
3365         BUG_TRAP(dev->qdisc_list == NULL);
3366         dev->qdisc_list = NULL;
3367 -       end_bh_atomic();
3368 +       sch_dev_queue_unlock(dev);
3369  }
3370 -
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
3374 @@ -0,0 +1,633 @@
3375 +/*
3376 + * net/sched/sch_gred.c        Generic Random Early Detection queue.
3377 + *
3378 + *
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.
3383 + *
3384 + * Authors:    J Hadi Salim (hadi@cyberus.ca) 1998-2002
3385 + *
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
3389 + *                      from Ren Liu
3390 + *                    - More error checks
3391 + *
3392 + *
3393 + *
3394 + *  For all the glorious comments look at Alexey's sch_red.c
3395 + */
3396 +
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>
3422 +
3423 +#if 1 /* control */
3424 +#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
3425 +#else
3426 +#define DPRINTK(format,args...)
3427 +#endif
3428 +
3429 +#if 0 /* data */
3430 +#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
3431 +#else
3432 +#define D2PRINTK(format,args...)
3433 +#endif
3434 +
3435 +struct gred_sched_data;
3436 +struct gred_sched;
3437 +
3438 +struct gred_sched_data
3439 +{
3440 +/* Parameters */
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   */
3447 +       u32             Scell_max;
3448 +       u32             Rmask;
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 */
3456 +       char            Scell_log;
3457 +       u8              Stab[256];
3458 +       u8              prio;        /* the prio of this vq */
3459 +
3460 +/* Variables */
3461 +       unsigned long   qave;           /* Average queue length: A scaled */
3462 +       int             qcount;         /* Packets since last random number generation */
3463 +       u32             qR;             /* Cached random number */
3464 +
3465 +       psched_time_t   qidlestart;     /* Start of idle period */
3466 +};
3467 +
3468 +struct gred_sched
3469 +{
3470 +       struct gred_sched_data *tab[MAX_DPs];
3471 +       u32             DPs;   
3472 +       u32             def; 
3473 +       u8              initd; 
3474 +       u8              grio; 
3475 +       u8              eqp; 
3476 +};
3477 +
3478 +static int
3479 +gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
3480 +{
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; 
3485 +       int i=0;
3486 +
3487 +       if (!t->initd && skb_queue_len(&sch->q) <= sch->dev->tx_queue_len) {
3488 +               D2PRINTK("NO GRED Queues setup yet! Enqueued anyway\n");
3489 +               goto do_enqueue;
3490 +       }
3491 +
3492 +
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);
3498 +                       goto drop;
3499 +               }
3500 +               /* fix tc_index? --could be controvesial but needed for
3501 +                  requeueing */
3502 +               skb->tc_index=(skb->tc_index&0xfffffff0) | t->def;
3503 +       }
3504 +
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)) 
3512 +                               continue; 
3513 +                               
3514 +                       if ((t->tab[i]->prio < q->prio) && (PSCHED_IS_PASTPERFECT(t->tab[i]->qidlestart)))
3515 +                               qave +=t->tab[i]->qave;
3516 +               }
3517 +                       
3518 +       }
3519 +
3520 +       q->packetsin++;
3521 +       q->bytesin+=skb->len;
3522 +
3523 +       if (t->eqp && t->grio) {
3524 +               qave=0;
3525 +               q->qave=t->tab[t->def]->qave;
3526 +               q->qidlestart=t->tab[t->def]->qidlestart;
3527 +       }
3528 +
3529 +       if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) {
3530 +               long us_idle;
3531 +               PSCHED_GET_TIME(now);
3532 +               us_idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max, 0);
3533 +               PSCHED_SET_PASTPERFECT(q->qidlestart);
3534 +
3535 +               q->qave >>= q->Stab[(us_idle>>q->Scell_log)&0xFF];
3536 +       } else {
3537 +               if (t->eqp) {
3538 +                       q->qave += sch->stats.backlog - (q->qave >> q->Wlog);
3539 +               } else {
3540 +                       q->qave += q->backlog - (q->qave >> q->Wlog);
3541 +               }
3542 +
3543 +       }
3544 +       
3545 +
3546 +       if (t->eqp && t->grio) 
3547 +               t->tab[t->def]->qave=q->qave;
3548 +
3549 +       if ((q->qave+qave) < q->qth_min) {
3550 +               q->qcount = -1;
3551 +enqueue:
3552 +               if (q->backlog <= q->limit) {
3553 +                       q->backlog += skb->len;
3554 +do_enqueue:
3555 +                       __skb_queue_tail(&sch->q, skb);
3556 +                       sch->stats.backlog += skb->len;
3557 +                       sch->stats.bytes += skb->len;
3558 +                       sch->stats.packets++;
3559 +                       return 0;
3560 +               } else {
3561 +                       q->pdrop++;
3562 +               }
3563 +
3564 +drop:
3565 +               kfree_skb(skb);
3566 +               sch->stats.drops++;
3567 +               return NET_XMIT_DROP;
3568 +       }
3569 +       if ((q->qave+qave) >= q->qth_max) {
3570 +               q->qcount = -1;
3571 +               sch->stats.overlimits++;
3572 +               q->forced++;
3573 +               goto drop;
3574 +       }
3575 +       if (++q->qcount) {
3576 +               if ((((qave+q->qave) - q->qth_min)>>q->Wlog)*q->qcount < q->qR)
3577 +                       goto enqueue;
3578 +               q->qcount = 0;
3579 +               q->qR = net_random()&q->Rmask;
3580 +               sch->stats.overlimits++;
3581 +               q->early++;
3582 +               goto drop;
3583 +       }
3584 +       q->qR = net_random()&q->Rmask;
3585 +       goto enqueue;
3586 +}
3587 +
3588 +static int
3589 +gred_requeue(struct sk_buff *skb, struct Qdisc* sch)
3590 +{
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);
3596 +
3597 +       __skb_queue_head(&sch->q, skb);
3598 +       sch->stats.backlog += skb->len;
3599 +       q->backlog += skb->len;
3600 +       return 0;
3601 +}
3602 +
3603 +static struct sk_buff *
3604 +gred_dequeue(struct Qdisc* sch)
3605 +{
3606 +       struct sk_buff *skb;
3607 +       struct gred_sched_data *q;
3608 +       struct gred_sched *t= (struct gred_sched *)sch->data;
3609 +
3610 +       skb = __skb_dequeue(&sch->q);
3611 +       if (skb) {
3612 +               sch->stats.backlog -= skb->len;
3613 +               q= t->tab[(skb->tc_index&0xf)];
3614 +               if (q) {
3615 +                       q->backlog -= skb->len;
3616 +                       if (!q->backlog && !t->eqp)
3617 +                               PSCHED_GET_TIME(q->qidlestart);
3618 +               } else {
3619 +                       D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); 
3620 +               }
3621 +               return skb;
3622 +       }
3623 +
3624 +       if (t->eqp) {
3625 +                       q= t->tab[t->def];
3626 +                       if (!q) 
3627 +                               D2PRINTK("no default VQ set: Results will be "
3628 +                                      "screwed up\n");
3629 +                       else
3630 +                               PSCHED_GET_TIME(q->qidlestart);
3631 +       }
3632 +
3633 +       return NULL;
3634 +}
3635 +
3636 +static int
3637 +gred_drop(struct Qdisc* sch)
3638 +{
3639 +       struct sk_buff *skb;
3640 +
3641 +       struct gred_sched_data *q;
3642 +       struct gred_sched *t= (struct gred_sched *)sch->data;
3643 +
3644 +       skb = __skb_dequeue_tail(&sch->q);
3645 +       if (skb) {
3646 +               sch->stats.backlog -= skb->len;
3647 +               sch->stats.drops++;
3648 +               q= t->tab[(skb->tc_index&0xf)];
3649 +               if (q) {
3650 +                       q->backlog -= skb->len;
3651 +                       q->other++;
3652 +                       if (!q->backlog && !t->eqp)
3653 +                               PSCHED_GET_TIME(q->qidlestart);
3654 +                       } else {
3655 +                               D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); 
3656 +                       }
3657 +
3658 +               kfree_skb(skb);
3659 +               return 1;
3660 +       }
3661 +
3662 +       q=t->tab[t->def];
3663 +       if (!q) {
3664 +               D2PRINTK("no default VQ set: Results might be screwed up\n");
3665 +               return 0;
3666 +       }
3667 +
3668 +       PSCHED_GET_TIME(q->qidlestart);
3669 +       return 0;
3670 +
3671 +}
3672 +
3673 +static void gred_reset(struct Qdisc* sch)
3674 +{
3675 +       int i;
3676 +       struct gred_sched_data *q;
3677 +       struct gred_sched *t= (struct gred_sched *)sch->data;
3678 +
3679 +       __skb_queue_purge(&sch->q);
3680 +
3681 +       sch->stats.backlog = 0;
3682 +
3683 +        for (i=0;i<t->DPs;i++) {
3684 +               q= t->tab[i];
3685 +               if (!q) 
3686 +                       continue; 
3687 +               PSCHED_SET_PASTPERFECT(q->qidlestart);
3688 +               q->qave = 0;
3689 +               q->qcount = -1;
3690 +               q->backlog = 0;
3691 +               q->other=0;
3692 +               q->forced=0;
3693 +               q->pdrop=0;
3694 +               q->early=0;
3695 +       }
3696 +}
3697 +
3698 +static int gred_change(struct Qdisc *sch, struct rtattr *opt)
3699 +{
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];
3706 +       int i;
3707 +
3708 +       if (opt == NULL ||
3709 +               rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
3710 +                       return -EINVAL;
3711 +
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));
3716 +
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; 
3721 +               table->initd=0;
3722 +               /* probably need to clear all the table DP entries as well */
3723 +               MOD_INC_USE_COUNT;
3724 +               return 0;
3725 +           }
3726 +
3727 +
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)
3731 +                       return -EINVAL;
3732 +
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;
3739 +       }
3740 +       
3741 +       if (table->tab[ctl->DP] == NULL) {
3742 +               table->tab[ctl->DP]=kmalloc(sizeof(struct gred_sched_data),
3743 +                                           GFP_KERNEL);
3744 +               if (NULL == table->tab[ctl->DP])
3745 +                       return -ENOMEM;
3746 +               memset(table->tab[ctl->DP], 0, (sizeof(struct gred_sched_data)));
3747 +       }
3748 +       q= table->tab[ctl->DP]; 
3749 +
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;
3757 +                       } else { 
3758 +                               DPRINTK("\nGRED: DP %u does not have a prio"
3759 +                                       " setting default to 8\n",ctl->DP);
3760 +                               q->prio=8;
3761 +                       }
3762 +               } else {
3763 +                       q->prio=ctl->prio;
3764 +               }
3765 +       } else {
3766 +               q->prio=8;
3767 +       }
3768 +
3769 +
3770 +       q->DP=ctl->DP;
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;
3779 +       q->qave=0;
3780 +       q->backlog=0;
3781 +       q->qcount = -1;
3782 +       q->other=0;
3783 +       q->forced=0;
3784 +       q->pdrop=0;
3785 +       q->early=0;
3786 +
3787 +       PSCHED_SET_PASTPERFECT(q->qidlestart);
3788 +       memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256);
3789 +
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) )    
3794 +                               continue; 
3795 +                       if (table->tab[i]->prio == q->prio ){
3796 +                               /* WRED mode detected */
3797 +                               table->eqp=1;
3798 +                               break;
3799 +                       }
3800 +               }
3801 +       }
3802 +
3803 +       if (!table->initd) {
3804 +               table->initd=1;
3805 +               /* 
3806 +               the first entry also goes into the default until
3807 +               over-written 
3808 +               */
3809 +
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])
3814 +                               return -ENOMEM;
3815 +
3816 +                       memset(table->tab[table->def], 0,
3817 +                              (sizeof(struct gred_sched_data)));
3818 +               }
3819 +               q= table->tab[table->def]; 
3820 +               q->DP=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;
3829 +
3830 +               if (table->grio)
3831 +                       q->prio=table->tab[ctl->DP]->prio;
3832 +               else
3833 +                       q->prio=8;
3834 +
3835 +               q->qcount = -1;
3836 +               PSCHED_SET_PASTPERFECT(q->qidlestart);
3837 +               memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256);
3838 +       }
3839 +       return 0;
3840 +
3841 +}
3842 +
3843 +static int gred_init(struct Qdisc *sch, struct rtattr *opt)
3844 +{
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];
3849 +
3850 +       if (opt == NULL ||
3851 +               rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
3852 +                       return -EINVAL;
3853 +
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));
3857 +
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; 
3862 +               table->initd=0;
3863 +               MOD_INC_USE_COUNT;
3864 +               return 0;
3865 +       }
3866 +
3867 +       DPRINTK("\n GRED_INIT error!\n");
3868 +       return -EINVAL;
3869 +}
3870 +
3871 +static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
3872 +{
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;
3879 +       int i;
3880 +       unsigned char    *b = skb->tail;
3881 +
3882 +       rta = (struct rtattr*)b;
3883 +       RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
3884 +
3885 +       opt=kmalloc(sizeof(struct tc_gred_qopt)*MAX_DPs, GFP_KERNEL);
3886 +
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;
3891 +       }
3892 +
3893 +       memset(opt, 0, (sizeof(struct tc_gred_qopt))*table->DPs);
3894 +
3895 +       if (!table->initd) {
3896 +               DPRINTK("NO GRED Queues setup!\n");
3897 +       }
3898 +
3899 +       for (i=0;i<MAX_DPs;i++) {
3900 +               dst= &opt[i]; 
3901 +               q= table->tab[i]; 
3902 +
3903 +               if (!q) {
3904 +                       /* hack -- fix at some point with proper message
3905 +                          This is how we indicate to tc that there is no VQ
3906 +                          at this DP */
3907 +
3908 +                       dst->DP=MAX_DPs+i;
3909 +                       continue;
3910 +               }
3911 +
3912 +               dst->limit=q->limit;
3913 +               dst->qth_min=q->qth_min>>q->Wlog;
3914 +               dst->qth_max=q->qth_max>>q->Wlog;
3915 +               dst->DP=q->DP;
3916 +               dst->backlog=q->backlog;
3917 +               if (q->qave) {
3918 +                       if (table->eqp && table->grio) {
3919 +                               q->qidlestart=table->tab[table->def]->qidlestart;
3920 +                               q->qave=table->tab[table->def]->qave;
3921 +                       }
3922 +                       if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) {
3923 +                               long idle;
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;
3929 +
3930 +                       } else {
3931 +                               dst->qave = q->qave >> q->Wlog;
3932 +                       }
3933 +               } else {
3934 +                       dst->qave = 0;
3935 +               }
3936 +               
3937 +
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;
3948 +       }
3949 +
3950 +       RTA_PUT(skb, TCA_GRED_PARMS, sizeof(struct tc_gred_qopt)*MAX_DPs, opt);
3951 +       rta->rta_len = skb->tail - b;
3952 +
3953 +       kfree(opt);
3954 +       return skb->len;
3955 +
3956 +rtattr_failure:
3957 +       if (opt)
3958 +               kfree(opt);
3959 +       DPRINTK("gred_dump: FAILURE!!!!\n");
3960 +
3961 +/* also free the opt struct here */
3962 +       skb_trim(skb, b - skb->data);
3963 +       return -1;
3964 +}
3965 +
3966 +static void gred_destroy(struct Qdisc *sch)
3967 +{
3968 +       struct gred_sched *table = (struct gred_sched *)sch->data;
3969 +       int i;
3970 +
3971 +       for (i = 0;i < table->DPs; i++) {
3972 +               if (table->tab[i])
3973 +                       kfree(table->tab[i]);
3974 +       }
3975 +       MOD_DEC_USE_COUNT;
3976 +}
3977 +
3978 +struct Qdisc_ops gred_qdisc_ops =
3979 +{
3980 +       NULL,
3981 +       NULL,
3982 +       "gred",
3983 +       sizeof(struct gred_sched),
3984 +       gred_enqueue,
3985 +       gred_dequeue,
3986 +       gred_requeue,
3987 +       gred_drop,
3988 +       gred_init,
3989 +       gred_reset,
3990 +       gred_destroy,
3991 +       gred_change, /* change */
3992 +       gred_dump,
3993 +};
3994 +
3995 +
3996 +#ifdef MODULE
3997 +int init_module(void)
3998 +{
3999 +       return register_qdisc(&gred_qdisc_ops);
4000 +}
4001 +
4002 +void cleanup_module(void) 
4003 +{
4004 +       unregister_qdisc(&gred_qdisc_ops);
4005 +}
4006 +#endif
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
4011 @@ -0,0 +1,313 @@
4012 +/* net/sched/sch_ingress.c - Ingress qdisc */
4013 +
4014 +/* Written 1999 by Jamal Hadi Salim */
4015 +
4016 +
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>
4026 +
4027 +#undef DEBUG_INGRESS
4028 +
4029 +#ifdef DEBUG_INGRESS  /* control */
4030 +#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
4031 +#else
4032 +#define DPRINTK(format,args...)
4033 +#endif
4034 +
4035 +#if 0  /* data */
4036 +#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
4037 +#else
4038 +#define D2PRINTK(format,args...)
4039 +#endif
4040 +
4041 +
4042 +#define PRIV(sch) ((struct ingress_qdisc_data *) (sch)->data)
4043 +
4044 +
4045 +
4046 +struct ingress_qdisc_data {
4047 +       struct Qdisc            *q;
4048 +       struct tcf_proto        *filter_list;
4049 +};
4050 +
4051 +
4052 +/* ------------------------- Class/flow operations ------------------------- */
4053 +
4054 +
4055 +static int ingress_graft(struct Qdisc *sch,unsigned long arg,
4056 +    struct Qdisc *new,struct Qdisc **old)
4057 +{
4058 +#ifdef DEBUG_INGRESS
4059 +       struct ingress_qdisc_data *p = PRIV(sch);
4060 +#endif
4061 +
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");
4065 +        return 1;
4066 +}
4067 +
4068 +
4069 +static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
4070 +{
4071 +       return NULL;
4072 +}
4073 +
4074 +
4075 +static unsigned long ingress_get(struct Qdisc *sch,u32 classid)
4076 +{
4077 +#ifdef DEBUG_INGRESS
4078 +       struct ingress_qdisc_data *p = PRIV(sch);
4079 +#endif
4080 +       DPRINTK("ingress_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
4081 +       return TC_H_MIN(classid) + 1;
4082 +}
4083 +
4084 +
4085 +static unsigned long ingress_bind_filter(struct Qdisc *sch,
4086 +    unsigned long parent, u32 classid)
4087 +{
4088 +       return ingress_get(sch, classid);
4089 +}
4090 +
4091 +
4092 +static void ingress_put(struct Qdisc *sch, unsigned long cl)
4093 +{
4094 +}
4095 +
4096 +
4097 +static int ingress_change(struct Qdisc *sch, u32 classid, u32 parent,
4098 +    struct rtattr **tca, unsigned long *arg)
4099 +{
4100 +#ifdef DEBUG_INGRESS
4101 +       struct ingress_qdisc_data *p = PRIV(sch);
4102 +#endif
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");
4106 +       return 0;
4107 +}
4108 +
4109 +
4110 +
4111 +static void ingress_walk(struct Qdisc *sch,struct qdisc_walker *walker)
4112 +{
4113 +#ifdef DEBUG_INGRESS
4114 +       struct ingress_qdisc_data *p = PRIV(sch);
4115 +#endif
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");
4118 +}
4119 +
4120 +
4121 +static struct tcf_proto **ingress_find_tcf(struct Qdisc *sch,unsigned long cl)
4122 +{
4123 +       struct ingress_qdisc_data *p = PRIV(sch);
4124 +
4125 +       return &p->filter_list;
4126 +}
4127 +
4128 +
4129 +/* --------------------------- Qdisc operations ---------------------------- */
4130 +
4131 +
4132 +static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
4133 +{
4134 +       struct ingress_qdisc_data *p = PRIV(sch);
4135 +       struct tcf_result res;
4136 +       int result;
4137 +
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);
4141 +       /*
4142 +        * Unlike normal "enqueue" functions, ingress_enqueue returns a
4143 +        * firewall FW_* code.
4144 +        */
4145 +#ifdef CONFIG_NET_CLS_POLICE
4146 +       switch (result) {
4147 +               case TC_POLICE_SHOT:
4148 +                       result = FW_BLOCK;
4149 +                       sch->stats.drops++;
4150 +                       break;
4151 +               case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */
4152 +               case TC_POLICE_OK:
4153 +               case TC_POLICE_UNSPEC:
4154 +               default:
4155 +                       sch->stats.packets++;
4156 +                       sch->stats.bytes += skb->len;
4157 +                       result = FW_ACCEPT;
4158 +                       break;
4159 +       };
4160 +#else
4161 +       sch->stats.packets++;
4162 +       sch->stats.bytes += skb->len;
4163 +#endif
4164 +
4165 +       skb->tc_index = TC_H_MIN(res.classid);
4166 +       return result;
4167 +}
4168 +
4169 +
4170 +static struct sk_buff *ingress_dequeue(struct Qdisc *sch)
4171 +{
4172 +/*
4173 +       struct ingress_qdisc_data *p = PRIV(sch);
4174 +       D2PRINTK("ingress_dequeue(sch %p,[qdisc %p])\n",sch,PRIV(p));
4175 +*/
4176 +       return NULL;
4177 +}
4178 +
4179 +
4180 +static int ingress_requeue(struct sk_buff *skb,struct Qdisc *sch)
4181 +{
4182 +/*
4183 +       struct ingress_qdisc_data *p = PRIV(sch);
4184 +       D2PRINTK("ingress_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,PRIV(p));
4185 +*/
4186 +       return 0;
4187 +}
4188 +
4189 +static int ingress_drop(struct Qdisc *sch)
4190 +{
4191 +#ifdef DEBUG_INGRESS
4192 +       struct ingress_qdisc_data *p = PRIV(sch);
4193 +#endif
4194 +       DPRINTK("ingress_drop(sch %p,[qdisc %p])\n", sch, p);
4195 +       return 0;
4196 +}
4197 +
4198 +
4199 +int ingress_init(struct Qdisc *sch,struct rtattr *opt)
4200 +{
4201 +       struct ingress_qdisc_data *p = PRIV(sch);
4202 +
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;
4208 +       return 0;
4209 +}
4210 +
4211 +
4212 +static void ingress_reset(struct Qdisc *sch)
4213 +{
4214 +       struct ingress_qdisc_data *p = PRIV(sch);
4215 +
4216 +       DPRINTK("ingress_reset(sch %p,[qdisc %p])\n", sch, p);
4217 +
4218 +/*
4219 +#if 0
4220 +*/
4221 +/* for future use */
4222 +       qdisc_reset(p->q);
4223 +/*
4224 +#endif
4225 +*/
4226 +}
4227 +
4228 +
4229 +static void ingress_destroy(struct Qdisc *sch)
4230 +{
4231 +       struct ingress_qdisc_data *p = PRIV(sch);
4232 +       struct tcf_proto *tp;
4233 +
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);
4239 +       }
4240 +       memset(p, 0, sizeof(*p));
4241 +       p->filter_list = NULL;
4242 +
4243 +#if 0
4244 +/* for future use */
4245 +       qdisc_destroy(p->q);
4246 +#endif
4247
4248 +       MOD_DEC_USE_COUNT;
4249 +
4250 +}
4251 +
4252 +
4253 +static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
4254 +{
4255 +       unsigned char *b = skb->tail;
4256 +       struct rtattr *rta;
4257 +
4258 +       rta = (struct rtattr *) b;
4259 +       RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
4260 +       rta->rta_len = skb->tail - b;
4261 +       return skb->len;
4262 +
4263 +rtattr_failure:
4264 +       skb_trim(skb, b - skb->data);
4265 +       return -1;
4266 +}
4267 +
4268 +static struct Qdisc_class_ops ingress_class_ops =
4269 +{
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 */
4277 +
4278 +       ingress_find_tcf,               /* tcf_chain */
4279 +       ingress_bind_filter,            /* bind_tcf */
4280 +       ingress_put,                    /* unbind_tcf */
4281 +
4282 +       NULL,           /* dump */
4283 +};
4284 +
4285 +struct Qdisc_ops ingress_qdisc_ops =
4286 +{
4287 +       NULL,                           /* next */
4288 +       &ingress_class_ops,             /* cl_ops */
4289 +       "ingress",
4290 +       sizeof(struct ingress_qdisc_data),
4291 +
4292 +       ingress_enqueue,                /* enqueue */
4293 +       ingress_dequeue,                /* dequeue */
4294 +       ingress_requeue,                /* requeue */
4295 +       ingress_drop,                   /* drop */
4296 +
4297 +       ingress_init,                   /* init */
4298 +       ingress_reset,                  /* reset */
4299 +       ingress_destroy,                /* destroy */
4300 +       NULL,                           /* change */
4301 +
4302 +       ingress_dump,                   /* dump */
4303 +};
4304 +
4305 +
4306 +#ifdef MODULE
4307 +int init_module(void)
4308 +{
4309 +       int ret = 0;
4310 +
4311 +       if ((ret = register_qdisc(&ingress_qdisc_ops)) < 0) {
4312 +               printk("Unable to register Ingress qdisc\n");
4313 +               return ret;
4314 +       }
4315 +
4316 +       return ret;
4317 +}
4318 +
4319 +
4320 +void cleanup_module(void) 
4321 +{
4322 +       unregister_qdisc(&ingress_qdisc_ops);
4323 +}
4324 +#endif
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
4328 @@ -7,6 +7,8 @@
4329   *             2 of the License, or (at your option) any later version.
4330   *
4331   * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
4332 + * Fixes:       19990609: J Hadi Salim <hadi@nortelnetworks.com>: 
4333 + *              Init --  EINVAL when opt undefined
4334   */
4335  
4336  #include <linux/config.h>
4337 @@ -69,17 +71,18 @@
4338  {
4339         struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
4340         struct Qdisc *qdisc;
4341 +       int ret;
4342  
4343         qdisc = q->queues[prio_classify(skb, sch)];
4344  
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++;
4349                 sch->q.qlen++;
4350 -               return 1;
4351 +               return 0;
4352         }
4353         sch->stats.drops++;
4354 -       return 0;
4355 +       return ret;
4356  }
4357  
4358  
4359 @@ -88,15 +91,16 @@
4360  {
4361         struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
4362         struct Qdisc *qdisc;
4363 +       int ret;
4364  
4365         qdisc = q->queues[prio_classify(skb, sch)];
4366  
4367 -       if (qdisc->ops->requeue(skb, qdisc) == 1) {
4368 +       if ((ret = qdisc->ops->requeue(skb, qdisc)) == 0) {
4369                 sch->q.qlen++;
4370 -               return 1;
4371 +               return 0;
4372         }
4373         sch->stats.drops++;
4374 -       return 0;
4375 +       return ret;
4376  }
4377  
4378  
4379 @@ -178,7 +182,7 @@
4380                         return -EINVAL;
4381         }
4382  
4383 -       start_bh_atomic();
4384 +       sch_tree_lock(sch);
4385         q->bands = qopt->bands;
4386         memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
4387  
4388 @@ -187,7 +191,7 @@
4389                 if (child != &noop_qdisc)
4390                         qdisc_destroy(child);
4391         }
4392 -       end_bh_atomic();
4393 +       sch_tree_unlock(sch);
4394  
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);
4400                         if (child) {
4401 +                               sch_tree_lock(sch);
4402                                 child = xchg(&q->queues[band], child);
4403 -                               synchronize_bh();
4404  
4405                                 if (child != &noop_qdisc)
4406                                         qdisc_destroy(child);
4407 +                               sch_tree_unlock(sch);
4408                         }
4409                 }
4410         }
4411 @@ -208,8 +213,6 @@
4412  
4413  static int prio_init(struct Qdisc *sch, struct rtattr *opt)
4414  {
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;
4418         int i;
4419  
4420 @@ -217,14 +220,7 @@
4421                 q->queues[i] = &noop_qdisc;
4422  
4423         if (opt == NULL) {
4424 -               q->bands = 3;
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);
4429 -                       if (child)
4430 -                               q->queues[i] = child;
4431 -               }
4432 +               return -EINVAL;
4433         } else {
4434                 int err;
4435  
4436 @@ -235,7 +231,6 @@
4437         return 0;
4438  }
4439  
4440 -#ifdef CONFIG_RTNETLINK
4441  static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
4442  {
4443         struct prio_sched_data *q = (struct prio_sched_data *)sch->data;
4444 @@ -251,7 +246,6 @@
4445         skb_trim(skb, b - skb->data);
4446         return -1;
4447  }
4448 -#endif
4449  
4450  static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
4451                       struct Qdisc **old)
4452 @@ -265,7 +259,11 @@
4453         if (new == NULL)
4454                 new = &noop_qdisc;
4455  
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);
4462  
4463         return 0;
4464  }
4465 @@ -322,7 +320,6 @@
4466  }
4467  
4468  
4469 -#ifdef CONFIG_RTNETLINK
4470  static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb,
4471                            struct tcmsg *tcm)
4472  {
4473 @@ -330,11 +327,11 @@
4474  
4475         if (cl - 1 > q->bands)
4476                 return -ENOENT;
4477 +       tcm->tcm_handle |= TC_H_MIN(cl);
4478         if (q->queues[cl-1])
4479                 tcm->tcm_info = q->queues[cl-1]->handle;
4480         return 0;
4481  }
4482 -#endif
4483  
4484  static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
4485  {
4486 @@ -381,9 +378,7 @@
4487         prio_bind,
4488         prio_put,
4489  
4490 -#ifdef CONFIG_RTNETLINK
4491         prio_dump_class,
4492 -#endif
4493  };
4494  
4495  struct Qdisc_ops prio_qdisc_ops =
4496 @@ -403,9 +398,7 @@
4497         prio_destroy,
4498         prio_tune,
4499  
4500 -#ifdef CONFIG_RTNETLINK
4501         prio_dump,
4502 -#endif
4503  };
4504  
4505  #ifdef MODULE
4506 @@ -421,3 +414,4 @@
4507  }
4508  
4509  #endif
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
4514 @@ -10,6 +10,8 @@
4515   *
4516   * Changes:
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 
4520   */
4521  
4522  #include <linux/config.h>
4523 @@ -38,6 +40,9 @@
4524  #include <net/sock.h>
4525  #include <net/pkt_sched.h>
4526  
4527 +#define RED_ECN_ECT  0x02
4528 +#define RED_ECN_CE   0x01
4529 +
4530  
4531  /*     Random Early Detection (RED) algorithm.
4532         =======================================
4533 @@ -137,6 +142,7 @@
4534         u32             qth_max;        /* Max average length threshold: A scaled */
4535         u32             Rmask;
4536         u32             Scell_max;
4537 +       unsigned char   flags;
4538         char            Wlog;           /* log(W)               */
4539         char            Plog;           /* random number bits   */
4540         char            Scell_log;
4541 @@ -148,8 +154,43 @@
4542         u32             qR;             /* Cached random number */
4543  
4544         psched_time_t   qidlestart;     /* Start of idle period         */
4545 +       struct tc_red_xstats st;
4546  };
4547  
4548 +static int red_ecn_mark(struct sk_buff *skb)
4549 +{
4550 +       if (skb->nh.raw + 20 > skb->tail)
4551 +               return 0;
4552 +
4553 +       switch (skb->protocol) {
4554 +       case __constant_htons(ETH_P_IP):
4555 +       {
4556 +               u8 tos = skb->nh.iph->tos;
4557 +
4558 +               if (!(tos & RED_ECN_ECT))
4559 +                       return 0;
4560 +
4561 +               if (!(tos & RED_ECN_CE))
4562 +                       IP_ECN_set_ce(skb->nh.iph);
4563 +
4564 +               return 1;
4565 +       }
4566 +
4567 +       case __constant_htons(ETH_P_IPV6):
4568 +       {
4569 +               u32 label = *(u32*)skb->nh.raw;
4570 +
4571 +               if (!(label & __constant_htonl(RED_ECN_ECT<<20)))
4572 +                       return 0;
4573 +               label |= __constant_htonl(RED_ECN_CE<<20);
4574 +               return 1;
4575 +       }
4576 +
4577 +       default:
4578 +               return 0;
4579 +       }
4580 +}
4581 +
4582  static int
4583  red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
4584  {
4585 @@ -159,6 +200,8 @@
4586  
4587         if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) {
4588                 long us_idle;
4589 +               int  shift;
4590 +
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.
4597  */
4598 -               q->qave >>= q->Stab[(us_idle>>q->Scell_log)&0xFF];
4599 +               shift = q->Stab[us_idle>>q->Scell_log];
4600 +
4601 +               if (shift) {
4602 +                       q->qave >>= shift;
4603 +               } else {
4604 +                       /* Approximate initial part of exponent
4605 +                          with linear function:
4606 +                          (1-W)^m ~= 1-mW + ...
4607 +
4608 +                          Seems, it is the best solution to
4609 +                          problem of too coarce exponent tabulation.
4610 +                        */
4611 +
4612 +                       us_idle = (q->qave * us_idle)>>q->Scell_log;
4613 +                       if (us_idle < q->qave/2)
4614 +                               q->qave -= us_idle;
4615 +                       else
4616 +                               q->qave >>= 1;
4617 +               }
4618         } else {
4619                 q->qave += sch->stats.backlog - (q->qave >> q->Wlog);
4620                 /* NOTE:
4621 @@ -200,18 +261,26 @@
4622                         sch->stats.backlog += skb->len;
4623                         sch->stats.bytes += skb->len;
4624                         sch->stats.packets++;
4625 -                       return 1;
4626 +                       return NET_XMIT_SUCCESS;
4627 +               } else {
4628 +                       q->st.pdrop++;
4629                 }
4630 -drop:
4631                 kfree_skb(skb);
4632                 sch->stats.drops++;
4633 -               return 0;
4634 +               return NET_XMIT_DROP;
4635         }
4636         if (q->qave >= q->qth_max) {
4637                 q->qcount = -1;
4638                 sch->stats.overlimits++;
4639 -               goto drop;
4640 +mark:
4641 +               if  (!(q->flags&TC_RED_ECN) || !red_ecn_mark(skb)) {
4642 +                       q->st.early++;
4643 +                       goto drop;
4644 +               }
4645 +               q->st.marked++;
4646 +               goto enqueue;
4647         }
4648 +
4649         if (++q->qcount) {
4650                 /* The formula used below causes questions.
4651  
4652 @@ -234,10 +303,15 @@
4653                 q->qcount = 0;
4654                 q->qR = net_random()&q->Rmask;
4655                 sch->stats.overlimits++;
4656 -               goto drop;
4657 +               goto mark;
4658         }
4659         q->qR = net_random()&q->Rmask;
4660         goto enqueue;
4661 +
4662 +drop:
4663 +       kfree_skb(skb);
4664 +       sch->stats.drops++;
4665 +       return NET_XMIT_CN;
4666  }
4667  
4668  static int
4669 @@ -249,7 +323,7 @@
4670  
4671         __skb_queue_head(&sch->q, skb);
4672         sch->stats.backlog += skb->len;
4673 -       return 1;
4674 +       return 0;
4675  }
4676  
4677  static struct sk_buff *
4678 @@ -277,6 +351,7 @@
4679         if (skb) {
4680                 sch->stats.backlog -= skb->len;
4681                 sch->stats.drops++;
4682 +               q->st.other++;
4683                 kfree_skb(skb);
4684                 return 1;
4685         }
4686 @@ -287,17 +362,15 @@
4687  static void red_reset(struct Qdisc* sch)
4688  {
4689         struct red_sched_data *q = (struct red_sched_data *)sch->data;
4690 -       struct sk_buff *skb;
4691  
4692 -       while((skb=__skb_dequeue(&sch->q))!=NULL)
4693 -               kfree_skb(skb);
4694 +       __skb_queue_purge(&sch->q);
4695         sch->stats.backlog = 0;
4696         PSCHED_SET_PASTPERFECT(q->qidlestart);
4697         q->qave = 0;
4698         q->qcount = -1;
4699  }
4700  
4701 -static int red_init(struct Qdisc *sch, struct rtattr *opt)
4702 +static int red_change(struct Qdisc *sch, struct rtattr *opt)
4703  {
4704         struct red_sched_data *q = (struct red_sched_data *)sch->data;
4705         struct rtattr *tb[TCA_RED_STAB];
4706 @@ -312,6 +385,8 @@
4707  
4708         ctl = RTA_DATA(tb[TCA_RED_PARMS-1]);
4709  
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);
4717  
4718         q->qcount = -1;
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);
4724         return 0;
4725  }
4726  
4727 -#ifdef CONFIG_RTNETLINK
4728 +static int red_init(struct Qdisc* sch, struct rtattr *opt)
4729 +{
4730 +       int err;
4731 +
4732 +       MOD_INC_USE_COUNT;
4733 +
4734 +       if ((err = red_change(sch, opt)) != 0) {
4735 +               MOD_DEC_USE_COUNT;
4736 +       }
4737 +       return err;
4738 +}
4739 +
4740 +
4741 +int red_copy_xstats(struct sk_buff *skb, struct tc_red_xstats *st)
4742 +{
4743 +        RTA_PUT(skb, TCA_XSTATS, sizeof(*st), st);
4744 +        return 0;
4745 +
4746 +rtattr_failure:
4747 +        return 1;
4748 +}
4749 +
4750  static int red_dump(struct Qdisc *sch, struct sk_buff *skb)
4751  {
4752         struct red_sched_data *q = (struct red_sched_data *)sch->data;
4753 @@ -344,16 +441,19 @@
4754         opt.Wlog = q->Wlog;
4755         opt.Plog = q->Plog;
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;
4760  
4761 +       if (red_copy_xstats(skb, &q->st))
4762 +               goto rtattr_failure;
4763 +
4764         return skb->len;
4765  
4766  rtattr_failure:
4767         skb_trim(skb, b - skb->data);
4768         return -1;
4769  }
4770 -#endif
4771  
4772  static void red_destroy(struct Qdisc *sch)
4773  {
4774 @@ -375,11 +475,9 @@
4775         red_init,
4776         red_reset,
4777         red_destroy,
4778 -       NULL /* red_change */,
4779 +       red_change,
4780  
4781 -#ifdef CONFIG_RTNETLINK
4782         red_dump,
4783 -#endif
4784  };
4785  
4786  
4787 @@ -394,3 +492,4 @@
4788         unregister_qdisc(&red_qdisc_ops);
4789  }
4790  #endif
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
4795 @@ -105,6 +105,7 @@
4796  /* Parameters */
4797         int             perturb_period;
4798         unsigned        quantum;        /* Allotment per round: MUST BE >= MTU */
4799 +       int             limit;
4800  
4801  /* Variables */
4802         struct timer_list perturb_timer;
4803 @@ -275,14 +276,14 @@
4804                         q->tail = x;
4805                 }
4806         }
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++;
4811 -               return 1;
4812 +               return 0;
4813         }
4814  
4815         sfq_drop(sch);
4816 -       return 0;
4817 +       return NET_XMIT_CN;
4818  }
4819  
4820  static int
4821 @@ -310,12 +311,12 @@
4822                         q->tail = x;
4823                 }
4824         }
4825 -       if (++sch->q.qlen < SFQ_DEPTH-1)
4826 -               return 1;
4827 +       if (++sch->q.qlen < q->limit - 1)
4828 +               return 0;
4829  
4830         sch->stats.drops++;
4831         sfq_drop(sch);
4832 -       return 0;
4833 +       return NET_XMIT_CN;
4834  }
4835  
4836  
4837 @@ -387,16 +388,21 @@
4838         if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
4839                 return -EINVAL;
4840  
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;
4845 +       if (ctl->limit)
4846 +               q->limit = min_t(u32, ctl->limit, SFQ_DEPTH);
4847 +
4848 +       while (sch->q.qlen >= q->limit-1)
4849 +               sfq_drop(sch);
4850  
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);
4855         }
4856 -       end_bh_atomic();
4857 +       sch_tree_unlock(sch);
4858         return 0;
4859  }
4860  
4861 @@ -416,6 +422,7 @@
4862                 q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH;
4863                 q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH;
4864         }
4865 +       q->limit = SFQ_DEPTH;
4866         q->max_depth = 0;
4867         q->tail = SFQ_DEPTH;
4868         if (opt == NULL) {
4869 @@ -439,7 +446,6 @@
4870         MOD_DEC_USE_COUNT;
4871  }
4872  
4873 -#ifdef CONFIG_RTNETLINK
4874  static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
4875  {
4876         struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data;
4877 @@ -449,9 +455,9 @@
4878         opt.quantum = q->quantum;
4879         opt.perturb_period = q->perturb_period/HZ;
4880  
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;
4886  
4887         RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
4888  
4889 @@ -461,7 +467,6 @@
4890         skb_trim(skb, b - skb->data);
4891         return -1;
4892  }
4893 -#endif
4894  
4895  struct Qdisc_ops sfq_qdisc_ops =
4896  {
4897 @@ -480,9 +485,7 @@
4898         sfq_destroy,
4899         NULL, /* sfq_change */
4900  
4901 -#ifdef CONFIG_RTNETLINK
4902         sfq_dump,
4903 -#endif
4904  };
4905  
4906  #ifdef MODULE
4907 @@ -496,3 +499,4 @@
4908         unregister_qdisc(&sfq_qdisc_ops);
4909  }
4910  #endif
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
4915 @@ -66,7 +66,7 @@
4916         N(t+delta) = min{B/R, N(t) + delta}
4917  
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:
4922  
4923         N(t_* + 0) = N(t_* - 0) - S/R.
4924 @@ -139,7 +139,7 @@
4925         if ((sch->stats.backlog += skb->len) <= q->limit) {
4926                 sch->stats.bytes += skb->len;
4927                 sch->stats.packets++;
4928 -               return 1;
4929 +               return 0;
4930         }
4931  
4932         /* Drop action: undo the things that we just did,
4933 @@ -155,7 +155,7 @@
4934         if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
4935  #endif
4936                 kfree_skb(skb);
4937 -       return 0;
4938 +       return NET_XMIT_DROP;
4939  }
4940  
4941  static int
4942 @@ -163,7 +163,7 @@
4943  {
4944         __skb_queue_head(&sch->q, skb);
4945         sch->stats.backlog += skb->len;
4946 -       return 1;
4947 +       return 0;
4948  }
4949  
4950  static int
4951 @@ -186,7 +186,7 @@
4952         struct Qdisc *sch = (struct Qdisc*)arg;
4953  
4954         sch->flags &= ~TCQ_F_THROTTLED;
4955 -       qdisc_wakeup(sch->dev);
4956 +       netif_schedule(sch->dev);
4957  }
4958  
4959  static struct sk_buff *
4960 @@ -226,15 +226,13 @@
4961                         return skb;
4962                 }
4963  
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));
4968  
4969                         if (delay == 0)
4970                                 delay = 1;
4971  
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);
4976                 }
4977  
4978                 /* Maybe we have a shorter packet in the queue,
4979 @@ -278,7 +276,7 @@
4980         struct tc_tbf_qopt *qopt;
4981         struct qdisc_rate_table *rtab = NULL;
4982         struct qdisc_rate_table *ptab = NULL;
4983 -       int max_size;
4984 +       int max_size,n;
4985  
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 @@
4989                         goto done;
4990         }
4991  
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;
4996         if (ptab) {
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);
5000 -                       n--;
5001 -               }
5002 +               int size;
5003 +
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;
5008         }
5009 -       if (rtab->data[max_size>>qopt->rate.cell_log] > qopt->buffer)
5010 +       if (max_size < 0)
5011                 goto done;
5012  
5013 -       start_bh_atomic();
5014 +       sch_tree_lock(sch);
5015         q->limit = qopt->limit;
5016         q->mtu = qopt->mtu;
5017         q->max_size = max_size;
5018 @@ -317,7 +318,7 @@
5019         q->ptokens = q->mtu;
5020         rtab = xchg(&q->R_tab, rtab);
5021         ptab = xchg(&q->P_tab, ptab);
5022 -       end_bh_atomic();
5023 +       sch_tree_unlock(sch);
5024         err = 0;
5025  done:
5026         if (rtab)
5027 @@ -362,7 +363,6 @@
5028         MOD_DEC_USE_COUNT;
5029  }
5030  
5031 -#ifdef CONFIG_RTNETLINK
5032  static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb)
5033  {
5034         struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
5035 @@ -390,7 +390,6 @@
5036         skb_trim(skb, b - skb->data);
5037         return -1;
5038  }
5039 -#endif
5040  
5041  struct Qdisc_ops tbf_qdisc_ops =
5042  {
5043 @@ -409,9 +408,7 @@
5044         tbf_destroy,
5045         tbf_change,
5046  
5047 -#ifdef CONFIG_RTNETLINK
5048         tbf_dump,
5049 -#endif
5050  };
5051  
5052  
5053 @@ -426,3 +423,4 @@
5054         unregister_qdisc(&tbf_qdisc_ops);
5055  }
5056  #endif
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
5061 @@ -97,13 +97,13 @@
5062         if (q->q.qlen <= dev->tx_queue_len) {
5063                 sch->stats.bytes += skb->len;
5064                 sch->stats.packets++;
5065 -               return 1;
5066 +               return 0;
5067         }
5068  
5069         __skb_unlink(skb, &q->q);
5070         kfree_skb(skb);
5071         sch->stats.drops++;
5072 -       return 0;
5073 +       return NET_XMIT_DROP;
5074  }
5075  
5076  static int
5077 @@ -112,7 +112,7 @@
5078         struct teql_sched_data *q = (struct teql_sched_data *)sch->data;
5079  
5080         __skb_queue_head(&q->q, skb);
5081 -       return 1;
5082 +       return 0;
5083  }
5084  
5085  static struct sk_buff *
5086 @@ -167,7 +167,9 @@
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);
5093                                         }
5094                                 }
5095                                 skb_queue_purge(&dat->q);
5096 @@ -189,6 +191,9 @@
5097  
5098         if (dev->hard_header_len > m->dev.hard_header_len)
5099                 return -EINVAL;
5100 +
5101 +       if (&m->dev == dev)
5102 +               return -ELOOP;
5103  
5104         q->m = m;
5105  
This page took 0.482486 seconds and 3 git commands to generate.