]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/altq/altq_red.c
Merge from head
[FreeBSD/FreeBSD.git] / sys / net / altq / altq_red.c
1 /*-
2  * Copyright (C) 1997-2003
3  *      Sony Computer Science Laboratories Inc.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 /*-
28  * Copyright (c) 1990-1994 Regents of the University of California.
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  * 1. Redistributions of source code must retain the above copyright
35  *    notice, this list of conditions and the following disclaimer.
36  * 2. Redistributions in binary form must reproduce the above copyright
37  *    notice, this list of conditions and the following disclaimer in the
38  *    documentation and/or other materials provided with the distribution.
39  * 3. All advertising materials mentioning features or use of this software
40  *    must display the following acknowledgement:
41  *      This product includes software developed by the Computer Systems
42  *      Engineering Group at Lawrence Berkeley Laboratory.
43  * 4. Neither the name of the University nor of the Laboratory may be used
44  *    to endorse or promote products derived from this software without
45  *    specific prior written permission.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57  * SUCH DAMAGE.
58  *
59  * $KAME: altq_red.c,v 1.18 2003/09/05 22:40:36 itojun Exp $
60  * $FreeBSD$    
61  */
62
63 #include "opt_altq.h"
64 #include "opt_inet.h"
65 #include "opt_inet6.h"
66 #ifdef ALTQ_RED /* red is enabled by ALTQ_RED option in opt_altq.h */
67
68 #include <sys/param.h>
69 #include <sys/malloc.h>
70 #include <sys/mbuf.h>
71 #include <sys/socket.h>
72 #include <sys/systm.h>
73 #include <sys/errno.h>
74 #if 1 /* ALTQ3_COMPAT */
75 #include <sys/sockio.h>
76 #include <sys/proc.h>
77 #include <sys/kernel.h>
78 #ifdef ALTQ_FLOWVALVE
79 #include <sys/queue.h>
80 #include <sys/time.h>
81 #endif
82 #endif /* ALTQ3_COMPAT */
83
84 #include <net/if.h>
85 #include <net/if_var.h>
86
87 #include <netinet/in.h>
88 #include <netinet/in_systm.h>
89 #include <netinet/ip.h>
90 #ifdef INET6
91 #include <netinet/ip6.h>
92 #endif
93
94 #include <netpfil/pf/pf.h>
95 #include <netpfil/pf/pf_altq.h>
96 #include <netpfil/pf/pf_mtag.h>
97 #include <net/altq/altq.h>
98 #include <net/altq/altq_red.h>
99 #ifdef ALTQ3_COMPAT
100 #include <net/altq/altq_conf.h>
101 #ifdef ALTQ_FLOWVALVE
102 #include <net/altq/altq_flowvalve.h>
103 #endif
104 #endif
105
106 /*
107  * ALTQ/RED (Random Early Detection) implementation using 32-bit
108  * fixed-point calculation.
109  *
110  * written by kjc using the ns code as a reference.
111  * you can learn more about red and ns from Sally's home page at
112  * http://www-nrg.ee.lbl.gov/floyd/
113  *
114  * most of the red parameter values are fixed in this implementation
115  * to prevent fixed-point overflow/underflow.
116  * if you change the parameters, watch out for overflow/underflow!
117  *
118  * the parameters used are recommended values by Sally.
119  * the corresponding ns config looks:
120  *      q_weight=0.00195
121  *      minthresh=5 maxthresh=15 queue-size=60
122  *      linterm=30
123  *      dropmech=drop-tail
124  *      bytes=false (can't be handled by 32-bit fixed-point)
125  *      doubleq=false dqthresh=false
126  *      wait=true
127  */
128 /*
129  * alternative red parameters for a slow link.
130  *
131  * assume the queue length becomes from zero to L and keeps L, it takes
132  * N packets for q_avg to reach 63% of L.
133  * when q_weight is 0.002, N is about 500 packets.
134  * for a slow link like dial-up, 500 packets takes more than 1 minute!
135  * when q_weight is 0.008, N is about 127 packets.
136  * when q_weight is 0.016, N is about 63 packets.
137  * bursts of 50 packets are allowed for 0.002, bursts of 25 packets
138  * are allowed for 0.016.
139  * see Sally's paper for more details.
140  */
141 /* normal red parameters */
142 #define W_WEIGHT        512     /* inverse of weight of EWMA (511/512) */
143                                 /* q_weight = 0.00195 */
144
145 /* red parameters for a slow link */
146 #define W_WEIGHT_1      128     /* inverse of weight of EWMA (127/128) */
147                                 /* q_weight = 0.0078125 */
148
149 /* red parameters for a very slow link (e.g., dialup) */
150 #define W_WEIGHT_2      64      /* inverse of weight of EWMA (63/64) */
151                                 /* q_weight = 0.015625 */
152
153 /* fixed-point uses 12-bit decimal places */
154 #define FP_SHIFT        12      /* fixed-point shift */
155
156 /* red parameters for drop probability */
157 #define INV_P_MAX       10      /* inverse of max drop probability */
158 #define TH_MIN          5       /* min threshold */
159 #define TH_MAX          15      /* max threshold */
160
161 #define RED_LIMIT       60      /* default max queue lenght */
162 #define RED_STATS               /* collect statistics */
163
164 /*
165  * our default policy for forced-drop is drop-tail.
166  * (in altq-1.1.2 or earlier, the default was random-drop.
167  * but it makes more sense to punish the cause of the surge.)
168  * to switch to the random-drop policy, define "RED_RANDOM_DROP".
169  */
170
171 #ifdef ALTQ3_COMPAT
172 #ifdef ALTQ_FLOWVALVE
173 /*
174  * flow-valve is an extention to protect red from unresponsive flows
175  * and to promote end-to-end congestion control.
176  * flow-valve observes the average drop rates of the flows that have
177  * experienced packet drops in the recent past.
178  * when the average drop rate exceeds the threshold, the flow is
179  * blocked by the flow-valve.  the trapped flow should back off
180  * exponentially to escape from the flow-valve.
181  */
182 #ifdef RED_RANDOM_DROP
183 #error "random-drop can't be used with flow-valve!"
184 #endif
185 #endif /* ALTQ_FLOWVALVE */
186
187 /* red_list keeps all red_queue_t's allocated. */
188 static red_queue_t *red_list = NULL;
189
190 #endif /* ALTQ3_COMPAT */
191
192 /* default red parameter values */
193 static int default_th_min = TH_MIN;
194 static int default_th_max = TH_MAX;
195 static int default_inv_pmax = INV_P_MAX;
196
197 #ifdef ALTQ3_COMPAT
198 /* internal function prototypes */
199 static int red_enqueue(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
200 static struct mbuf *red_dequeue(struct ifaltq *, int);
201 static int red_request(struct ifaltq *, int, void *);
202 static void red_purgeq(red_queue_t *);
203 static int red_detach(red_queue_t *);
204 #ifdef ALTQ_FLOWVALVE
205 static __inline struct fve *flowlist_lookup(struct flowvalve *,
206                          struct altq_pktattr *, struct timeval *);
207 static __inline struct fve *flowlist_reclaim(struct flowvalve *,
208                                              struct altq_pktattr *);
209 static __inline void flowlist_move_to_head(struct flowvalve *, struct fve *);
210 static __inline int fv_p2f(struct flowvalve *, int);
211 #if 0 /* XXX: make the compiler happy (fv_alloc unused) */
212 static struct flowvalve *fv_alloc(struct red *);
213 #endif
214 static void fv_destroy(struct flowvalve *);
215 static int fv_checkflow(struct flowvalve *, struct altq_pktattr *,
216                         struct fve **);
217 static void fv_dropbyred(struct flowvalve *fv, struct altq_pktattr *,
218                          struct fve *);
219 #endif
220 #endif /* ALTQ3_COMPAT */
221
222 /*
223  * red support routines
224  */
225 red_t *
226 red_alloc(int weight, int inv_pmax, int th_min, int th_max, int flags,
227    int pkttime)
228 {
229         red_t   *rp;
230         int      w, i;
231         int      npkts_per_sec;
232
233         rp = malloc(sizeof(red_t), M_DEVBUF, M_NOWAIT | M_ZERO);
234         if (rp == NULL)
235                 return (NULL);
236
237         if (weight == 0)
238                 rp->red_weight = W_WEIGHT;
239         else
240                 rp->red_weight = weight;
241
242         /* allocate weight table */
243         rp->red_wtab = wtab_alloc(rp->red_weight);
244         if (rp->red_wtab == NULL) {
245                 free(rp, M_DEVBUF);
246                 return (NULL);
247         }
248
249         rp->red_avg = 0;
250         rp->red_idle = 1;
251
252         if (inv_pmax == 0)
253                 rp->red_inv_pmax = default_inv_pmax;
254         else
255                 rp->red_inv_pmax = inv_pmax;
256         if (th_min == 0)
257                 rp->red_thmin = default_th_min;
258         else
259                 rp->red_thmin = th_min;
260         if (th_max == 0)
261                 rp->red_thmax = default_th_max;
262         else
263                 rp->red_thmax = th_max;
264
265         rp->red_flags = flags;
266
267         if (pkttime == 0)
268                 /* default packet time: 1000 bytes / 10Mbps * 8 * 1000000 */
269                 rp->red_pkttime = 800;
270         else
271                 rp->red_pkttime = pkttime;
272
273         if (weight == 0) {
274                 /* when the link is very slow, adjust red parameters */
275                 npkts_per_sec = 1000000 / rp->red_pkttime;
276                 if (npkts_per_sec < 50) {
277                         /* up to about 400Kbps */
278                         rp->red_weight = W_WEIGHT_2;
279                 } else if (npkts_per_sec < 300) {
280                         /* up to about 2.4Mbps */
281                         rp->red_weight = W_WEIGHT_1;
282                 }
283         }
284
285         /* calculate wshift.  weight must be power of 2 */
286         w = rp->red_weight;
287         for (i = 0; w > 1; i++)
288                 w = w >> 1;
289         rp->red_wshift = i;
290         w = 1 << rp->red_wshift;
291         if (w != rp->red_weight) {
292                 printf("invalid weight value %d for red! use %d\n",
293                        rp->red_weight, w);
294                 rp->red_weight = w;
295         }
296
297         /*
298          * thmin_s and thmax_s are scaled versions of th_min and th_max
299          * to be compared with avg.
300          */
301         rp->red_thmin_s = rp->red_thmin << (rp->red_wshift + FP_SHIFT);
302         rp->red_thmax_s = rp->red_thmax << (rp->red_wshift + FP_SHIFT);
303
304         /*
305          * precompute probability denominator
306          *  probd = (2 * (TH_MAX-TH_MIN) / pmax) in fixed-point
307          */
308         rp->red_probd = (2 * (rp->red_thmax - rp->red_thmin)
309                          * rp->red_inv_pmax) << FP_SHIFT;
310
311         microtime(&rp->red_last);
312         return (rp);
313 }
314
315 void
316 red_destroy(red_t *rp)
317 {
318 #ifdef ALTQ3_COMPAT
319 #ifdef ALTQ_FLOWVALVE
320         if (rp->red_flowvalve != NULL)
321                 fv_destroy(rp->red_flowvalve);
322 #endif
323 #endif /* ALTQ3_COMPAT */
324         wtab_destroy(rp->red_wtab);
325         free(rp, M_DEVBUF);
326 }
327
328 void
329 red_getstats(red_t *rp, struct redstats *sp)
330 {
331         sp->q_avg               = rp->red_avg >> rp->red_wshift;
332         sp->xmit_cnt            = rp->red_stats.xmit_cnt;
333         sp->drop_cnt            = rp->red_stats.drop_cnt;
334         sp->drop_forced         = rp->red_stats.drop_forced;
335         sp->drop_unforced       = rp->red_stats.drop_unforced;
336         sp->marked_packets      = rp->red_stats.marked_packets;
337 }
338
339 int
340 red_addq(red_t *rp, class_queue_t *q, struct mbuf *m,
341     struct altq_pktattr *pktattr)
342 {
343         int avg, droptype;
344         int n;
345 #ifdef ALTQ3_COMPAT
346 #ifdef ALTQ_FLOWVALVE
347         struct fve *fve = NULL;
348
349         if (rp->red_flowvalve != NULL && rp->red_flowvalve->fv_flows > 0)
350                 if (fv_checkflow(rp->red_flowvalve, pktattr, &fve)) {
351                         m_freem(m);
352                         return (-1);
353                 }
354 #endif
355 #endif /* ALTQ3_COMPAT */
356
357         avg = rp->red_avg;
358
359         /*
360          * if we were idle, we pretend that n packets arrived during
361          * the idle period.
362          */
363         if (rp->red_idle) {
364                 struct timeval now;
365                 int t;
366
367                 rp->red_idle = 0;
368                 microtime(&now);
369                 t = (now.tv_sec - rp->red_last.tv_sec);
370                 if (t > 60) {
371                         /*
372                          * being idle for more than 1 minute, set avg to zero.
373                          * this prevents t from overflow.
374                          */
375                         avg = 0;
376                 } else {
377                         t = t * 1000000 + (now.tv_usec - rp->red_last.tv_usec);
378                         n = t / rp->red_pkttime - 1;
379
380                         /* the following line does (avg = (1 - Wq)^n * avg) */
381                         if (n > 0)
382                                 avg = (avg >> FP_SHIFT) *
383                                     pow_w(rp->red_wtab, n);
384                 }
385         }
386
387         /* run estimator. (note: avg is scaled by WEIGHT in fixed-point) */
388         avg += (qlen(q) << FP_SHIFT) - (avg >> rp->red_wshift);
389         rp->red_avg = avg;              /* save the new value */
390
391         /*
392          * red_count keeps a tally of arriving traffic that has not
393          * been dropped.
394          */
395         rp->red_count++;
396
397         /* see if we drop early */
398         droptype = DTYPE_NODROP;
399         if (avg >= rp->red_thmin_s && qlen(q) > 1) {
400                 if (avg >= rp->red_thmax_s) {
401                         /* avg >= th_max: forced drop */
402                         droptype = DTYPE_FORCED;
403                 } else if (rp->red_old == 0) {
404                         /* first exceeds th_min */
405                         rp->red_count = 1;
406                         rp->red_old = 1;
407                 } else if (drop_early((avg - rp->red_thmin_s) >> rp->red_wshift,
408                                       rp->red_probd, rp->red_count)) {
409                         /* mark or drop by red */
410                         if ((rp->red_flags & REDF_ECN) &&
411                             mark_ecn(m, pktattr, rp->red_flags)) {
412                                 /* successfully marked.  do not drop. */
413                                 rp->red_count = 0;
414 #ifdef RED_STATS
415                                 rp->red_stats.marked_packets++;
416 #endif
417                         } else {
418                                 /* unforced drop by red */
419                                 droptype = DTYPE_EARLY;
420                         }
421                 }
422         } else {
423                 /* avg < th_min */
424                 rp->red_old = 0;
425         }
426
427         /*
428          * if the queue length hits the hard limit, it's a forced drop.
429          */
430         if (droptype == DTYPE_NODROP && qlen(q) >= qlimit(q))
431                 droptype = DTYPE_FORCED;
432
433 #ifdef RED_RANDOM_DROP
434         /* if successful or forced drop, enqueue this packet. */
435         if (droptype != DTYPE_EARLY)
436                 _addq(q, m);
437 #else
438         /* if successful, enqueue this packet. */
439         if (droptype == DTYPE_NODROP)
440                 _addq(q, m);
441 #endif
442         if (droptype != DTYPE_NODROP) {
443                 if (droptype == DTYPE_EARLY) {
444                         /* drop the incoming packet */
445 #ifdef RED_STATS
446                         rp->red_stats.drop_unforced++;
447 #endif
448                 } else {
449                         /* forced drop, select a victim packet in the queue. */
450 #ifdef RED_RANDOM_DROP
451                         m = _getq_random(q);
452 #endif
453 #ifdef RED_STATS
454                         rp->red_stats.drop_forced++;
455 #endif
456                 }
457 #ifdef RED_STATS
458                 PKTCNTR_ADD(&rp->red_stats.drop_cnt, m_pktlen(m));
459 #endif
460                 rp->red_count = 0;
461 #ifdef ALTQ3_COMPAT
462 #ifdef ALTQ_FLOWVALVE
463                 if (rp->red_flowvalve != NULL)
464                         fv_dropbyred(rp->red_flowvalve, pktattr, fve);
465 #endif
466 #endif /* ALTQ3_COMPAT */
467                 m_freem(m);
468                 return (-1);
469         }
470         /* successfully queued */
471 #ifdef RED_STATS
472         PKTCNTR_ADD(&rp->red_stats.xmit_cnt, m_pktlen(m));
473 #endif
474         return (0);
475 }
476
477 /*
478  * early-drop probability is calculated as follows:
479  *   prob = p_max * (avg - th_min) / (th_max - th_min)
480  *   prob_a = prob / (2 - count*prob)
481  *          = (avg-th_min) / (2*(th_max-th_min)*inv_p_max - count*(avg-th_min))
482  * here prob_a increases as successive undrop count increases.
483  * (prob_a starts from prob/2, becomes prob when (count == (1 / prob)),
484  * becomes 1 when (count >= (2 / prob))).
485  */
486 int
487 drop_early(int fp_len, int fp_probd, int count)
488 {
489         int     d;              /* denominator of drop-probability */
490
491         d = fp_probd - count * fp_len;
492         if (d <= 0)
493                 /* count exceeds the hard limit: drop or mark */
494                 return (1);
495
496         /*
497          * now the range of d is [1..600] in fixed-point. (when
498          * th_max-th_min=10 and p_max=1/30)
499          * drop probability = (avg - TH_MIN) / d
500          */
501
502         if ((arc4random() % d) < fp_len) {
503                 /* drop or mark */
504                 return (1);
505         }
506         /* no drop/mark */
507         return (0);
508 }
509
510 /*
511  * try to mark CE bit to the packet.
512  *    returns 1 if successfully marked, 0 otherwise.
513  */
514 int
515 mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
516 {
517         struct mbuf     *m0;
518         struct pf_mtag  *at;
519         void            *hdr;
520
521         at = pf_find_mtag(m);
522         if (at != NULL) {
523                 hdr = at->hdr;
524 #ifdef ALTQ3_COMPAT
525         } else if (pktattr != NULL) {
526                 af = pktattr->pattr_af;
527                 hdr = pktattr->pattr_hdr;
528 #endif /* ALTQ3_COMPAT */
529         } else
530                 return (0);
531
532         /* verify that pattr_hdr is within the mbuf data */
533         for (m0 = m; m0 != NULL; m0 = m0->m_next)
534                 if (((caddr_t)hdr >= m0->m_data) &&
535                     ((caddr_t)hdr < m0->m_data + m0->m_len))
536                         break;
537         if (m0 == NULL) {
538                 /* ick, tag info is stale */
539                 return (0);
540         }
541
542         switch (((struct ip *)hdr)->ip_v) {
543         case IPVERSION:
544                 if (flags & REDF_ECN4) {
545                         struct ip *ip = hdr;
546                         u_int8_t otos;
547                         int sum;
548
549                         if (ip->ip_v != 4)
550                                 return (0);     /* version mismatch! */
551
552                         if ((ip->ip_tos & IPTOS_ECN_MASK) == IPTOS_ECN_NOTECT)
553                                 return (0);     /* not-ECT */
554                         if ((ip->ip_tos & IPTOS_ECN_MASK) == IPTOS_ECN_CE)
555                                 return (1);     /* already marked */
556
557                         /*
558                          * ecn-capable but not marked,
559                          * mark CE and update checksum
560                          */
561                         otos = ip->ip_tos;
562                         ip->ip_tos |= IPTOS_ECN_CE;
563                         /*
564                          * update checksum (from RFC1624)
565                          *         HC' = ~(~HC + ~m + m')
566                          */
567                         sum = ~ntohs(ip->ip_sum) & 0xffff;
568                         sum += (~otos & 0xffff) + ip->ip_tos;
569                         sum = (sum >> 16) + (sum & 0xffff);
570                         sum += (sum >> 16);  /* add carry */
571                         ip->ip_sum = htons(~sum & 0xffff);
572                         return (1);
573                 }
574                 break;
575 #ifdef INET6
576         case (IPV6_VERSION >> 4):
577                 if (flags & REDF_ECN6) {
578                         struct ip6_hdr *ip6 = hdr;
579                         u_int32_t flowlabel;
580
581                         flowlabel = ntohl(ip6->ip6_flow);
582                         if ((flowlabel >> 28) != 6)
583                                 return (0);     /* version mismatch! */
584                         if ((flowlabel & (IPTOS_ECN_MASK << 20)) ==
585                             (IPTOS_ECN_NOTECT << 20))
586                                 return (0);     /* not-ECT */
587                         if ((flowlabel & (IPTOS_ECN_MASK << 20)) ==
588                             (IPTOS_ECN_CE << 20))
589                                 return (1);     /* already marked */
590                         /*
591                          * ecn-capable but not marked,  mark CE
592                          */
593                         flowlabel |= (IPTOS_ECN_CE << 20);
594                         ip6->ip6_flow = htonl(flowlabel);
595                         return (1);
596                 }
597                 break;
598 #endif  /* INET6 */
599         }
600
601         /* not marked */
602         return (0);
603 }
604
605 struct mbuf *
606 red_getq(rp, q)
607         red_t *rp;
608         class_queue_t *q;
609 {
610         struct mbuf *m;
611
612         if ((m = _getq(q)) == NULL) {
613                 if (rp->red_idle == 0) {
614                         rp->red_idle = 1;
615                         microtime(&rp->red_last);
616                 }
617                 return NULL;
618         }
619
620         rp->red_idle = 0;
621         return (m);
622 }
623
624 /*
625  * helper routine to calibrate avg during idle.
626  * pow_w(wtab, n) returns (1 - Wq)^n in fixed-point
627  * here Wq = 1/weight and the code assumes Wq is close to zero.
628  *
629  * w_tab[n] holds ((1 - Wq)^(2^n)) in fixed-point.
630  */
631 static struct wtab *wtab_list = NULL;   /* pointer to wtab list */
632
633 struct wtab *
634 wtab_alloc(int weight)
635 {
636         struct wtab     *w;
637         int              i;
638
639         for (w = wtab_list; w != NULL; w = w->w_next)
640                 if (w->w_weight == weight) {
641                         w->w_refcount++;
642                         return (w);
643                 }
644
645         w = malloc(sizeof(struct wtab), M_DEVBUF, M_NOWAIT | M_ZERO);
646         if (w == NULL)
647                 return (NULL);
648         w->w_weight = weight;
649         w->w_refcount = 1;
650         w->w_next = wtab_list;
651         wtab_list = w;
652
653         /* initialize the weight table */
654         w->w_tab[0] = ((weight - 1) << FP_SHIFT) / weight;
655         for (i = 1; i < 32; i++) {
656                 w->w_tab[i] = (w->w_tab[i-1] * w->w_tab[i-1]) >> FP_SHIFT;
657                 if (w->w_tab[i] == 0 && w->w_param_max == 0)
658                         w->w_param_max = 1 << i;
659         }
660
661         return (w);
662 }
663
664 int
665 wtab_destroy(struct wtab *w)
666 {
667         struct wtab     *prev;
668
669         if (--w->w_refcount > 0)
670                 return (0);
671
672         if (wtab_list == w)
673                 wtab_list = w->w_next;
674         else for (prev = wtab_list; prev->w_next != NULL; prev = prev->w_next)
675                 if (prev->w_next == w) {
676                         prev->w_next = w->w_next;
677                         break;
678                 }
679
680         free(w, M_DEVBUF);
681         return (0);
682 }
683
684 int32_t
685 pow_w(struct wtab *w, int n)
686 {
687         int     i, bit;
688         int32_t val;
689
690         if (n >= w->w_param_max)
691                 return (0);
692
693         val = 1 << FP_SHIFT;
694         if (n <= 0)
695                 return (val);
696
697         bit = 1;
698         i = 0;
699         while (n) {
700                 if (n & bit) {
701                         val = (val * w->w_tab[i]) >> FP_SHIFT;
702                         n &= ~bit;
703                 }
704                 i++;
705                 bit <<=  1;
706         }
707         return (val);
708 }
709
710 #ifdef ALTQ3_COMPAT
711 /*
712  * red device interface
713  */
714 altqdev_decl(red);
715
716 int
717 redopen(dev, flag, fmt, p)
718         dev_t dev;
719         int flag, fmt;
720 #if (__FreeBSD_version > 500000)
721         struct thread *p;
722 #else
723         struct proc *p;
724 #endif
725 {
726         /* everything will be done when the queueing scheme is attached. */
727         return 0;
728 }
729
730 int
731 redclose(dev, flag, fmt, p)
732         dev_t dev;
733         int flag, fmt;
734 #if (__FreeBSD_version > 500000)
735         struct thread *p;
736 #else
737         struct proc *p;
738 #endif
739 {
740         red_queue_t *rqp;
741         int err, error = 0;
742
743         while ((rqp = red_list) != NULL) {
744                 /* destroy all */
745                 err = red_detach(rqp);
746                 if (err != 0 && error == 0)
747                         error = err;
748         }
749
750         return error;
751 }
752
753 int
754 redioctl(dev, cmd, addr, flag, p)
755         dev_t dev;
756         ioctlcmd_t cmd;
757         caddr_t addr;
758         int flag;
759 #if (__FreeBSD_version > 500000)
760         struct thread *p;
761 #else
762         struct proc *p;
763 #endif
764 {
765         red_queue_t *rqp;
766         struct red_interface *ifacep;
767         struct ifnet *ifp;
768         int     error = 0;
769
770         /* check super-user privilege */
771         switch (cmd) {
772         case RED_GETSTATS:
773                 break;
774         default:
775 #if (__FreeBSD_version > 700000)
776                 if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
777 #elsif (__FreeBSD_version > 400000)
778                 if ((error = suser(p)) != 0)
779 #else
780                 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
781 #endif
782                         return (error);
783                 break;
784         }
785
786         switch (cmd) {
787
788         case RED_ENABLE:
789                 ifacep = (struct red_interface *)addr;
790                 if ((rqp = altq_lookup(ifacep->red_ifname, ALTQT_RED)) == NULL) {
791                         error = EBADF;
792                         break;
793                 }
794                 error = altq_enable(rqp->rq_ifq);
795                 break;
796
797         case RED_DISABLE:
798                 ifacep = (struct red_interface *)addr;
799                 if ((rqp = altq_lookup(ifacep->red_ifname, ALTQT_RED)) == NULL) {
800                         error = EBADF;
801                         break;
802                 }
803                 error = altq_disable(rqp->rq_ifq);
804                 break;
805
806         case RED_IF_ATTACH:
807                 ifp = ifunit(((struct red_interface *)addr)->red_ifname);
808                 if (ifp == NULL) {
809                         error = ENXIO;
810                         break;
811                 }
812
813                 /* allocate and initialize red_queue_t */
814                 rqp = malloc(sizeof(red_queue_t), M_DEVBUF, M_WAITOK);
815                 if (rqp == NULL) {
816                         error = ENOMEM;
817                         break;
818                 }
819                 bzero(rqp, sizeof(red_queue_t));
820
821                 rqp->rq_q = malloc(sizeof(class_queue_t),
822                        M_DEVBUF, M_WAITOK);
823                 if (rqp->rq_q == NULL) {
824                         free(rqp, M_DEVBUF);
825                         error = ENOMEM;
826                         break;
827                 }
828                 bzero(rqp->rq_q, sizeof(class_queue_t));
829
830                 rqp->rq_red = red_alloc(0, 0, 0, 0, 0, 0);
831                 if (rqp->rq_red == NULL) {
832                         free(rqp->rq_q, M_DEVBUF);
833                         free(rqp, M_DEVBUF);
834                         error = ENOMEM;
835                         break;
836                 }
837
838                 rqp->rq_ifq = &ifp->if_snd;
839                 qtail(rqp->rq_q) = NULL;
840                 qlen(rqp->rq_q) = 0;
841                 qlimit(rqp->rq_q) = RED_LIMIT;
842                 qtype(rqp->rq_q) = Q_RED;
843
844                 /*
845                  * set RED to this ifnet structure.
846                  */
847                 error = altq_attach(rqp->rq_ifq, ALTQT_RED, rqp,
848                                     red_enqueue, red_dequeue, red_request,
849                                     NULL, NULL);
850                 if (error) {
851                         red_destroy(rqp->rq_red);
852                         free(rqp->rq_q, M_DEVBUF);
853                         free(rqp, M_DEVBUF);
854                         break;
855                 }
856
857                 /* add this state to the red list */
858                 rqp->rq_next = red_list;
859                 red_list = rqp;
860                 break;
861
862         case RED_IF_DETACH:
863                 ifacep = (struct red_interface *)addr;
864                 if ((rqp = altq_lookup(ifacep->red_ifname, ALTQT_RED)) == NULL) {
865                         error = EBADF;
866                         break;
867                 }
868                 error = red_detach(rqp);
869                 break;
870
871         case RED_GETSTATS:
872                 do {
873                         struct red_stats *q_stats;
874                         red_t *rp;
875
876                         q_stats = (struct red_stats *)addr;
877                         if ((rqp = altq_lookup(q_stats->iface.red_ifname,
878                                              ALTQT_RED)) == NULL) {
879                                 error = EBADF;
880                                 break;
881                         }
882
883                         q_stats->q_len     = qlen(rqp->rq_q);
884                         q_stats->q_limit   = qlimit(rqp->rq_q);
885
886                         rp = rqp->rq_red;
887                         q_stats->q_avg     = rp->red_avg >> rp->red_wshift;
888                         q_stats->xmit_cnt  = rp->red_stats.xmit_cnt;
889                         q_stats->drop_cnt  = rp->red_stats.drop_cnt;
890                         q_stats->drop_forced   = rp->red_stats.drop_forced;
891                         q_stats->drop_unforced = rp->red_stats.drop_unforced;
892                         q_stats->marked_packets = rp->red_stats.marked_packets;
893
894                         q_stats->weight         = rp->red_weight;
895                         q_stats->inv_pmax       = rp->red_inv_pmax;
896                         q_stats->th_min         = rp->red_thmin;
897                         q_stats->th_max         = rp->red_thmax;
898
899 #ifdef ALTQ_FLOWVALVE
900                         if (rp->red_flowvalve != NULL) {
901                                 struct flowvalve *fv = rp->red_flowvalve;
902                                 q_stats->fv_flows    = fv->fv_flows;
903                                 q_stats->fv_pass     = fv->fv_stats.pass;
904                                 q_stats->fv_predrop  = fv->fv_stats.predrop;
905                                 q_stats->fv_alloc    = fv->fv_stats.alloc;
906                                 q_stats->fv_escape   = fv->fv_stats.escape;
907                         } else {
908 #endif /* ALTQ_FLOWVALVE */
909                                 q_stats->fv_flows    = 0;
910                                 q_stats->fv_pass     = 0;
911                                 q_stats->fv_predrop  = 0;
912                                 q_stats->fv_alloc    = 0;
913                                 q_stats->fv_escape   = 0;
914 #ifdef ALTQ_FLOWVALVE
915                         }
916 #endif /* ALTQ_FLOWVALVE */
917                 } while (/*CONSTCOND*/ 0);
918                 break;
919
920         case RED_CONFIG:
921                 do {
922                         struct red_conf *fc;
923                         red_t *new;
924                         int s, limit;
925
926                         fc = (struct red_conf *)addr;
927                         if ((rqp = altq_lookup(fc->iface.red_ifname,
928                                                ALTQT_RED)) == NULL) {
929                                 error = EBADF;
930                                 break;
931                         }
932                         new = red_alloc(fc->red_weight,
933                                         fc->red_inv_pmax,
934                                         fc->red_thmin,
935                                         fc->red_thmax,
936                                         fc->red_flags,
937                                         fc->red_pkttime);
938                         if (new == NULL) {
939                                 error = ENOMEM;
940                                 break;
941                         }
942
943                         s = splnet();
944                         red_purgeq(rqp);
945                         limit = fc->red_limit;
946                         if (limit < fc->red_thmax)
947                                 limit = fc->red_thmax;
948                         qlimit(rqp->rq_q) = limit;
949                         fc->red_limit = limit;  /* write back the new value */
950
951                         red_destroy(rqp->rq_red);
952                         rqp->rq_red = new;
953
954                         splx(s);
955
956                         /* write back new values */
957                         fc->red_limit = limit;
958                         fc->red_inv_pmax = rqp->rq_red->red_inv_pmax;
959                         fc->red_thmin = rqp->rq_red->red_thmin;
960                         fc->red_thmax = rqp->rq_red->red_thmax;
961
962                 } while (/*CONSTCOND*/ 0);
963                 break;
964
965         case RED_SETDEFAULTS:
966                 do {
967                         struct redparams *rp;
968
969                         rp = (struct redparams *)addr;
970
971                         default_th_min = rp->th_min;
972                         default_th_max = rp->th_max;
973                         default_inv_pmax = rp->inv_pmax;
974                 } while (/*CONSTCOND*/ 0);
975                 break;
976
977         default:
978                 error = EINVAL;
979                 break;
980         }
981         return error;
982 }
983
984 static int
985 red_detach(rqp)
986         red_queue_t *rqp;
987 {
988         red_queue_t *tmp;
989         int error = 0;
990
991         if (ALTQ_IS_ENABLED(rqp->rq_ifq))
992                 altq_disable(rqp->rq_ifq);
993
994         if ((error = altq_detach(rqp->rq_ifq)))
995                 return (error);
996
997         if (red_list == rqp)
998                 red_list = rqp->rq_next;
999         else {
1000                 for (tmp = red_list; tmp != NULL; tmp = tmp->rq_next)
1001                         if (tmp->rq_next == rqp) {
1002                                 tmp->rq_next = rqp->rq_next;
1003                                 break;
1004                         }
1005                 if (tmp == NULL)
1006                         printf("red_detach: no state found in red_list!\n");
1007         }
1008
1009         red_destroy(rqp->rq_red);
1010         free(rqp->rq_q, M_DEVBUF);
1011         free(rqp, M_DEVBUF);
1012         return (error);
1013 }
1014
1015 /*
1016  * enqueue routine:
1017  *
1018  *      returns: 0 when successfully queued.
1019  *               ENOBUFS when drop occurs.
1020  */
1021 static int
1022 red_enqueue(ifq, m, pktattr)
1023         struct ifaltq *ifq;
1024         struct mbuf *m;
1025         struct altq_pktattr *pktattr;
1026 {
1027         red_queue_t *rqp = (red_queue_t *)ifq->altq_disc;
1028
1029         IFQ_LOCK_ASSERT(ifq);
1030
1031         if (red_addq(rqp->rq_red, rqp->rq_q, m, pktattr) < 0)
1032                 return ENOBUFS;
1033         ifq->ifq_len++;
1034         return 0;
1035 }
1036
1037 /*
1038  * dequeue routine:
1039  *      must be called in splimp.
1040  *
1041  *      returns: mbuf dequeued.
1042  *               NULL when no packet is available in the queue.
1043  */
1044
1045 static struct mbuf *
1046 red_dequeue(ifq, op)
1047         struct ifaltq *ifq;
1048         int op;
1049 {
1050         red_queue_t *rqp = (red_queue_t *)ifq->altq_disc;
1051         struct mbuf *m;
1052
1053         IFQ_LOCK_ASSERT(ifq);
1054
1055         if (op == ALTDQ_POLL)
1056                 return qhead(rqp->rq_q);
1057
1058         /* op == ALTDQ_REMOVE */
1059         m =  red_getq(rqp->rq_red, rqp->rq_q);
1060         if (m != NULL)
1061                 ifq->ifq_len--;
1062         return (m);
1063 }
1064
1065 static int
1066 red_request(ifq, req, arg)
1067         struct ifaltq *ifq;
1068         int req;
1069         void *arg;
1070 {
1071         red_queue_t *rqp = (red_queue_t *)ifq->altq_disc;
1072
1073         IFQ_LOCK_ASSERT(ifq);
1074
1075         switch (req) {
1076         case ALTRQ_PURGE:
1077                 red_purgeq(rqp);
1078                 break;
1079         }
1080         return (0);
1081 }
1082
1083 static void
1084 red_purgeq(rqp)
1085         red_queue_t *rqp;
1086 {
1087         _flushq(rqp->rq_q);
1088         if (ALTQ_IS_ENABLED(rqp->rq_ifq))
1089                 rqp->rq_ifq->ifq_len = 0;
1090 }
1091
1092 #ifdef ALTQ_FLOWVALVE
1093
1094 #define FV_PSHIFT       7       /* weight of average drop rate -- 1/128 */
1095 #define FV_PSCALE(x)    ((x) << FV_PSHIFT)
1096 #define FV_PUNSCALE(x)  ((x) >> FV_PSHIFT)
1097 #define FV_FSHIFT       5       /* weight of average fraction -- 1/32 */
1098 #define FV_FSCALE(x)    ((x) << FV_FSHIFT)
1099 #define FV_FUNSCALE(x)  ((x) >> FV_FSHIFT)
1100
1101 #define FV_TIMER        (3 * hz)        /* timer value for garbage collector */
1102 #define FV_FLOWLISTSIZE         64      /* how many flows in flowlist */
1103
1104 #define FV_N                    10      /* update fve_f every FV_N packets */
1105
1106 #define FV_BACKOFFTHRESH        1  /* backoff threshold interval in second */
1107 #define FV_TTHRESH              3  /* time threshold to delete fve */
1108 #define FV_ALPHA                5  /* extra packet count */
1109
1110 #define FV_STATS
1111
1112 #if (__FreeBSD_version > 300000)
1113 #define FV_TIMESTAMP(tp)        getmicrotime(tp)
1114 #else
1115 #define FV_TIMESTAMP(tp)        { (*(tp)) = time; }
1116 #endif
1117
1118 /*
1119  * Brtt table: 127 entry table to convert drop rate (p) to
1120  * the corresponding bandwidth fraction (f)
1121  * the following equation is implemented to use scaled values,
1122  * fve_p and fve_f, in the fixed point format.
1123  *
1124  *   Brtt(p) = 1 /(sqrt(4*p/3) + min(1,3*sqrt(p*6/8)) * p * (1+32 * p*p))
1125  *   f = Brtt(p) / (max_th + alpha)
1126  */
1127 #define BRTT_SIZE       128
1128 #define BRTT_SHIFT      12
1129 #define BRTT_MASK       0x0007f000
1130 #define BRTT_PMAX       (1 << (FV_PSHIFT + FP_SHIFT))
1131
1132 const int brtt_tab[BRTT_SIZE] = {
1133         0, 1262010, 877019, 703694, 598706, 525854, 471107, 427728,
1134         392026, 361788, 335598, 312506, 291850, 273158, 256081, 240361,
1135         225800, 212247, 199585, 187788, 178388, 169544, 161207, 153333,
1136         145888, 138841, 132165, 125836, 119834, 114141, 108739, 103612,
1137         98747, 94129, 89746, 85585, 81637, 77889, 74333, 70957,
1138         67752, 64711, 61824, 59084, 56482, 54013, 51667, 49440,
1139         47325, 45315, 43406, 41591, 39866, 38227, 36667, 35184,
1140         33773, 32430, 31151, 29933, 28774, 27668, 26615, 25611,
1141         24653, 23740, 22868, 22035, 21240, 20481, 19755, 19062,
1142         18399, 17764, 17157, 16576, 16020, 15487, 14976, 14487,
1143         14017, 13567, 13136, 12721, 12323, 11941, 11574, 11222,
1144         10883, 10557, 10243, 9942, 9652, 9372, 9103, 8844,
1145         8594, 8354, 8122, 7898, 7682, 7474, 7273, 7079,
1146         6892, 6711, 6536, 6367, 6204, 6046, 5893, 5746,
1147         5603, 5464, 5330, 5201, 5075, 4954, 4836, 4722,
1148         4611, 4504, 4400, 4299, 4201, 4106, 4014, 3924
1149 };
1150
1151 static __inline struct fve *
1152 flowlist_lookup(fv, pktattr, now)
1153         struct flowvalve *fv;
1154         struct altq_pktattr *pktattr;
1155         struct timeval *now;
1156 {
1157         struct fve *fve;
1158         int flows;
1159         struct ip *ip;
1160 #ifdef INET6
1161         struct ip6_hdr *ip6;
1162 #endif
1163         struct timeval tthresh;
1164
1165         if (pktattr == NULL)
1166                 return (NULL);
1167
1168         tthresh.tv_sec = now->tv_sec - FV_TTHRESH;
1169         flows = 0;
1170         /*
1171          * search the flow list
1172          */
1173         switch (pktattr->pattr_af) {
1174         case AF_INET:
1175                 ip = (struct ip *)pktattr->pattr_hdr;
1176                 TAILQ_FOREACH(fve, &fv->fv_flowlist, fve_lru){
1177                         if (fve->fve_lastdrop.tv_sec == 0)
1178                                 break;
1179                         if (fve->fve_lastdrop.tv_sec < tthresh.tv_sec) {
1180                                 fve->fve_lastdrop.tv_sec = 0;
1181                                 break;
1182                         }
1183                         if (fve->fve_flow.flow_af == AF_INET &&
1184                             fve->fve_flow.flow_ip.ip_src.s_addr ==
1185                             ip->ip_src.s_addr &&
1186                             fve->fve_flow.flow_ip.ip_dst.s_addr ==
1187                             ip->ip_dst.s_addr)
1188                                 return (fve);
1189                         flows++;
1190                 }
1191                 break;
1192 #ifdef INET6
1193         case AF_INET6:
1194                 ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
1195                 TAILQ_FOREACH(fve, &fv->fv_flowlist, fve_lru){
1196                         if (fve->fve_lastdrop.tv_sec == 0)
1197                                 break;
1198                         if (fve->fve_lastdrop.tv_sec < tthresh.tv_sec) {
1199                                 fve->fve_lastdrop.tv_sec = 0;
1200                                 break;
1201                         }
1202                         if (fve->fve_flow.flow_af == AF_INET6 &&
1203                             IN6_ARE_ADDR_EQUAL(&fve->fve_flow.flow_ip6.ip6_src,
1204                                                &ip6->ip6_src) &&
1205                             IN6_ARE_ADDR_EQUAL(&fve->fve_flow.flow_ip6.ip6_dst,
1206                                                &ip6->ip6_dst))
1207                                 return (fve);
1208                         flows++;
1209                 }
1210                 break;
1211 #endif /* INET6 */
1212
1213         default:
1214                 /* unknown protocol.  no drop. */
1215                 return (NULL);
1216         }
1217         fv->fv_flows = flows;   /* save the number of active fve's */
1218         return (NULL);
1219 }
1220
1221 static __inline struct fve *
1222 flowlist_reclaim(fv, pktattr)
1223         struct flowvalve *fv;
1224         struct altq_pktattr *pktattr;
1225 {
1226         struct fve *fve;
1227         struct ip *ip;
1228 #ifdef INET6
1229         struct ip6_hdr *ip6;
1230 #endif
1231
1232         /*
1233          * get an entry from the tail of the LRU list.
1234          */
1235         fve = TAILQ_LAST(&fv->fv_flowlist, fv_flowhead);
1236
1237         switch (pktattr->pattr_af) {
1238         case AF_INET:
1239                 ip = (struct ip *)pktattr->pattr_hdr;
1240                 fve->fve_flow.flow_af = AF_INET;
1241                 fve->fve_flow.flow_ip.ip_src = ip->ip_src;
1242                 fve->fve_flow.flow_ip.ip_dst = ip->ip_dst;
1243                 break;
1244 #ifdef INET6
1245         case AF_INET6:
1246                 ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
1247                 fve->fve_flow.flow_af = AF_INET6;
1248                 fve->fve_flow.flow_ip6.ip6_src = ip6->ip6_src;
1249                 fve->fve_flow.flow_ip6.ip6_dst = ip6->ip6_dst;
1250                 break;
1251 #endif
1252         }
1253
1254         fve->fve_state = Green;
1255         fve->fve_p = 0.0;
1256         fve->fve_f = 0.0;
1257         fve->fve_ifseq = fv->fv_ifseq - 1;
1258         fve->fve_count = 0;
1259
1260         fv->fv_flows++;
1261 #ifdef FV_STATS
1262         fv->fv_stats.alloc++;
1263 #endif
1264         return (fve);
1265 }
1266
1267 static __inline void
1268 flowlist_move_to_head(fv, fve)
1269         struct flowvalve *fv;
1270         struct fve *fve;
1271 {
1272         if (TAILQ_FIRST(&fv->fv_flowlist) != fve) {
1273                 TAILQ_REMOVE(&fv->fv_flowlist, fve, fve_lru);
1274                 TAILQ_INSERT_HEAD(&fv->fv_flowlist, fve, fve_lru);
1275         }
1276 }
1277
1278 #if 0 /* XXX: make the compiler happy (fv_alloc unused) */
1279 /*
1280  * allocate flowvalve structure
1281  */
1282 static struct flowvalve *
1283 fv_alloc(rp)
1284         struct red *rp;
1285 {
1286         struct flowvalve *fv;
1287         struct fve *fve;
1288         int i, num;
1289
1290         num = FV_FLOWLISTSIZE;
1291         fv = malloc(sizeof(struct flowvalve),
1292                M_DEVBUF, M_WAITOK);
1293         if (fv == NULL)
1294                 return (NULL);
1295         bzero(fv, sizeof(struct flowvalve));
1296
1297         fv->fv_fves = malloc(sizeof(struct fve) * num,
1298                M_DEVBUF, M_WAITOK);
1299         if (fv->fv_fves == NULL) {
1300                 free(fv, M_DEVBUF);
1301                 return (NULL);
1302         }
1303         bzero(fv->fv_fves, sizeof(struct fve) * num);
1304
1305         fv->fv_flows = 0;
1306         TAILQ_INIT(&fv->fv_flowlist);
1307         for (i = 0; i < num; i++) {
1308                 fve = &fv->fv_fves[i];
1309                 fve->fve_lastdrop.tv_sec = 0;
1310                 TAILQ_INSERT_TAIL(&fv->fv_flowlist, fve, fve_lru);
1311         }
1312
1313         /* initialize drop rate threshold in scaled fixed-point */
1314         fv->fv_pthresh = (FV_PSCALE(1) << FP_SHIFT) / rp->red_inv_pmax;
1315
1316         /* initialize drop rate to fraction table */
1317         fv->fv_p2ftab = malloc(sizeof(int) * BRTT_SIZE,
1318                M_DEVBUF, M_WAITOK);
1319         if (fv->fv_p2ftab == NULL) {
1320                 free(fv->fv_fves, M_DEVBUF);
1321                 free(fv, M_DEVBUF);
1322                 return (NULL);
1323         }
1324         /*
1325          * create the p2f table.
1326          * (shift is used to keep the precision)
1327          */
1328         for (i = 1; i < BRTT_SIZE; i++) {
1329                 int f;
1330
1331                 f = brtt_tab[i] << 8;
1332                 fv->fv_p2ftab[i] = (f / (rp->red_thmax + FV_ALPHA)) >> 8;
1333         }
1334
1335         return (fv);
1336 }
1337 #endif
1338
1339 static void fv_destroy(fv)
1340         struct flowvalve *fv;
1341 {
1342         free(fv->fv_p2ftab, M_DEVBUF);
1343         free(fv->fv_fves, M_DEVBUF);
1344         free(fv, M_DEVBUF);
1345 }
1346
1347 static __inline int
1348 fv_p2f(fv, p)
1349         struct flowvalve        *fv;
1350         int     p;
1351 {
1352         int val, f;
1353
1354         if (p >= BRTT_PMAX)
1355                 f = fv->fv_p2ftab[BRTT_SIZE-1];
1356         else if ((val = (p & BRTT_MASK)))
1357                 f = fv->fv_p2ftab[(val >> BRTT_SHIFT)];
1358         else
1359                 f = fv->fv_p2ftab[1];
1360         return (f);
1361 }
1362
1363 /*
1364  * check if an arriving packet should be pre-dropped.
1365  * called from red_addq() when a packet arrives.
1366  * returns 1 when the packet should be pre-dropped.
1367  * should be called in splimp.
1368  */
1369 static int
1370 fv_checkflow(fv, pktattr, fcache)
1371         struct flowvalve *fv;
1372         struct altq_pktattr *pktattr;
1373         struct fve **fcache;
1374 {
1375         struct fve *fve;
1376         struct timeval now;
1377
1378         fv->fv_ifseq++;
1379         FV_TIMESTAMP(&now);
1380
1381         if ((fve = flowlist_lookup(fv, pktattr, &now)) == NULL)
1382                 /* no matching entry in the flowlist */
1383                 return (0);
1384
1385         *fcache = fve;
1386
1387         /* update fraction f for every FV_N packets */
1388         if (++fve->fve_count == FV_N) {
1389                 /*
1390                  * f = Wf * N / (fv_ifseq - fve_ifseq) + (1 - Wf) * f
1391                  */
1392                 fve->fve_f =
1393                         (FV_N << FP_SHIFT) / (fv->fv_ifseq - fve->fve_ifseq)
1394                         + fve->fve_f - FV_FUNSCALE(fve->fve_f);
1395                 fve->fve_ifseq = fv->fv_ifseq;
1396                 fve->fve_count = 0;
1397         }
1398
1399         /*
1400          * overpumping test
1401          */
1402         if (fve->fve_state == Green && fve->fve_p > fv->fv_pthresh) {
1403                 int fthresh;
1404
1405                 /* calculate a threshold */
1406                 fthresh = fv_p2f(fv, fve->fve_p);
1407                 if (fve->fve_f > fthresh)
1408                         fve->fve_state = Red;
1409         }
1410
1411         if (fve->fve_state == Red) {
1412                 /*
1413                  * backoff test
1414                  */
1415                 if (now.tv_sec - fve->fve_lastdrop.tv_sec > FV_BACKOFFTHRESH) {
1416                         /* no drop for at least FV_BACKOFFTHRESH sec */
1417                         fve->fve_p = 0;
1418                         fve->fve_state = Green;
1419 #ifdef FV_STATS
1420                         fv->fv_stats.escape++;
1421 #endif
1422                 } else {
1423                         /* block this flow */
1424                         flowlist_move_to_head(fv, fve);
1425                         fve->fve_lastdrop = now;
1426 #ifdef FV_STATS
1427                         fv->fv_stats.predrop++;
1428 #endif
1429                         return (1);
1430                 }
1431         }
1432
1433         /*
1434          * p = (1 - Wp) * p
1435          */
1436         fve->fve_p -= FV_PUNSCALE(fve->fve_p);
1437         if (fve->fve_p < 0)
1438                 fve->fve_p = 0;
1439 #ifdef FV_STATS
1440         fv->fv_stats.pass++;
1441 #endif
1442         return (0);
1443 }
1444
1445 /*
1446  * called from red_addq when a packet is dropped by red.
1447  * should be called in splimp.
1448  */
1449 static void fv_dropbyred(fv, pktattr, fcache)
1450         struct flowvalve *fv;
1451         struct altq_pktattr *pktattr;
1452         struct fve *fcache;
1453 {
1454         struct fve *fve;
1455         struct timeval now;
1456
1457         if (pktattr == NULL)
1458                 return;
1459         FV_TIMESTAMP(&now);
1460
1461         if (fcache != NULL)
1462                 /* the fve of this packet is already cached */
1463                 fve = fcache;
1464         else if ((fve = flowlist_lookup(fv, pktattr, &now)) == NULL)
1465                 fve = flowlist_reclaim(fv, pktattr);
1466
1467         flowlist_move_to_head(fv, fve);
1468
1469         /*
1470          * update p:  the following line cancels the update
1471          *            in fv_checkflow() and calculate
1472          *      p = Wp + (1 - Wp) * p
1473          */
1474         fve->fve_p = (1 << FP_SHIFT) + fve->fve_p;
1475
1476         fve->fve_lastdrop = now;
1477 }
1478
1479 #endif /* ALTQ_FLOWVALVE */
1480
1481 #ifdef KLD_MODULE
1482
1483 static struct altqsw red_sw =
1484         {"red", redopen, redclose, redioctl};
1485
1486 ALTQ_MODULE(altq_red, ALTQT_RED, &red_sw);
1487 MODULE_VERSION(altq_red, 1);
1488
1489 #endif /* KLD_MODULE */
1490 #endif /* ALTQ3_COMPAT */
1491
1492 #endif /* ALTQ_RED */