Major changes:
[ipfw.git] / dummynet / ip_dummynet.c
1 /*-
2  * Copyright (c) 1998-2002 Luigi Rizzo, Universita` di Pisa
3  * Portions Copyright (c) 2000 Akamba Corp.
4  * All rights reserved
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: src/sys/netinet/ip_dummynet.c,v 1.110.2.4 2008/10/31 12:58:12 oleg Exp $");
30
31 #define DUMMYNET_DEBUG
32
33 #include "opt_inet6.h"
34
35 /*
36  * This module implements IP dummynet, a bandwidth limiter/delay emulator
37  * used in conjunction with the ipfw package.
38  * Description of the data structures used is in ip_dummynet.h
39  * Here you mainly find the following blocks of code:
40  *  + variable declarations;
41  *  + heap management functions;
42  *  + scheduler and dummynet functions;
43  *  + configuration and initialization.
44  *
45  * NOTA BENE: critical sections are protected by the "dummynet lock".
46  *
47  * Most important Changes:
48  *
49  * 011004: KLDable
50  * 010124: Fixed WF2Q behaviour
51  * 010122: Fixed spl protection.
52  * 000601: WF2Q support
53  * 000106: large rewrite, use heaps to handle very many pipes.
54  * 980513:      initial release
55  *
56  * include files marked with XXX are probably not needed
57  */
58
59 #include <sys/limits.h>
60 #include <sys/param.h>
61 #include <sys/systm.h>
62 #include <sys/malloc.h>
63 #include <sys/mbuf.h>
64 #include <sys/kernel.h>
65 #include <sys/lock.h>
66 #include <sys/module.h>
67 #include <sys/mutex.h>
68 #include <sys/priv.h>
69 #include <sys/proc.h>
70 #include <sys/socket.h>
71 #include <sys/socketvar.h>
72 #include <sys/time.h>
73 #include <sys/sysctl.h>
74 #include <sys/taskqueue.h>
75 #include <net/if.h>     /* IFNAMSIZ, struct ifaddr, ifq head */
76 #include <net/netisr.h>
77 #include <netinet/in.h>
78 #include <netinet/ip.h>         /* ip_len, ip_off */
79 #include <netinet/ip_fw.h>
80 #include <netinet/ip_dummynet.h>
81 #include <netinet/ip_var.h>     /* ip_output(), IP_FORWARDING */
82
83 #include <netinet/if_ether.h> /* various ether_* routines */
84
85 #include <netinet/ip6.h>       /* for ip6_input, ip6_output prototypes */
86 #include <netinet6/ip6_var.h>
87
88 #include "missing.h"
89
90 /*
91  * We keep a private variable for the simulation time, but we could
92  * probably use an existing one ("softticks" in sys/kern/kern_timeout.c)
93  */
94 static dn_key curr_time = 0 ; /* current simulation time */
95
96 static int dn_hash_size = 64 ;  /* default hash size */
97
98 /* statistics on number of queue searches and search steps */
99 static long searches, search_steps ;
100 static int pipe_expire = 1 ;   /* expire queue if empty */
101 static int dn_max_ratio = 16 ; /* max queues/buckets ratio */
102
103 static long pipe_slot_limit = 100; /* Foot shooting limit for pipe queues. */
104 static long pipe_byte_limit = 1024 * 1024;
105
106 static int red_lookup_depth = 256;      /* RED - default lookup table depth */
107 static int red_avg_pkt_size = 512;      /* RED - default medium packet size */
108 static int red_max_pkt_size = 1500;     /* RED - default max packet size */
109
110 static struct timeval prev_t, t;
111 static long tick_last;                  /* Last tick duration (usec). */
112 static long tick_delta;                 /* Last vs standard tick diff (usec). */
113 static long tick_delta_sum;             /* Accumulated tick difference (usec).*/
114 static long tick_adjustment;            /* Tick adjustments done. */
115 static long tick_lost;                  /* Lost(coalesced) ticks number. */
116 /* Adjusted vs non-adjusted curr_time difference (ticks). */
117 static long tick_diff;
118
119 static int              io_fast;
120 static unsigned long    io_pkt;
121 static unsigned long    io_pkt_fast;
122 static unsigned long    io_pkt_drop;
123
124 /*
125  * Three heaps contain queues and pipes that the scheduler handles:
126  *
127  * ready_heap contains all dn_flow_queue related to fixed-rate pipes.
128  *
129  * wfq_ready_heap contains the pipes associated with WF2Q flows
130  *
131  * extract_heap contains pipes associated with delay lines.
132  *
133  */
134
135 MALLOC_DEFINE(M_DUMMYNET, "dummynet", "dummynet heap");
136
137 static struct dn_heap ready_heap, extract_heap, wfq_ready_heap ;
138
139 static int      heap_init(struct dn_heap *h, int size);
140 static int      heap_insert (struct dn_heap *h, dn_key key1, void *p);
141 static void     heap_extract(struct dn_heap *h, void *obj);
142 static void     transmit_event(struct dn_pipe *pipe, struct mbuf **head,
143                     struct mbuf **tail);
144 static void     ready_event(struct dn_flow_queue *q, struct mbuf **head,
145                     struct mbuf **tail);
146 static void     ready_event_wfq(struct dn_pipe *p, struct mbuf **head,
147                     struct mbuf **tail);
148
149 #define HASHSIZE        16
150 #define HASH(num)       ((((num) >> 8) ^ ((num) >> 4) ^ (num)) & 0x0f)
151 static struct dn_pipe_head      pipehash[HASHSIZE];     /* all pipes */
152 static struct dn_flow_set_head  flowsethash[HASHSIZE];  /* all flowsets */
153
154 static struct callout dn_timeout;
155
156 extern  void (*bridge_dn_p)(struct mbuf *, struct ifnet *);
157
158 #ifdef SYSCTL_NODE
159 SYSCTL_DECL(_net_inet);
160 SYSCTL_DECL(_net_inet_ip);
161
162 SYSCTL_NODE(_net_inet_ip, OID_AUTO, dummynet, CTLFLAG_RW, 0, "Dummynet");
163 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, hash_size,
164     CTLFLAG_RW, &dn_hash_size, 0, "Default hash table size");
165 #if 0 /* curr_time is 64 bit */
166 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, curr_time,
167     CTLFLAG_RD, &curr_time, 0, "Current tick");
168 #endif
169 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, ready_heap,
170     CTLFLAG_RD, &ready_heap.size, 0, "Size of ready heap");
171 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, extract_heap,
172     CTLFLAG_RD, &extract_heap.size, 0, "Size of extract heap");
173 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, searches,
174     CTLFLAG_RD, &searches, 0, "Number of queue searches");
175 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, search_steps,
176     CTLFLAG_RD, &search_steps, 0, "Number of queue search steps");
177 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, expire,
178     CTLFLAG_RW, &pipe_expire, 0, "Expire queue if empty");
179 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, max_chain_len,
180     CTLFLAG_RW, &dn_max_ratio, 0,
181     "Max ratio between dynamic queues and buckets");
182 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, red_lookup_depth,
183     CTLFLAG_RD, &red_lookup_depth, 0, "Depth of RED lookup table");
184 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, red_avg_pkt_size,
185     CTLFLAG_RD, &red_avg_pkt_size, 0, "RED Medium packet size");
186 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, red_max_pkt_size,
187     CTLFLAG_RD, &red_max_pkt_size, 0, "RED Max packet size");
188 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, tick_delta,
189     CTLFLAG_RD, &tick_delta, 0, "Last vs standard tick difference (usec).");
190 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, tick_delta_sum,
191     CTLFLAG_RD, &tick_delta_sum, 0, "Accumulated tick difference (usec).");
192 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, tick_adjustment,
193     CTLFLAG_RD, &tick_adjustment, 0, "Tick adjustments done.");
194 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, tick_diff,
195     CTLFLAG_RD, &tick_diff, 0,
196     "Adjusted vs non-adjusted curr_time difference (ticks).");
197 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, tick_lost,
198     CTLFLAG_RD, &tick_lost, 0,
199     "Number of ticks coalesced by dummynet taskqueue.");
200 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, io_fast,
201     CTLFLAG_RW, &io_fast, 0, "Enable fast dummynet io.");
202 SYSCTL_ULONG(_net_inet_ip_dummynet, OID_AUTO, io_pkt,
203     CTLFLAG_RD, &io_pkt, 0,
204     "Number of packets passed to dummynet.");
205 SYSCTL_ULONG(_net_inet_ip_dummynet, OID_AUTO, io_pkt_fast,
206     CTLFLAG_RD, &io_pkt_fast, 0,
207     "Number of packets bypassed dummynet scheduler.");
208 SYSCTL_ULONG(_net_inet_ip_dummynet, OID_AUTO, io_pkt_drop,
209     CTLFLAG_RD, &io_pkt_drop, 0,
210     "Number of packets dropped by dummynet.");
211 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, pipe_slot_limit,
212     CTLFLAG_RW, &pipe_slot_limit, 0, "Upper limit in slots for pipe queue.");
213 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, pipe_byte_limit,
214     CTLFLAG_RW, &pipe_byte_limit, 0, "Upper limit in bytes for pipe queue.");
215 #endif
216
217 #ifdef DUMMYNET_DEBUG
218 int     dummynet_debug = 0;
219 #ifdef SYSCTL_NODE
220 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, debug, CTLFLAG_RW, &dummynet_debug,
221             0, "control debugging printfs");
222 #endif
223 #define DPRINTF(X)      if (dummynet_debug) printf X
224 #else
225 #define DPRINTF(X)
226 #endif
227
228 static struct task      dn_task;
229 static struct taskqueue *dn_tq = NULL;
230 static void dummynet_task(void *, int);
231
232 #if defined( __linux__ ) || defined( _WIN32 )
233 static DEFINE_SPINLOCK(dummynet_mtx);
234 #else
235 static struct mtx dummynet_mtx;
236 #endif
237 #define DUMMYNET_LOCK_INIT() \
238         mtx_init(&dummynet_mtx, "dummynet", NULL, MTX_DEF)
239 #define DUMMYNET_LOCK_DESTROY() mtx_destroy(&dummynet_mtx)
240 #define DUMMYNET_LOCK()         mtx_lock(&dummynet_mtx)
241 #define DUMMYNET_UNLOCK()       mtx_unlock(&dummynet_mtx)
242 #define DUMMYNET_LOCK_ASSERT()  mtx_assert(&dummynet_mtx, MA_OWNED)
243
244 static int      config_pipe(struct dn_pipe *p);
245 static int      ip_dn_ctl(struct sockopt *sopt);
246
247 static void     dummynet(void *);
248 static void     dummynet_flush(void);
249 static void     dummynet_send(struct mbuf *);
250 void            dummynet_drain(void);
251 static ip_dn_io_t dummynet_io;
252 static void     dn_rule_delete(void *);
253
254 /*
255  * Heap management functions.
256  *
257  * In the heap, first node is element 0. Children of i are 2i+1 and 2i+2.
258  * Some macros help finding parent/children so we can optimize them.
259  *
260  * heap_init() is called to expand the heap when needed.
261  * Increment size in blocks of 16 entries.
262  * XXX failure to allocate a new element is a pretty bad failure
263  * as we basically stall a whole queue forever!!
264  * Returns 1 on error, 0 on success
265  */
266 #define HEAP_FATHER(x) ( ( (x) - 1 ) / 2 )
267 #define HEAP_LEFT(x) ( 2*(x) + 1 )
268 #define HEAP_IS_LEFT(x) ( (x) & 1 )
269 #define HEAP_RIGHT(x) ( 2*(x) + 2 )
270 #define HEAP_SWAP(a, b, buffer) { buffer = a ; a = b ; b = buffer ; }
271 #define HEAP_INCREMENT  15
272
273 static int
274 heap_init(struct dn_heap *h, int new_size)
275 {
276     struct dn_heap_entry *p;
277
278     if (h->size >= new_size ) {
279         printf("dummynet: %s, Bogus call, have %d want %d\n", __func__,
280                 h->size, new_size);
281         return 0 ;
282     }
283     new_size = (new_size + HEAP_INCREMENT ) & ~HEAP_INCREMENT ;
284     p = malloc(new_size * sizeof(*p), M_DUMMYNET, M_NOWAIT);
285     if (p == NULL) {
286         printf("dummynet: %s, resize %d failed\n", __func__, new_size );
287         return 1 ; /* error */
288     }
289     if (h->size > 0) {
290         bcopy(h->p, p, h->size * sizeof(*p) );
291         free(h->p, M_DUMMYNET);
292     }
293     h->p = p ;
294     h->size = new_size ;
295     return 0 ;
296 }
297
298 /*
299  * Insert element in heap. Normally, p != NULL, we insert p in
300  * a new position and bubble up. If p == NULL, then the element is
301  * already in place, and key is the position where to start the
302  * bubble-up.
303  * Returns 1 on failure (cannot allocate new heap entry)
304  *
305  * If offset > 0 the position (index, int) of the element in the heap is
306  * also stored in the element itself at the given offset in bytes.
307  */
308 #define SET_OFFSET(heap, node) \
309     if (heap->offset > 0) \
310             *((int *)((char *)(heap->p[node].object) + heap->offset)) = node ;
311 /*
312  * RESET_OFFSET is used for sanity checks. It sets offset to an invalid value.
313  */
314 #define RESET_OFFSET(heap, node) \
315     if (heap->offset > 0) \
316             *((int *)((char *)(heap->p[node].object) + heap->offset)) = -1 ;
317 static int
318 heap_insert(struct dn_heap *h, dn_key key1, void *p)
319 {
320     int son = h->elements ;
321
322     if (p == NULL)      /* data already there, set starting point */
323         son = key1 ;
324     else {              /* insert new element at the end, possibly resize */
325         son = h->elements ;
326         if (son == h->size) /* need resize... */
327             if (heap_init(h, h->elements+1) )
328                 return 1 ; /* failure... */
329         h->p[son].object = p ;
330         h->p[son].key = key1 ;
331         h->elements++ ;
332     }
333     while (son > 0) {                           /* bubble up */
334         int father = HEAP_FATHER(son) ;
335         struct dn_heap_entry tmp  ;
336
337         if (DN_KEY_LT( h->p[father].key, h->p[son].key ) )
338             break ; /* found right position */
339         /* son smaller than father, swap and repeat */
340         HEAP_SWAP(h->p[son], h->p[father], tmp) ;
341         SET_OFFSET(h, son);
342         son = father ;
343     }
344     SET_OFFSET(h, son);
345     return 0 ;
346 }
347
348 /*
349  * remove top element from heap, or obj if obj != NULL
350  */
351 static void
352 heap_extract(struct dn_heap *h, void *obj)
353 {
354     int child, father, max = h->elements - 1 ;
355
356     if (max < 0) {
357         printf("dummynet: warning, extract from empty heap 0x%p\n", h);
358         return ;
359     }
360     father = 0 ; /* default: move up smallest child */
361     if (obj != NULL) { /* extract specific element, index is at offset */
362         if (h->offset <= 0)
363             panic("dummynet: heap_extract from middle not supported on this heap!!!\n");
364         father = *((int *)((char *)obj + h->offset)) ;
365         if (father < 0 || father >= h->elements) {
366             printf("dummynet: heap_extract, father %d out of bound 0..%d\n",
367                 father, h->elements);
368             panic("dummynet: heap_extract");
369         }
370     }
371     RESET_OFFSET(h, father);
372     child = HEAP_LEFT(father) ;         /* left child */
373     while (child <= max) {              /* valid entry */
374         if (child != max && DN_KEY_LT(h->p[child+1].key, h->p[child].key) )
375             child = child+1 ;           /* take right child, otherwise left */
376         h->p[father] = h->p[child] ;
377         SET_OFFSET(h, father);
378         father = child ;
379         child = HEAP_LEFT(child) ;   /* left child for next loop */
380     }
381     h->elements-- ;
382     if (father != max) {
383         /*
384          * Fill hole with last entry and bubble up, reusing the insert code
385          */
386         h->p[father] = h->p[max] ;
387         heap_insert(h, father, NULL); /* this one cannot fail */
388     }
389 }
390
391 #if 0
392 /*
393  * change object position and update references
394  * XXX this one is never used!
395  */
396 static void
397 heap_move(struct dn_heap *h, dn_key new_key, void *object)
398 {
399     int temp;
400     int i ;
401     int max = h->elements-1 ;
402     struct dn_heap_entry buf ;
403
404     if (h->offset <= 0)
405         panic("cannot move items on this heap");
406
407     i = *((int *)((char *)object + h->offset));
408     if (DN_KEY_LT(new_key, h->p[i].key) ) { /* must move up */
409         h->p[i].key = new_key ;
410         for (; i>0 && DN_KEY_LT(new_key, h->p[(temp = HEAP_FATHER(i))].key) ;
411                  i = temp ) { /* bubble up */
412             HEAP_SWAP(h->p[i], h->p[temp], buf) ;
413             SET_OFFSET(h, i);
414         }
415     } else {            /* must move down */
416         h->p[i].key = new_key ;
417         while ( (temp = HEAP_LEFT(i)) <= max ) { /* found left child */
418             if ((temp != max) && DN_KEY_GT(h->p[temp].key, h->p[temp+1].key))
419                 temp++ ; /* select child with min key */
420             if (DN_KEY_GT(new_key, h->p[temp].key)) { /* go down */
421                 HEAP_SWAP(h->p[i], h->p[temp], buf) ;
422                 SET_OFFSET(h, i);
423             } else
424                 break ;
425             i = temp ;
426         }
427     }
428     SET_OFFSET(h, i);
429 }
430 #endif /* heap_move, unused */
431
432 /*
433  * heapify() will reorganize data inside an array to maintain the
434  * heap property. It is needed when we delete a bunch of entries.
435  */
436 static void
437 heapify(struct dn_heap *h)
438 {
439     int i ;
440
441     for (i = 0 ; i < h->elements ; i++ )
442         heap_insert(h, i , NULL) ;
443 }
444
445 /*
446  * cleanup the heap and free data structure
447  */
448 static void
449 heap_free(struct dn_heap *h)
450 {
451     if (h->size >0 )
452         free(h->p, M_DUMMYNET);
453     bzero(h, sizeof(*h) );
454 }
455
456 /*
457  * --- end of heap management functions ---
458  */
459
460 /*
461  * Return the mbuf tag holding the dummynet state.  As an optimization
462  * this is assumed to be the first tag on the list.  If this turns out
463  * wrong we'll need to search the list.
464  */
465 static struct dn_pkt_tag *
466 dn_tag_get(struct mbuf *m)
467 {
468     struct m_tag *mtag = m_tag_first(m);
469     KASSERT(mtag != NULL &&
470             mtag->m_tag_cookie == MTAG_ABI_COMPAT &&
471             mtag->m_tag_id == PACKET_TAG_DUMMYNET,
472             ("packet on dummynet queue w/o dummynet tag!"));
473     return (struct dn_pkt_tag *)(mtag+1);
474 }
475
476 /*
477  * Scheduler functions:
478  *
479  * transmit_event() is called when the delay-line needs to enter
480  * the scheduler, either because of existing pkts getting ready,
481  * or new packets entering the queue. The event handled is the delivery
482  * time of the packet.
483  *
484  * ready_event() does something similar with fixed-rate queues, and the
485  * event handled is the finish time of the head pkt.
486  *
487  * wfq_ready_event() does something similar with WF2Q queues, and the
488  * event handled is the start time of the head pkt.
489  *
490  * In all cases, we make sure that the data structures are consistent
491  * before passing pkts out, because this might trigger recursive
492  * invocations of the procedures.
493  */
494 static void
495 transmit_event(struct dn_pipe *pipe, struct mbuf **head, struct mbuf **tail)
496 {
497         struct mbuf *m;
498         struct dn_pkt_tag *pkt;
499
500         DUMMYNET_LOCK_ASSERT();
501
502         while ((m = pipe->head) != NULL) {
503                 pkt = dn_tag_get(m);
504                 if (!DN_KEY_LEQ(pkt->output_time, curr_time))
505                         break;
506
507                 pipe->head = m->m_nextpkt;
508                 if (*tail != NULL)
509                         (*tail)->m_nextpkt = m;
510                 else
511                         *head = m;
512                 *tail = m;
513         }
514         if (*tail != NULL)
515                 (*tail)->m_nextpkt = NULL;
516
517         /* If there are leftover packets, put into the heap for next event. */
518         if ((m = pipe->head) != NULL) {
519                 pkt = dn_tag_get(m);
520                 /*
521                  * XXX Should check errors on heap_insert, by draining the
522                  * whole pipe p and hoping in the future we are more successful.
523                  */
524                 heap_insert(&extract_heap, pkt->output_time, pipe);
525         }
526 }
527
528 #ifndef __linux__
529 #define div64(a, b)     ((int64_t)(a) / (int64_t)(b))
530 #endif
531 #define DN_TO_DROP      0xffff
532 /*
533  * Compute how many ticks we have to wait before being able to send
534  * a packet. This is computed as the "wire time" for the packet
535  * (length + extra bits), minus the credit available, scaled to ticks.
536  * Check that the result is not be negative (it could be if we have
537  * too much leftover credit in q->numbytes).
538  */
539 static inline dn_key
540 set_ticks(struct mbuf *m, struct dn_flow_queue *q, struct dn_pipe *p)
541 {
542         int64_t ret;
543
544         ret = div64( (m->m_pkthdr.len * 8 + q->extra_bits) * hz
545                 - q->numbytes + p->bandwidth - 1 , p->bandwidth);
546 #if 0
547         printf("%s %d extra_bits %d numb %d ret %d\n",
548                 __FUNCTION__, __LINE__,
549                 (int)(q->extra_bits & 0xffffffff),
550                 (int)(q->numbytes & 0xffffffff),
551                 (int)(ret & 0xffffffff));
552 #endif
553         if (ret < 0)
554                 ret = 0;
555         return ret;
556 }
557
558 /*
559  * Convert the additional MAC overheads/delays into an equivalent
560  * number of bits for the given data rate. The samples are in milliseconds
561  * so we need to divide by 1000.
562  */
563 static dn_key
564 compute_extra_bits(struct mbuf *pkt, struct dn_pipe *p)
565 {
566         int index;
567         dn_key extra_bits;
568
569         if (!p->samples || p->samples_no == 0)
570                 return 0;
571         index  = random() % p->samples_no;
572         extra_bits = div64((dn_key)p->samples[index] * p->bandwidth, 1000);
573         if (index >= p->loss_level) {
574                 struct dn_pkt_tag *dt = dn_tag_get(pkt);
575                 if (dt)
576                         dt->dn_dir = DN_TO_DROP;
577         }
578         return extra_bits;
579 }
580
581 static void
582 free_pipe(struct dn_pipe *p)
583 {
584         if (p->samples)
585                 free(p->samples, M_DUMMYNET);
586         free(p, M_DUMMYNET);
587 }
588
589 /*
590  * extract pkt from queue, compute output time (could be now)
591  * and put into delay line (p_queue)
592  */
593 static void
594 move_pkt(struct mbuf *pkt, struct dn_flow_queue *q, struct dn_pipe *p,
595     int len)
596 {
597     struct dn_pkt_tag *dt = dn_tag_get(pkt);
598
599     q->head = pkt->m_nextpkt ;
600     q->len-- ;
601     q->len_bytes -= len ;
602
603     dt->output_time = curr_time + p->delay ;
604
605     if (p->head == NULL)
606         p->head = pkt;
607     else
608         p->tail->m_nextpkt = pkt;
609     p->tail = pkt;
610     p->tail->m_nextpkt = NULL;
611 }
612
613 /*
614  * ready_event() is invoked every time the queue must enter the
615  * scheduler, either because the first packet arrives, or because
616  * a previously scheduled event fired.
617  * On invokation, drain as many pkts as possible (could be 0) and then
618  * if there are leftover packets reinsert the pkt in the scheduler.
619  */
620 static void
621 ready_event(struct dn_flow_queue *q, struct mbuf **head, struct mbuf **tail)
622 {
623         struct mbuf *pkt;
624         struct dn_pipe *p = q->fs->pipe;
625         int p_was_empty;
626
627         DUMMYNET_LOCK_ASSERT();
628
629         if (p == NULL) {
630                 printf("dummynet: ready_event- pipe is gone\n");
631                 return;
632         }
633         p_was_empty = (p->head == NULL);
634
635         /*
636          * Schedule fixed-rate queues linked to this pipe:
637          * account for the bw accumulated since last scheduling, then
638          * drain as many pkts as allowed by q->numbytes and move to
639          * the delay line (in p) computing output time.
640          * bandwidth==0 (no limit) means we can drain the whole queue,
641          * setting len_scaled = 0 does the job.
642          */
643         q->numbytes += (curr_time - q->sched_time) * p->bandwidth;
644         while ((pkt = q->head) != NULL) {
645                 int len = pkt->m_pkthdr.len;
646                 dn_key len_scaled = p->bandwidth ? len*8*hz
647                         + q->extra_bits*hz
648                         : 0;
649
650                 if (DN_KEY_GT(len_scaled, q->numbytes))
651                         break;
652                 q->numbytes -= len_scaled;
653                 move_pkt(pkt, q, p, len);
654                 if (q->head)
655                         q->extra_bits = compute_extra_bits(q->head, p);
656         }
657         /*
658          * If we have more packets queued, schedule next ready event
659          * (can only occur when bandwidth != 0, otherwise we would have
660          * flushed the whole queue in the previous loop).
661          * To this purpose we record the current time and compute how many
662          * ticks to go for the finish time of the packet.
663          */
664         if ((pkt = q->head) != NULL) {  /* this implies bandwidth != 0 */
665                 dn_key t = set_ticks(pkt, q, p); /* ticks i have to wait */
666
667                 q->sched_time = curr_time;
668                 heap_insert(&ready_heap, curr_time + t, (void *)q);
669                 /*
670                  * XXX Should check errors on heap_insert, and drain the whole
671                  * queue on error hoping next time we are luckier.
672                  */
673         } else          /* RED needs to know when the queue becomes empty. */
674                 q->q_time = curr_time;
675
676         /*
677          * If the delay line was empty call transmit_event() now.
678          * Otherwise, the scheduler will take care of it.
679          */
680         if (p_was_empty)
681                 transmit_event(p, head, tail);
682 }
683
684 /*
685  * Called when we can transmit packets on WF2Q queues. Take pkts out of
686  * the queues at their start time, and enqueue into the delay line.
687  * Packets are drained until p->numbytes < 0. As long as
688  * len_scaled >= p->numbytes, the packet goes into the delay line
689  * with a deadline p->delay. For the last packet, if p->numbytes < 0,
690  * there is an additional delay.
691  */
692 static void
693 ready_event_wfq(struct dn_pipe *p, struct mbuf **head, struct mbuf **tail)
694 {
695         int p_was_empty = (p->head == NULL);
696         struct dn_heap *sch = &(p->scheduler_heap);
697         struct dn_heap *neh = &(p->not_eligible_heap);
698         int64_t p_numbytes = p->numbytes;
699
700         DUMMYNET_LOCK_ASSERT();
701
702         if (p->if_name[0] == 0)         /* tx clock is simulated */
703                 /*
704                  * Since result may not fit into p->numbytes (32bit) we
705                  * are using 64bit var here.
706                  */
707                 p_numbytes += (curr_time - p->sched_time) * p->bandwidth;
708         else {  /*
709                  * tx clock is for real,
710                  * the ifq must be empty or this is a NOP.
711                  * XXX not supported in Linux
712                  */
713                 if (1) // p->ifp && p->ifp->if_snd.ifq_head != NULL)
714                         return;
715                 else {
716                         DPRINTF(("dummynet: pipe %d ready from %s --\n",
717                             p->pipe_nr, p->if_name));
718                 }
719         }
720
721         /*
722          * While we have backlogged traffic AND credit, we need to do
723          * something on the queue.
724          */
725         while (p_numbytes >= 0 && (sch->elements > 0 || neh->elements > 0)) {
726                 if (sch->elements > 0) {
727                         /* Have some eligible pkts to send out. */
728                         struct dn_flow_queue *q = sch->p[0].object;
729                         struct mbuf *pkt = q->head;
730                         struct dn_flow_set *fs = q->fs;
731                         uint64_t len = pkt->m_pkthdr.len;
732                         int len_scaled = p->bandwidth ? len * 8 * hz : 0;
733
734                         heap_extract(sch, NULL); /* Remove queue from heap. */
735                         p_numbytes -= len_scaled;
736                         move_pkt(pkt, q, p, len);
737
738                         p->V += div64((len << MY_M), p->sum);   /* Update V. */
739                         q->S = q->F;                    /* Update start time. */
740                         if (q->len == 0) {
741                                 /* Flow not backlogged any more. */
742                                 fs->backlogged--;
743                                 heap_insert(&(p->idle_heap), q->F, q);
744                         } else {
745                                 /* Still backlogged. */
746
747                                 /*
748                                  * Update F and position in backlogged queue,
749                                  * then put flow in not_eligible_heap
750                                  * (we will fix this later).
751                                  */
752                                 len = (q->head)->m_pkthdr.len;
753                                 q->F += div64((len << MY_M), fs->weight);
754                                 if (DN_KEY_LEQ(q->S, p->V))
755                                         heap_insert(neh, q->S, q);
756                                 else
757                                         heap_insert(sch, q->F, q);
758                         }
759                 }
760                 /*
761                  * Now compute V = max(V, min(S_i)). Remember that all elements
762                  * in sch have by definition S_i <= V so if sch is not empty,
763                  * V is surely the max and we must not update it. Conversely,
764                  * if sch is empty we only need to look at neh.
765                  */
766                 if (sch->elements == 0 && neh->elements > 0)
767                         p->V = MAX64(p->V, neh->p[0].key);
768                 /* Move from neh to sch any packets that have become eligible */
769                 while (neh->elements > 0 && DN_KEY_LEQ(neh->p[0].key, p->V)) {
770                         struct dn_flow_queue *q = neh->p[0].object;
771                         heap_extract(neh, NULL);
772                         heap_insert(sch, q->F, q);
773                 }
774
775                 if (p->if_name[0] != '\0') { /* Tx clock is from a real thing */
776                         p_numbytes = -1;        /* Mark not ready for I/O. */
777                         break;
778                 }
779         }
780         if (sch->elements == 0 && neh->elements == 0 && p_numbytes >= 0 &&
781             p->idle_heap.elements > 0) {
782                 /*
783                  * No traffic and no events scheduled.
784                  * We can get rid of idle-heap.
785                  */
786                 int i;
787
788                 for (i = 0; i < p->idle_heap.elements; i++) {
789                         struct dn_flow_queue *q = p->idle_heap.p[i].object;
790
791                         q->F = 0;
792                         q->S = q->F + 1;
793                 }
794                 p->sum = 0;
795                 p->V = 0;
796                 p->idle_heap.elements = 0;
797         }
798         /*
799          * If we are getting clocks from dummynet (not a real interface) and
800          * If we are under credit, schedule the next ready event.
801          * Also fix the delivery time of the last packet.
802          */
803         if (p->if_name[0]==0 && p_numbytes < 0) { /* This implies bw > 0. */
804                 dn_key t = 0;           /* Number of ticks i have to wait. */
805
806                 if (p->bandwidth > 0)
807                         t = div64(p->bandwidth - 1 - p_numbytes, p->bandwidth);
808                 dn_tag_get(p->tail)->output_time += t;
809                 p->sched_time = curr_time;
810                 heap_insert(&wfq_ready_heap, curr_time + t, (void *)p);
811                 /*
812                  * XXX Should check errors on heap_insert, and drain the whole
813                  * queue on error hoping next time we are luckier.
814                  */
815         }
816
817         /* Fit (adjust if necessary) 64bit result into 32bit variable. */
818         if (p_numbytes > INT_MAX)
819                 p->numbytes = INT_MAX;
820         else if (p_numbytes < INT_MIN)
821                 p->numbytes = INT_MIN;
822         else
823                 p->numbytes = p_numbytes;
824
825         /*
826          * If the delay line was empty call transmit_event() now.
827          * Otherwise, the scheduler will take care of it.
828          */
829         if (p_was_empty)
830                 transmit_event(p, head, tail);
831 }
832
833 /*
834  * This is called one tick, after previous run. It is used to
835  * schedule next run.
836  */
837 static void
838 dummynet(void * __unused unused)
839 {
840
841         taskqueue_enqueue(dn_tq, &dn_task);
842 }
843
844 /*
845  * The main dummynet processing function.
846  */
847 static void
848 dummynet_task(void *context, int pending)
849 {
850         struct mbuf *head = NULL, *tail = NULL;
851         struct dn_pipe *pipe;
852         struct dn_heap *heaps[3];
853         struct dn_heap *h;
854         void *p;        /* generic parameter to handler */
855         int i;
856
857         DUMMYNET_LOCK();
858
859         heaps[0] = &ready_heap;                 /* fixed-rate queues */
860         heaps[1] = &wfq_ready_heap;             /* wfq queues */
861         heaps[2] = &extract_heap;               /* delay line */
862
863         /* Update number of lost(coalesced) ticks. */
864         tick_lost += pending - 1;
865  
866         getmicrouptime(&t);
867         /* Last tick duration (usec). */
868         tick_last = (t.tv_sec - prev_t.tv_sec) * 1000000 +
869             (t.tv_usec - prev_t.tv_usec);
870         /* Last tick vs standard tick difference (usec). */
871         tick_delta = (tick_last * hz - 1000000) / hz;
872         /* Accumulated tick difference (usec). */
873         tick_delta_sum += tick_delta;
874  
875         prev_t = t;
876  
877         /*
878          * Adjust curr_time if accumulated tick difference greater than
879          * 'standard' tick. Since curr_time should be monotonically increasing,
880          * we do positive adjustment as required and throttle curr_time in
881          * case of negative adjustment.
882          */
883         curr_time++;
884         if (tick_delta_sum - tick >= 0) {
885                 int diff = tick_delta_sum / tick;
886  
887                 curr_time += diff;
888                 tick_diff += diff;
889                 tick_delta_sum %= tick;
890                 tick_adjustment++;
891         } else if (tick_delta_sum + tick <= 0) {
892                 curr_time--;
893                 tick_diff--;
894                 tick_delta_sum += tick;
895                 tick_adjustment++;
896         }
897
898         for (i = 0; i < 3; i++) {
899                 h = heaps[i];
900                 while (h->elements > 0 && DN_KEY_LEQ(h->p[0].key, curr_time)) {
901                         if (h->p[0].key > curr_time)
902                                 printf("dummynet: warning, "
903                                     "heap %d is %d ticks late\n",
904                                     i, (int)(curr_time - h->p[0].key));
905                         /* store a copy before heap_extract */
906                         p = h->p[0].object;
907                         /* need to extract before processing */
908                         heap_extract(h, NULL);
909                         if (i == 0)
910                                 ready_event(p, &head, &tail);
911                         else if (i == 1) {
912                                 struct dn_pipe *pipe = p;
913                                 if (pipe->if_name[0] != '\0')
914                                         printf("dummynet: bad ready_event_wfq "
915                                             "for pipe %s\n", pipe->if_name);
916                                 else
917                                         ready_event_wfq(p, &head, &tail);
918                         } else
919                                 transmit_event(p, &head, &tail);
920                 }
921         }
922
923         /* Sweep pipes trying to expire idle flow_queues. */
924         for (i = 0; i < HASHSIZE; i++)
925                 SLIST_FOREACH(pipe, &pipehash[i], next)
926                         if (pipe->idle_heap.elements > 0 &&
927                             DN_KEY_LT(pipe->idle_heap.p[0].key, pipe->V)) {
928                                 struct dn_flow_queue *q =
929                                     pipe->idle_heap.p[0].object;
930
931                                 heap_extract(&(pipe->idle_heap), NULL);
932                                 /* Mark timestamp as invalid. */
933                                 q->S = q->F + 1;
934                                 pipe->sum -= q->fs->weight;
935                         }
936
937         DUMMYNET_UNLOCK();
938
939         if (head != NULL)
940                 dummynet_send(head);
941
942         callout_reset(&dn_timeout, 1, dummynet, NULL);
943 }
944
945 static void
946 dummynet_send(struct mbuf *m)
947 {
948         struct dn_pkt_tag *pkt;
949         struct mbuf *n;
950         struct ip *ip;
951         int dst;
952
953         for (; m != NULL; m = n) {
954                 n = m->m_nextpkt;
955                 m->m_nextpkt = NULL;
956                 if (m_tag_first(m) == NULL) {
957                         pkt = NULL; /* probably unnecessary */
958                         dst = DN_TO_DROP;
959                 } else {
960                         pkt = dn_tag_get(m);
961                         dst = pkt->dn_dir;
962                 }
963
964                 switch (dst) {
965                 case DN_TO_IP_OUT:
966                         ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
967                         break ;
968                 case DN_TO_IP_IN :
969                         ip = mtod(m, struct ip *);
970 #ifndef __linux__       /* restore net format for FreeBSD */
971                         ip->ip_len = htons(ip->ip_len);
972                         ip->ip_off = htons(ip->ip_off);
973 #endif
974                         netisr_dispatch(NETISR_IP, m);
975                         break;
976 #ifdef INET6
977                 case DN_TO_IP6_IN:
978                         netisr_dispatch(NETISR_IPV6, m);
979                         break;
980
981                 case DN_TO_IP6_OUT:
982                         ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL);
983                         break;
984 #endif
985                 case DN_TO_IFB_FWD:
986                         if (bridge_dn_p != NULL)
987                                 ((*bridge_dn_p)(m, pkt->ifp));
988                         else
989                                 printf("dummynet: if_bridge not loaded\n");
990
991                         break;
992                 case DN_TO_ETH_DEMUX:
993                         /*
994                          * The Ethernet code assumes the Ethernet header is
995                          * contiguous in the first mbuf header.
996                          * Insure this is true.
997                          */
998                         if (m->m_len < ETHER_HDR_LEN &&
999                             (m = m_pullup(m, ETHER_HDR_LEN)) == NULL) {
1000                                 printf("dummynet/ether: pullup failed, "
1001                                     "dropping packet\n");
1002                                 break;
1003                         }
1004                         ether_demux(m->m_pkthdr.rcvif, m);
1005                         break;
1006                 case DN_TO_ETH_OUT:
1007                         ether_output_frame(pkt->ifp, m);
1008                         break;
1009
1010                 case DN_TO_DROP:
1011                         /* drop the packet after some time */
1012 #ifdef __linux__
1013                         netisr_dispatch(-1, m); /* -1 drop the packet */
1014 #else
1015                         m_freem(m);
1016 #endif
1017                         break;
1018
1019                 default:
1020                         printf("dummynet: bad switch %d!\n", pkt->dn_dir);
1021                         m_freem(m);
1022                         break;
1023                 }
1024         }
1025 }
1026
1027 /*
1028  * Unconditionally expire empty queues in case of shortage.
1029  * Returns the number of queues freed.
1030  */
1031 static int
1032 expire_queues(struct dn_flow_set *fs)
1033 {
1034     struct dn_flow_queue *q, *prev ;
1035     int i, initial_elements = fs->rq_elements ;
1036
1037     if (fs->last_expired == time_uptime)
1038         return 0 ;
1039     fs->last_expired = time_uptime ;
1040     for (i = 0 ; i <= fs->rq_size ; i++) /* last one is overflow */
1041         for (prev=NULL, q = fs->rq[i] ; q != NULL ; )
1042             if (q->head != NULL || q->S != q->F+1) {
1043                 prev = q ;
1044                 q = q->next ;
1045             } else { /* entry is idle, expire it */
1046                 struct dn_flow_queue *old_q = q ;
1047
1048                 if (prev != NULL)
1049                     prev->next = q = q->next ;
1050                 else
1051                     fs->rq[i] = q = q->next ;
1052                 fs->rq_elements-- ;
1053                 free(old_q, M_DUMMYNET);
1054             }
1055     return initial_elements - fs->rq_elements ;
1056 }
1057
1058 /*
1059  * If room, create a new queue and put at head of slot i;
1060  * otherwise, create or use the default queue.
1061  */
1062 static struct dn_flow_queue *
1063 create_queue(struct dn_flow_set *fs, int i)
1064 {
1065         struct dn_flow_queue *q;
1066
1067         if (fs->rq_elements > fs->rq_size * dn_max_ratio &&
1068             expire_queues(fs) == 0) {
1069                 /* No way to get room, use or create overflow queue. */
1070                 i = fs->rq_size;
1071                 if (fs->rq[i] != NULL)
1072                     return fs->rq[i];
1073         }
1074         q = malloc(sizeof(*q), M_DUMMYNET, M_NOWAIT | M_ZERO);
1075         if (q == NULL) {
1076                 printf("dummynet: sorry, cannot allocate queue for new flow\n");
1077                 return (NULL);
1078         }
1079         q->fs = fs;
1080         q->hash_slot = i;
1081         q->next = fs->rq[i];
1082         q->S = q->F + 1;        /* hack - mark timestamp as invalid. */
1083         q->numbytes = io_fast ? fs->pipe->bandwidth : 0;
1084         fs->rq[i] = q;
1085         fs->rq_elements++;
1086         return (q);
1087 }
1088
1089 /*
1090  * Given a flow_set and a pkt in last_pkt, find a matching queue
1091  * after appropriate masking. The queue is moved to front
1092  * so that further searches take less time.
1093  */
1094 static struct dn_flow_queue *
1095 find_queue(struct dn_flow_set *fs, struct ipfw_flow_id *id)
1096 {
1097     int i = 0 ; /* we need i and q for new allocations */
1098     struct dn_flow_queue *q, *prev;
1099     int is_v6 = IS_IP6_FLOW_ID(id);
1100
1101     if ( !(fs->flags_fs & DN_HAVE_FLOW_MASK) )
1102         q = fs->rq[0] ;
1103     else {
1104         /* first, do the masking, then hash */
1105         id->dst_port &= fs->flow_mask.dst_port ;
1106         id->src_port &= fs->flow_mask.src_port ;
1107         id->proto &= fs->flow_mask.proto ;
1108         id->flags = 0 ; /* we don't care about this one */
1109         if (is_v6) {
1110             APPLY_MASK(&id->dst_ip6, &fs->flow_mask.dst_ip6);
1111             APPLY_MASK(&id->src_ip6, &fs->flow_mask.src_ip6);
1112             id->flow_id6 &= fs->flow_mask.flow_id6;
1113
1114             i = ((id->dst_ip6.__u6_addr.__u6_addr32[0]) & 0xffff)^
1115                 ((id->dst_ip6.__u6_addr.__u6_addr32[1]) & 0xffff)^
1116                 ((id->dst_ip6.__u6_addr.__u6_addr32[2]) & 0xffff)^
1117                 ((id->dst_ip6.__u6_addr.__u6_addr32[3]) & 0xffff)^
1118
1119                 ((id->dst_ip6.__u6_addr.__u6_addr32[0] >> 15) & 0xffff)^
1120                 ((id->dst_ip6.__u6_addr.__u6_addr32[1] >> 15) & 0xffff)^
1121                 ((id->dst_ip6.__u6_addr.__u6_addr32[2] >> 15) & 0xffff)^
1122                 ((id->dst_ip6.__u6_addr.__u6_addr32[3] >> 15) & 0xffff)^
1123
1124                 ((id->src_ip6.__u6_addr.__u6_addr32[0] << 1) & 0xfffff)^
1125                 ((id->src_ip6.__u6_addr.__u6_addr32[1] << 1) & 0xfffff)^
1126                 ((id->src_ip6.__u6_addr.__u6_addr32[2] << 1) & 0xfffff)^
1127                 ((id->src_ip6.__u6_addr.__u6_addr32[3] << 1) & 0xfffff)^
1128
1129                 ((id->src_ip6.__u6_addr.__u6_addr32[0] << 16) & 0xffff)^
1130                 ((id->src_ip6.__u6_addr.__u6_addr32[1] << 16) & 0xffff)^
1131                 ((id->src_ip6.__u6_addr.__u6_addr32[2] << 16) & 0xffff)^
1132                 ((id->src_ip6.__u6_addr.__u6_addr32[3] << 16) & 0xffff)^
1133
1134                 (id->dst_port << 1) ^ (id->src_port) ^
1135                 (id->proto ) ^
1136                 (id->flow_id6);
1137         } else {
1138             id->dst_ip &= fs->flow_mask.dst_ip ;
1139             id->src_ip &= fs->flow_mask.src_ip ;
1140
1141             i = ( (id->dst_ip) & 0xffff ) ^
1142                 ( (id->dst_ip >> 15) & 0xffff ) ^
1143                 ( (id->src_ip << 1) & 0xffff ) ^
1144                 ( (id->src_ip >> 16 ) & 0xffff ) ^
1145                 (id->dst_port << 1) ^ (id->src_port) ^
1146                 (id->proto );
1147         }
1148         i = i % fs->rq_size ;
1149         /* finally, scan the current list for a match */
1150         searches++ ;
1151         for (prev=NULL, q = fs->rq[i] ; q ; ) {
1152             search_steps++;
1153             if (is_v6 &&
1154                     IN6_ARE_ADDR_EQUAL(&id->dst_ip6,&q->id.dst_ip6) &&  
1155                     IN6_ARE_ADDR_EQUAL(&id->src_ip6,&q->id.src_ip6) &&  
1156                     id->dst_port == q->id.dst_port &&
1157                     id->src_port == q->id.src_port &&
1158                     id->proto == q->id.proto &&
1159                     id->flags == q->id.flags &&
1160                     id->flow_id6 == q->id.flow_id6)
1161                 break ; /* found */
1162
1163             if (!is_v6 && id->dst_ip == q->id.dst_ip &&
1164                     id->src_ip == q->id.src_ip &&
1165                     id->dst_port == q->id.dst_port &&
1166                     id->src_port == q->id.src_port &&
1167                     id->proto == q->id.proto &&
1168                     id->flags == q->id.flags)
1169                 break ; /* found */
1170
1171             /* No match. Check if we can expire the entry */
1172             if (pipe_expire && q->head == NULL && q->S == q->F+1 ) {
1173                 /* entry is idle and not in any heap, expire it */
1174                 struct dn_flow_queue *old_q = q ;
1175
1176                 if (prev != NULL)
1177                     prev->next = q = q->next ;
1178                 else
1179                     fs->rq[i] = q = q->next ;
1180                 fs->rq_elements-- ;
1181                 free(old_q, M_DUMMYNET);
1182                 continue ;
1183             }
1184             prev = q ;
1185             q = q->next ;
1186         }
1187         if (q && prev != NULL) { /* found and not in front */
1188             prev->next = q->next ;
1189             q->next = fs->rq[i] ;
1190             fs->rq[i] = q ;
1191         }
1192     }
1193     if (q == NULL) { /* no match, need to allocate a new entry */
1194         q = create_queue(fs, i);
1195         if (q != NULL)
1196         q->id = *id ;
1197     }
1198     return q ;
1199 }
1200
1201 static int
1202 red_drops(struct dn_flow_set *fs, struct dn_flow_queue *q, int len)
1203 {
1204         /*
1205          * RED algorithm
1206          *
1207          * RED calculates the average queue size (avg) using a low-pass filter
1208          * with an exponential weighted (w_q) moving average:
1209          *      avg  <-  (1-w_q) * avg + w_q * q_size
1210          * where q_size is the queue length (measured in bytes or * packets).
1211          *
1212          * If q_size == 0, we compute the idle time for the link, and set
1213          *      avg = (1 - w_q)^(idle/s)
1214          * where s is the time needed for transmitting a medium-sized packet.
1215          *
1216          * Now, if avg < min_th the packet is enqueued.
1217          * If avg > max_th the packet is dropped. Otherwise, the packet is
1218          * dropped with probability P function of avg.
1219          */
1220
1221         int64_t p_b = 0;
1222
1223         /* Queue in bytes or packets? */
1224         u_int q_size = (fs->flags_fs & DN_QSIZE_IS_BYTES) ?
1225             q->len_bytes : q->len;
1226
1227         DPRINTF(("\ndummynet: %d q: %2u ", (int)curr_time, q_size));
1228
1229         /* Average queue size estimation. */
1230         if (q_size != 0) {
1231                 /* Queue is not empty, avg <- avg + (q_size - avg) * w_q */
1232                 int diff = SCALE(q_size) - q->avg;
1233                 int64_t v = SCALE_MUL((int64_t)diff, (int64_t)fs->w_q);
1234
1235                 q->avg += (int)v;
1236         } else {
1237                 /*
1238                  * Queue is empty, find for how long the queue has been
1239                  * empty and use a lookup table for computing
1240                  * (1 - * w_q)^(idle_time/s) where s is the time to send a
1241                  * (small) packet.
1242                  * XXX check wraps...
1243                  */
1244                 if (q->avg) {
1245                         u_int t = div64(curr_time - q->q_time,
1246                             fs->lookup_step);
1247
1248                         q->avg = (t >= 0 && t < fs->lookup_depth) ?
1249                             SCALE_MUL(q->avg, fs->w_q_lookup[t]) : 0;
1250                 }
1251         }
1252         DPRINTF(("dummynet: avg: %u ", SCALE_VAL(q->avg)));
1253
1254         /* Should i drop? */
1255         if (q->avg < fs->min_th) {
1256                 q->count = -1;
1257                 return (0);     /* accept packet */
1258         }
1259         if (q->avg >= fs->max_th) {     /* average queue >=  max threshold */
1260                 if (fs->flags_fs & DN_IS_GENTLE_RED) {
1261                         /*
1262                          * According to Gentle-RED, if avg is greater than
1263                          * max_th the packet is dropped with a probability
1264                          *       p_b = c_3 * avg - c_4
1265                          * where c_3 = (1 - max_p) / max_th
1266                          *       c_4 = 1 - 2 * max_p
1267                          */
1268                         p_b = SCALE_MUL((int64_t)fs->c_3, (int64_t)q->avg) -
1269                             fs->c_4;
1270                 } else {
1271                         q->count = -1;
1272                         DPRINTF(("dummynet: - drop"));
1273                         return (1);
1274                 }
1275         } else if (q->avg > fs->min_th) {
1276                 /*
1277                  * We compute p_b using the linear dropping function
1278                  *       p_b = c_1 * avg - c_2
1279                  * where c_1 = max_p / (max_th - min_th)
1280                  *       c_2 = max_p * min_th / (max_th - min_th)
1281                  */
1282                 p_b = SCALE_MUL((int64_t)fs->c_1, (int64_t)q->avg) - fs->c_2;
1283         }
1284
1285         if (fs->flags_fs & DN_QSIZE_IS_BYTES)
1286                 p_b = div64(p_b * len, fs->max_pkt_size);
1287         if (++q->count == 0)
1288                 q->random = random() & 0xffff;
1289         else {
1290                 /*
1291                  * q->count counts packets arrived since last drop, so a greater
1292                  * value of q->count means a greater packet drop probability.
1293                  */
1294                 if (SCALE_MUL(p_b, SCALE((int64_t)q->count)) > q->random) {
1295                         q->count = 0;
1296                         DPRINTF(("dummynet: - red drop"));
1297                         /* After a drop we calculate a new random value. */
1298                         q->random = random() & 0xffff;
1299                         return (1);     /* drop */
1300                 }
1301         }
1302         /* End of RED algorithm. */
1303
1304         return (0);     /* accept */
1305 }
1306
1307 static __inline struct dn_flow_set *
1308 locate_flowset(int fs_nr)
1309 {
1310         struct dn_flow_set *fs;
1311
1312         SLIST_FOREACH(fs, &flowsethash[HASH(fs_nr)], next)
1313                 if (fs->fs_nr == fs_nr)
1314                         return (fs);
1315
1316         return (NULL);
1317 }
1318
1319 static __inline struct dn_pipe *
1320 locate_pipe(int pipe_nr)
1321 {
1322         struct dn_pipe *pipe;
1323
1324         SLIST_FOREACH(pipe, &pipehash[HASH(pipe_nr)], next)
1325                 if (pipe->pipe_nr == pipe_nr)
1326                         return (pipe);
1327
1328         return (NULL);
1329 }
1330
1331 /*
1332  * dummynet hook for packets. Below 'pipe' is a pipe or a queue
1333  * depending on whether WF2Q or fixed bw is used.
1334  *
1335  * pipe_nr      pipe or queue the packet is destined for.
1336  * dir          where shall we send the packet after dummynet.
1337  * m            the mbuf with the packet
1338  * ifp          the 'ifp' parameter from the caller.
1339  *              NULL in ip_input, destination interface in ip_output,
1340  * rule         matching rule, in case of multiple passes
1341  */
1342 static int
1343 dummynet_io(struct mbuf **m0, int dir, struct ip_fw_args *fwa)
1344 {
1345         struct mbuf *m = *m0, *head = NULL, *tail = NULL;
1346         struct dn_pkt_tag *pkt;
1347         struct m_tag *mtag;
1348         struct dn_flow_set *fs = NULL;
1349         struct dn_pipe *pipe;
1350         uint64_t len = m->m_pkthdr.len;
1351         struct dn_flow_queue *q = NULL;
1352         int is_pipe;
1353         ipfw_insn *cmd = ACTION_PTR(fwa->rule);
1354
1355         KASSERT(m->m_nextpkt == NULL,
1356             ("dummynet_io: mbuf queue passed to dummynet"));
1357
1358         if (cmd->opcode == O_LOG)
1359                 cmd += F_LEN(cmd);
1360         if (cmd->opcode == O_ALTQ)
1361                 cmd += F_LEN(cmd);
1362         if (cmd->opcode == O_TAG)
1363                 cmd += F_LEN(cmd);
1364         is_pipe = (cmd->opcode == O_PIPE);
1365
1366         DUMMYNET_LOCK();
1367         io_pkt++;
1368         /*
1369          * This is a dummynet rule, so we expect an O_PIPE or O_QUEUE rule.
1370          *
1371          * XXXGL: probably the pipe->fs and fs->pipe logic here
1372          * below can be simplified.
1373          */
1374         if (is_pipe) {
1375                 pipe = locate_pipe(fwa->cookie);
1376                 if (pipe != NULL)
1377                         fs = &(pipe->fs);
1378         } else
1379                 fs = locate_flowset(fwa->cookie);
1380
1381         if (fs == NULL)
1382                 goto dropit;    /* This queue/pipe does not exist! */
1383         pipe = fs->pipe;
1384         if (pipe == NULL) {     /* Must be a queue, try find a matching pipe. */
1385                 pipe = locate_pipe(fs->parent_nr);
1386                 if (pipe != NULL)
1387                         fs->pipe = pipe;
1388                 else {
1389                         printf("dummynet: no pipe %d for queue %d, drop pkt\n",
1390                             fs->parent_nr, fs->fs_nr);
1391                         goto dropit;
1392                 }
1393         }
1394         q = find_queue(fs, &(fwa->f_id));
1395         if (q == NULL)
1396                 goto dropit;            /* Cannot allocate queue. */
1397
1398         /* Update statistics, then check reasons to drop pkt. */
1399         q->tot_bytes += len;
1400         q->tot_pkts++;
1401         if (fs->plr && random() < fs->plr)
1402                 goto dropit;            /* Random pkt drop. */
1403         if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
1404                 if (q->len_bytes > fs->qsize)
1405                         goto dropit;    /* Queue size overflow. */
1406         } else {
1407                 if (q->len >= fs->qsize)
1408                         goto dropit;    /* Queue count overflow. */
1409         }
1410         if (fs->flags_fs & DN_IS_RED && red_drops(fs, q, len))
1411                 goto dropit;
1412
1413         /* XXX expensive to zero, see if we can remove it. */
1414         mtag = m_tag_get(PACKET_TAG_DUMMYNET,
1415             sizeof(struct dn_pkt_tag), M_NOWAIT | M_ZERO);
1416         if (mtag == NULL)
1417                 goto dropit;            /* Cannot allocate packet header. */
1418         m_tag_prepend(m, mtag);         /* Attach to mbuf chain. */
1419
1420         pkt = (struct dn_pkt_tag *)(mtag + 1);
1421         /*
1422          * Ok, i can handle the pkt now...
1423          * Build and enqueue packet + parameters.
1424          */
1425         pkt->rule = fwa->rule;
1426         pkt->dn_dir = dir;
1427
1428         pkt->ifp = fwa->oif;
1429
1430         if (q->head == NULL)
1431                 q->head = m;
1432         else
1433                 q->tail->m_nextpkt = m;
1434         q->tail = m;
1435         q->len++;
1436         q->len_bytes += len;
1437
1438         if (q->head != m)               /* Flow was not idle, we are done. */
1439                 goto done;
1440
1441         if (q->q_time < (uint32_t)curr_time)
1442                 q->numbytes = io_fast ? fs->pipe->bandwidth : 0;
1443         q->q_time = curr_time;
1444
1445         /*
1446          * If we reach this point the flow was previously idle, so we need
1447          * to schedule it. This involves different actions for fixed-rate or
1448          * WF2Q queues.
1449          */
1450         if (is_pipe) {
1451                 /* Fixed-rate queue: just insert into the ready_heap. */
1452                 dn_key t = 0;
1453
1454                 if (pipe->bandwidth) {
1455                         q->extra_bits = compute_extra_bits(m, pipe);
1456                         t = set_ticks(m, q, pipe);
1457                 }
1458                 q->sched_time = curr_time;
1459                 if (t == 0)             /* Must process it now. */
1460                         ready_event(q, &head, &tail);
1461                 else
1462                         heap_insert(&ready_heap, curr_time + t , q);
1463         } else {
1464                 /*
1465                  * WF2Q. First, compute start time S: if the flow was
1466                  * idle (S = F + 1) set S to the virtual time V for the
1467                  * controlling pipe, and update the sum of weights for the pipe;
1468                  * otherwise, remove flow from idle_heap and set S to max(F,V).
1469                  * Second, compute finish time F = S + len / weight.
1470                  * Third, if pipe was idle, update V = max(S, V).
1471                  * Fourth, count one more backlogged flow.
1472                  */
1473                 if (DN_KEY_GT(q->S, q->F)) { /* Means timestamps are invalid. */
1474                         q->S = pipe->V;
1475                         pipe->sum += fs->weight; /* Add weight of new queue. */
1476                 } else {
1477                         heap_extract(&(pipe->idle_heap), q);
1478                         q->S = MAX64(q->F, pipe->V);
1479                 }
1480                 q->F = div64(q->S + (len << MY_M), fs->weight);
1481
1482                 if (pipe->not_eligible_heap.elements == 0 &&
1483                     pipe->scheduler_heap.elements == 0)
1484                         pipe->V = MAX64(q->S, pipe->V);
1485                 fs->backlogged++;
1486                 /*
1487                  * Look at eligibility. A flow is not eligibile if S>V (when
1488                  * this happens, it means that there is some other flow already
1489                  * scheduled for the same pipe, so the scheduler_heap cannot be
1490                  * empty). If the flow is not eligible we just store it in the
1491                  * not_eligible_heap. Otherwise, we store in the scheduler_heap
1492                  * and possibly invoke ready_event_wfq() right now if there is
1493                  * leftover credit.
1494                  * Note that for all flows in scheduler_heap (SCH), S_i <= V,
1495                  * and for all flows in not_eligible_heap (NEH), S_i > V.
1496                  * So when we need to compute max(V, min(S_i)) forall i in
1497                  * SCH+NEH, we only need to look into NEH.
1498                  */
1499                 if (DN_KEY_GT(q->S, pipe->V)) {         /* Not eligible. */
1500                         if (pipe->scheduler_heap.elements == 0)
1501                                 printf("dummynet: ++ ouch! not eligible but empty scheduler!\n");
1502                         heap_insert(&(pipe->not_eligible_heap), q->S, q);
1503                 } else {
1504                         heap_insert(&(pipe->scheduler_heap), q->F, q);
1505                         if (pipe->numbytes >= 0) {       /* Pipe is idle. */
1506                                 if (pipe->scheduler_heap.elements != 1)
1507                                         printf("dummynet: OUCH! pipe should have been idle!\n");
1508                                 DPRINTF(("dummynet: waking up pipe %d at %d\n",
1509                                     pipe->pipe_nr, (int)(q->F >> MY_M)));
1510                                 pipe->sched_time = curr_time;
1511                                 ready_event_wfq(pipe, &head, &tail);
1512                         }
1513                 }
1514         }
1515 done:
1516         if (head == m && dir != DN_TO_IFB_FWD && dir != DN_TO_ETH_DEMUX &&
1517             dir != DN_TO_ETH_OUT) {     /* Fast io. */
1518                 io_pkt_fast++;
1519                 if (m->m_nextpkt != NULL)
1520                         printf("dummynet: fast io: pkt chain detected!\n");
1521                 head = m->m_nextpkt = NULL;
1522         } else
1523                 *m0 = NULL;             /* Normal io. */
1524
1525         DUMMYNET_UNLOCK();
1526         if (head != NULL)
1527                 dummynet_send(head);
1528         return (0);
1529
1530 dropit:
1531         io_pkt_drop++;
1532         if (q)
1533                 q->drops++;
1534         DUMMYNET_UNLOCK();
1535         /*
1536          * set the tag, if present. dn_tag_get cannot fail
1537          * so we need to check first
1538          */
1539         if (m_tag_first(m)) {
1540                 pkt = dn_tag_get(m);
1541                 pkt->dn_dir = DN_TO_DROP;
1542         }
1543         dummynet_send(m);       /* drop the packet */
1544         *m0 = NULL;
1545         return ((fs && (fs->flags_fs & DN_NOERROR)) ? 0 : ENOBUFS);
1546 }
1547
1548 /*
1549  * Below, the rt_unref is only needed when (pkt->dn_dir == DN_TO_IP_OUT)
1550  * Doing this would probably save us the initial bzero of dn_pkt
1551  */
1552 #if defined( __linux__ )
1553 #define DN_FREE_PKT(_m) do {                            \
1554         netisr_dispatch(-1, _m);                        \
1555 } while (0)
1556 #else
1557 #define DN_FREE_PKT(_m) do {                            \
1558         m_freem(_m);                                    \
1559 } while (0)
1560 #endif
1561
1562 /*
1563  * Dispose all packets and flow_queues on a flow_set.
1564  * If all=1, also remove red lookup table and other storage,
1565  * including the descriptor itself.
1566  * For the one in dn_pipe MUST also cleanup ready_heap...
1567  */
1568 static void
1569 purge_flow_set(struct dn_flow_set *fs, int all)
1570 {
1571         struct dn_flow_queue *q, *qn;
1572         int i;
1573
1574         DUMMYNET_LOCK_ASSERT();
1575
1576         for (i = 0; i <= fs->rq_size; i++) {
1577                 for (q = fs->rq[i]; q != NULL; q = qn) {
1578                         struct mbuf *m, *mnext;
1579
1580                         mnext = q->head;
1581                         while ((m = mnext) != NULL) {
1582                                 mnext = m->m_nextpkt;
1583                                 DN_FREE_PKT(m);
1584                         }
1585                         qn = q->next;
1586                         free(q, M_DUMMYNET);
1587                 }
1588                 fs->rq[i] = NULL;
1589         }
1590
1591         fs->rq_elements = 0;
1592         if (all) {
1593                 /* RED - free lookup table. */
1594                 if (fs->w_q_lookup != NULL)
1595                         free(fs->w_q_lookup, M_DUMMYNET);
1596                 if (fs->rq != NULL)
1597                         free(fs->rq, M_DUMMYNET);
1598                 /* If this fs is not part of a pipe, free it. */
1599                 if (fs->pipe == NULL || fs != &(fs->pipe->fs))
1600                         free(fs, M_DUMMYNET);
1601         }
1602 }
1603
1604 /*
1605  * Dispose all packets queued on a pipe (not a flow_set).
1606  * Also free all resources associated to a pipe, which is about
1607  * to be deleted.
1608  */
1609 static void
1610 purge_pipe(struct dn_pipe *pipe)
1611 {
1612     struct mbuf *m, *mnext;
1613
1614     purge_flow_set( &(pipe->fs), 1 );
1615
1616     mnext = pipe->head;
1617     while ((m = mnext) != NULL) {
1618         mnext = m->m_nextpkt;
1619         DN_FREE_PKT(m);
1620     }
1621
1622     heap_free( &(pipe->scheduler_heap) );
1623     heap_free( &(pipe->not_eligible_heap) );
1624     heap_free( &(pipe->idle_heap) );
1625 }
1626
1627 /*
1628  * Delete all pipes and heaps returning memory. Must also
1629  * remove references from all ipfw rules to all pipes.
1630  */
1631 static void
1632 dummynet_flush(void)
1633 {
1634         struct dn_pipe *pipe, *pipe1;
1635         struct dn_flow_set *fs, *fs1;
1636         int i;
1637
1638         DUMMYNET_LOCK();
1639         /* Free heaps so we don't have unwanted events. */
1640         heap_free(&ready_heap);
1641         heap_free(&wfq_ready_heap);
1642         heap_free(&extract_heap);
1643
1644         /*
1645          * Now purge all queued pkts and delete all pipes.
1646          *
1647          * XXXGL: can we merge the for(;;) cycles into one or not?
1648          */
1649         for (i = 0; i < HASHSIZE; i++)
1650                 SLIST_FOREACH_SAFE(fs, &flowsethash[i], next, fs1) {
1651                         SLIST_REMOVE(&flowsethash[i], fs, dn_flow_set, next);
1652                         purge_flow_set(fs, 1);
1653                 }
1654         for (i = 0; i < HASHSIZE; i++)
1655                 SLIST_FOREACH_SAFE(pipe, &pipehash[i], next, pipe1) {
1656                         SLIST_REMOVE(&pipehash[i], pipe, dn_pipe, next);
1657                         purge_pipe(pipe);
1658                         free_pipe(pipe);
1659                 }
1660         DUMMYNET_UNLOCK();
1661 }
1662
1663 extern struct ip_fw *ip_fw_default_rule;
1664 static void
1665 dn_rule_delete_fs(struct dn_flow_set *fs, void *r)
1666 {
1667     int i ;
1668     struct dn_flow_queue *q ;
1669     struct mbuf *m ;
1670
1671     for (i = 0 ; i <= fs->rq_size ; i++) /* last one is ovflow */
1672         for (q = fs->rq[i] ; q ; q = q->next )
1673             for (m = q->head ; m ; m = m->m_nextpkt ) {
1674                 struct dn_pkt_tag *pkt = dn_tag_get(m) ;
1675                 if (pkt->rule == r)
1676                     pkt->rule = ip_fw_default_rule ;
1677             }
1678 }
1679
1680 /*
1681  * When a firewall rule is deleted, scan all queues and remove the pointer
1682  * to the rule from matching packets, making them point to the default rule.
1683  * The pointer is used to reinject packets in case one_pass = 0.
1684  */
1685 void
1686 dn_rule_delete(void *r)
1687 {
1688     struct dn_pipe *pipe;
1689     struct dn_flow_set *fs;
1690     struct dn_pkt_tag *pkt;
1691     struct mbuf *m;
1692     int i;
1693
1694     DUMMYNET_LOCK();
1695     /*
1696      * If the rule references a queue (dn_flow_set), then scan
1697      * the flow set, otherwise scan pipes. Should do either, but doing
1698      * both does not harm.
1699      */
1700     for (i = 0; i < HASHSIZE; i++)
1701         SLIST_FOREACH(fs, &flowsethash[i], next)
1702                 dn_rule_delete_fs(fs, r);
1703
1704     for (i = 0; i < HASHSIZE; i++)
1705         SLIST_FOREACH(pipe, &pipehash[i], next) {
1706                 fs = &(pipe->fs);
1707                 dn_rule_delete_fs(fs, r);
1708                 for (m = pipe->head ; m ; m = m->m_nextpkt ) {
1709                         pkt = dn_tag_get(m);
1710                         if (pkt->rule == r)
1711                                 pkt->rule = ip_fw_default_rule;
1712                 }
1713         }
1714     DUMMYNET_UNLOCK();
1715 }
1716
1717 /*
1718  * setup RED parameters
1719  */
1720 static int
1721 config_red(struct dn_flow_set *p, struct dn_flow_set *x)
1722 {
1723         int i;
1724
1725         x->w_q = p->w_q;
1726         x->min_th = SCALE(p->min_th);
1727         x->max_th = SCALE(p->max_th);
1728         x->max_p = p->max_p;
1729
1730         x->c_1 = p->max_p / (p->max_th - p->min_th);
1731         x->c_2 = SCALE_MUL(x->c_1, SCALE(p->min_th));
1732
1733         if (x->flags_fs & DN_IS_GENTLE_RED) {
1734                 x->c_3 = (SCALE(1) - p->max_p) / p->max_th;
1735                 x->c_4 = SCALE(1) - 2 * p->max_p;
1736         }
1737
1738         /* If the lookup table already exist, free and create it again. */
1739         if (x->w_q_lookup) {
1740                 free(x->w_q_lookup, M_DUMMYNET);
1741                 x->w_q_lookup = NULL;
1742         }
1743         if (red_lookup_depth == 0) {
1744                 printf("\ndummynet: net.inet.ip.dummynet.red_lookup_depth"
1745                     "must be > 0\n");
1746                 free(x, M_DUMMYNET);
1747                 return (EINVAL);
1748         }
1749         x->lookup_depth = red_lookup_depth;
1750         x->w_q_lookup = (u_int *)malloc(x->lookup_depth * sizeof(int),
1751             M_DUMMYNET, M_NOWAIT);
1752         if (x->w_q_lookup == NULL) {
1753                 printf("dummynet: sorry, cannot allocate red lookup table\n");
1754                 free(x, M_DUMMYNET);
1755                 return(ENOSPC);
1756         }
1757
1758         /* Fill the lookup table with (1 - w_q)^x */
1759         x->lookup_step = p->lookup_step;
1760         x->lookup_weight = p->lookup_weight;
1761         x->w_q_lookup[0] = SCALE(1) - x->w_q;
1762
1763         for (i = 1; i < x->lookup_depth; i++)
1764                 x->w_q_lookup[i] =
1765                     SCALE_MUL(x->w_q_lookup[i - 1], x->lookup_weight);
1766
1767         if (red_avg_pkt_size < 1)
1768                 red_avg_pkt_size = 512;
1769         x->avg_pkt_size = red_avg_pkt_size;
1770         if (red_max_pkt_size < 1)
1771                 red_max_pkt_size = 1500;
1772         x->max_pkt_size = red_max_pkt_size;
1773         return (0);
1774 }
1775
1776 static int
1777 alloc_hash(struct dn_flow_set *x, struct dn_flow_set *pfs)
1778 {
1779     if (x->flags_fs & DN_HAVE_FLOW_MASK) {     /* allocate some slots */
1780         int l = pfs->rq_size;
1781
1782         if (l == 0)
1783             l = dn_hash_size;
1784         if (l < 4)
1785             l = 4;
1786         else if (l > DN_MAX_HASH_SIZE)
1787             l = DN_MAX_HASH_SIZE;
1788         x->rq_size = l;
1789     } else                  /* one is enough for null mask */
1790         x->rq_size = 1;
1791     x->rq = malloc((1 + x->rq_size) * sizeof(struct dn_flow_queue *),
1792             M_DUMMYNET, M_NOWAIT | M_ZERO);
1793     if (x->rq == NULL) {
1794         printf("dummynet: sorry, cannot allocate queue\n");
1795         return (ENOMEM);
1796     }
1797     x->rq_elements = 0;
1798     return 0 ;
1799 }
1800
1801 static void
1802 set_fs_parms(struct dn_flow_set *x, struct dn_flow_set *src)
1803 {
1804         x->flags_fs = src->flags_fs;
1805         x->qsize = src->qsize;
1806         x->plr = src->plr;
1807         x->flow_mask = src->flow_mask;
1808         if (x->flags_fs & DN_QSIZE_IS_BYTES) {
1809                 if (x->qsize > pipe_byte_limit)
1810                         x->qsize = 1024 * 1024;
1811         } else {
1812                 if (x->qsize == 0)
1813                         x->qsize = 50;
1814                 if (x->qsize > pipe_slot_limit)
1815                         x->qsize = 50;
1816         }
1817         /* Configuring RED. */
1818         if (x->flags_fs & DN_IS_RED)
1819                 config_red(src, x);     /* XXX should check errors */
1820 }
1821
1822 /*
1823  * Setup pipe or queue parameters.
1824  */
1825 static int
1826 config_pipe(struct dn_pipe *p)
1827 {
1828         struct dn_flow_set *pfs = &(p->fs);
1829         struct dn_flow_queue *q;
1830         int i, error;
1831
1832         /*
1833          * The config program passes parameters as follows:
1834          * bw = bits/second (0 means no limits),
1835          * delay = ms, must be translated into ticks.
1836          * qsize = slots/bytes
1837          */
1838         p->delay = (p->delay * hz) / 1000;
1839         /* We need either a pipe number or a flow_set number. */
1840         if (p->pipe_nr == 0 && pfs->fs_nr == 0)
1841                 return (EINVAL);
1842         if (p->pipe_nr != 0 && pfs->fs_nr != 0)
1843                 return (EINVAL);
1844         if (p->pipe_nr != 0) {                  /* this is a pipe */
1845                 struct dn_pipe *pipe;
1846
1847                 DUMMYNET_LOCK();
1848                 pipe = locate_pipe(p->pipe_nr); /* locate pipe */
1849
1850                 if (pipe == NULL) {             /* new pipe */
1851                         pipe = malloc(sizeof(struct dn_pipe), M_DUMMYNET,
1852                             M_NOWAIT | M_ZERO);
1853                         if (pipe == NULL) {
1854                                 DUMMYNET_UNLOCK();
1855                                 printf("dummynet: no memory for new pipe\n");
1856                                 return (ENOMEM);
1857                         }
1858                         pipe->pipe_nr = p->pipe_nr;
1859                         pipe->fs.pipe = pipe;
1860                         /*
1861                          * idle_heap is the only one from which
1862                          * we extract from the middle.
1863                          */
1864                         pipe->idle_heap.size = pipe->idle_heap.elements = 0;
1865                         pipe->idle_heap.offset =
1866                             offsetof(struct dn_flow_queue, heap_pos);
1867                 } else
1868                         /* Flush accumulated credit for all queues. */
1869                         for (i = 0; i <= pipe->fs.rq_size; i++)
1870                                 for (q = pipe->fs.rq[i]; q; q = q->next)
1871                                         q->numbytes = io_fast ? p->bandwidth : 0;
1872
1873                 pipe->bandwidth = p->bandwidth;
1874                 pipe->numbytes = 0;             /* just in case... */
1875                 bcopy(p->if_name, pipe->if_name, sizeof(p->if_name));
1876                 pipe->ifp = NULL;               /* reset interface ptr */
1877                 pipe->delay = p->delay;
1878                 set_fs_parms(&(pipe->fs), pfs);
1879
1880                 /* Handle changes in the delay profile. */
1881                 if (p->samples_no > 0) {
1882                         if (pipe->samples_no != p->samples_no) {
1883                                 if (pipe->samples != NULL)
1884                                         free(pipe->samples, M_DUMMYNET);
1885                                 pipe->samples =
1886                                     malloc(p->samples_no*sizeof(dn_key),
1887                                         M_DUMMYNET, M_NOWAIT | M_ZERO);
1888                                 if (pipe->samples == NULL) {
1889                                         DUMMYNET_UNLOCK();
1890                                         printf("dummynet: no memory "
1891                                                 "for new samples\n");
1892                                         return (ENOMEM);
1893                                 }
1894                                 pipe->samples_no = p->samples_no;
1895                         }
1896
1897                         strncpy(pipe->name,p->name,sizeof(pipe->name));
1898                         pipe->loss_level = p->loss_level;
1899                         for (i = 0; i<pipe->samples_no; ++i)
1900                                 pipe->samples[i] = p->samples[i];
1901                 } else if (pipe->samples != NULL) {
1902                         free(pipe->samples, M_DUMMYNET);
1903                         pipe->samples = NULL;
1904                         pipe->samples_no = 0;
1905                 }
1906
1907                 if (pipe->fs.rq == NULL) {      /* a new pipe */
1908                         error = alloc_hash(&(pipe->fs), pfs);
1909                         if (error) {
1910                                 DUMMYNET_UNLOCK();
1911                                 free_pipe(pipe);
1912                                 return (error);
1913                         }
1914                         SLIST_INSERT_HEAD(&pipehash[HASH(pipe->pipe_nr)],
1915                             pipe, next);
1916                 }
1917                 DUMMYNET_UNLOCK();
1918         } else {                                /* config queue */
1919                 struct dn_flow_set *fs;
1920
1921                 DUMMYNET_LOCK();
1922                 fs = locate_flowset(pfs->fs_nr); /* locate flow_set */
1923
1924                 if (fs == NULL) {               /* new */
1925                         if (pfs->parent_nr == 0) { /* need link to a pipe */
1926                                 DUMMYNET_UNLOCK();
1927                                 return (EINVAL);
1928                         }
1929                         fs = malloc(sizeof(struct dn_flow_set), M_DUMMYNET,
1930                             M_NOWAIT | M_ZERO);
1931                         if (fs == NULL) {
1932                                 DUMMYNET_UNLOCK();
1933                                 printf(
1934                                     "dummynet: no memory for new flow_set\n");
1935                                 return (ENOMEM);
1936                         }
1937                         fs->fs_nr = pfs->fs_nr;
1938                         fs->parent_nr = pfs->parent_nr;
1939                         fs->weight = pfs->weight;
1940                         if (fs->weight == 0)
1941                                 fs->weight = 1;
1942                         else if (fs->weight > 100)
1943                                 fs->weight = 100;
1944                 } else {
1945                         /*
1946                          * Change parent pipe not allowed;
1947                          * must delete and recreate.
1948                          */
1949                         if (pfs->parent_nr != 0 &&
1950                             fs->parent_nr != pfs->parent_nr) {
1951                                 DUMMYNET_UNLOCK();
1952                                 return (EINVAL);
1953                         }
1954                 }
1955
1956                 set_fs_parms(fs, pfs);
1957
1958                 if (fs->rq == NULL) {           /* a new flow_set */
1959                         error = alloc_hash(fs, pfs);
1960                         if (error) {
1961                                 DUMMYNET_UNLOCK();
1962                                 free(fs, M_DUMMYNET);
1963                                 return (error);
1964                         }
1965                         SLIST_INSERT_HEAD(&flowsethash[HASH(fs->fs_nr)],
1966                             fs, next);
1967                 }
1968                 DUMMYNET_UNLOCK();
1969         }
1970         return (0);
1971 }
1972
1973 /*
1974  * Helper function to remove from a heap queues which are linked to
1975  * a flow_set about to be deleted.
1976  */
1977 static void
1978 fs_remove_from_heap(struct dn_heap *h, struct dn_flow_set *fs)
1979 {
1980     int i = 0, found = 0 ;
1981     for (; i < h->elements ;)
1982         if ( ((struct dn_flow_queue *)h->p[i].object)->fs == fs) {
1983             h->elements-- ;
1984             h->p[i] = h->p[h->elements] ;
1985             found++ ;
1986         } else
1987             i++ ;
1988     if (found)
1989         heapify(h);
1990 }
1991
1992 /*
1993  * helper function to remove a pipe from a heap (can be there at most once)
1994  */
1995 static void
1996 pipe_remove_from_heap(struct dn_heap *h, struct dn_pipe *p)
1997 {
1998     if (h->elements > 0) {
1999         int i = 0 ;
2000         for (i=0; i < h->elements ; i++ ) {
2001             if (h->p[i].object == p) { /* found it */
2002                 h->elements-- ;
2003                 h->p[i] = h->p[h->elements] ;
2004                 heapify(h);
2005                 break ;
2006             }
2007         }
2008     }
2009 }
2010
2011 /*
2012  * drain all queues. Called in case of severe mbuf shortage.
2013  */
2014 void
2015 dummynet_drain(void)
2016 {
2017     struct dn_flow_set *fs;
2018     struct dn_pipe *pipe;
2019     struct mbuf *m, *mnext;
2020     int i;
2021
2022     DUMMYNET_LOCK_ASSERT();
2023
2024     heap_free(&ready_heap);
2025     heap_free(&wfq_ready_heap);
2026     heap_free(&extract_heap);
2027     /* remove all references to this pipe from flow_sets */
2028     for (i = 0; i < HASHSIZE; i++)
2029         SLIST_FOREACH(fs, &flowsethash[i], next)
2030                 purge_flow_set(fs, 0);
2031
2032     for (i = 0; i < HASHSIZE; i++) {
2033         SLIST_FOREACH(pipe, &pipehash[i], next) {
2034                 purge_flow_set(&(pipe->fs), 0);
2035
2036                 mnext = pipe->head;
2037                 while ((m = mnext) != NULL) {
2038                         mnext = m->m_nextpkt;
2039                         DN_FREE_PKT(m);
2040                 }
2041                 pipe->head = pipe->tail = NULL;
2042         }
2043     }
2044 }
2045
2046 /*
2047  * Fully delete a pipe or a queue, cleaning up associated info.
2048  */
2049 static int
2050 delete_pipe(struct dn_pipe *p)
2051 {
2052
2053     if (p->pipe_nr == 0 && p->fs.fs_nr == 0)
2054         return EINVAL ;
2055     if (p->pipe_nr != 0 && p->fs.fs_nr != 0)
2056         return EINVAL ;
2057     if (p->pipe_nr != 0) { /* this is an old-style pipe */
2058         struct dn_pipe *pipe;
2059         struct dn_flow_set *fs;
2060         int i;
2061
2062         DUMMYNET_LOCK();
2063         pipe = locate_pipe(p->pipe_nr); /* locate pipe */
2064
2065         if (pipe == NULL) {
2066             DUMMYNET_UNLOCK();
2067             return (ENOENT);    /* not found */
2068         }
2069
2070         /* Unlink from list of pipes. */
2071         SLIST_REMOVE(&pipehash[HASH(pipe->pipe_nr)], pipe, dn_pipe, next);
2072
2073         /* Remove all references to this pipe from flow_sets. */
2074         for (i = 0; i < HASHSIZE; i++)
2075             SLIST_FOREACH(fs, &flowsethash[i], next)
2076                 if (fs->pipe == pipe) {
2077                         printf("dummynet: ++ ref to pipe %d from fs %d\n",
2078                             p->pipe_nr, fs->fs_nr);
2079                         fs->pipe = NULL ;
2080                         purge_flow_set(fs, 0);
2081                 }
2082         fs_remove_from_heap(&ready_heap, &(pipe->fs));
2083         purge_pipe(pipe); /* remove all data associated to this pipe */
2084         /* remove reference to here from extract_heap and wfq_ready_heap */
2085         pipe_remove_from_heap(&extract_heap, pipe);
2086         pipe_remove_from_heap(&wfq_ready_heap, pipe);
2087         DUMMYNET_UNLOCK();
2088
2089         free_pipe(pipe);
2090     } else { /* this is a WF2Q queue (dn_flow_set) */
2091         struct dn_flow_set *fs;
2092
2093         DUMMYNET_LOCK();
2094         fs = locate_flowset(p->fs.fs_nr); /* locate set */
2095
2096         if (fs == NULL) {
2097             DUMMYNET_UNLOCK();
2098             return (ENOENT); /* not found */
2099         }
2100
2101         /* Unlink from list of flowsets. */
2102         SLIST_REMOVE( &flowsethash[HASH(fs->fs_nr)], fs, dn_flow_set, next);
2103
2104         if (fs->pipe != NULL) {
2105             /* Update total weight on parent pipe and cleanup parent heaps. */
2106             fs->pipe->sum -= fs->weight * fs->backlogged ;
2107             fs_remove_from_heap(&(fs->pipe->not_eligible_heap), fs);
2108             fs_remove_from_heap(&(fs->pipe->scheduler_heap), fs);
2109 #if 1   /* XXX should i remove from idle_heap as well ? */
2110             fs_remove_from_heap(&(fs->pipe->idle_heap), fs);
2111 #endif
2112         }
2113         purge_flow_set(fs, 1);
2114         DUMMYNET_UNLOCK();
2115     }
2116     return 0 ;
2117 }
2118
2119 /*
2120  * helper function used to copy data from kernel in DUMMYNET_GET
2121  */
2122 static char *
2123 dn_copy_set(struct dn_flow_set *set, char *bp)
2124 {
2125     int i, copied = 0 ;
2126     struct dn_flow_queue *q, *qp = (struct dn_flow_queue *)bp;
2127
2128     DUMMYNET_LOCK_ASSERT();
2129
2130     for (i = 0 ; i <= set->rq_size ; i++)
2131         for (q = set->rq[i] ; q ; q = q->next, qp++ ) {
2132             if (q->hash_slot != i)
2133                 printf("dummynet: ++ at %d: wrong slot (have %d, "
2134                     "should be %d)\n", copied, q->hash_slot, i);
2135             if (q->fs != set)
2136                 printf("dummynet: ++ at %d: wrong fs ptr (have %p, should be %p)\n",
2137                         i, q->fs, set);
2138             copied++ ;
2139             bcopy(q, qp, sizeof( *q ) );
2140             /* cleanup pointers */
2141             qp->next = NULL ;
2142             qp->head = qp->tail = NULL ;
2143             qp->fs = NULL ;
2144         }
2145     if (copied != set->rq_elements)
2146         printf("dummynet: ++ wrong count, have %d should be %d\n",
2147             copied, set->rq_elements);
2148     return (char *)qp ;
2149 }
2150
2151 static size_t
2152 dn_calc_size(void)
2153 {
2154     struct dn_flow_set *fs;
2155     struct dn_pipe *pipe;
2156     size_t size = 0;
2157     int i;
2158
2159     DUMMYNET_LOCK_ASSERT();
2160     /*
2161      * Compute size of data structures: list of pipes and flow_sets.
2162      */
2163     for (i = 0; i < HASHSIZE; i++) {
2164         SLIST_FOREACH(pipe, &pipehash[i], next)
2165                 size += sizeof(*pipe) +
2166                     pipe->fs.rq_elements * sizeof(struct dn_flow_queue);
2167         SLIST_FOREACH(fs, &flowsethash[i], next)
2168                 size += sizeof (*fs) +
2169                     fs->rq_elements * sizeof(struct dn_flow_queue);
2170     }
2171     return size;
2172 }
2173
2174 static int
2175 dummynet_get(struct sockopt *sopt)
2176 {
2177     char *buf, *bp ; /* bp is the "copy-pointer" */
2178     size_t size ;
2179     struct dn_flow_set *fs;
2180     struct dn_pipe *pipe;
2181     int error=0, i ;
2182
2183     /* XXX lock held too long */
2184     DUMMYNET_LOCK();
2185     /*
2186      * XXX: Ugly, but we need to allocate memory with M_WAITOK flag and we
2187      *      cannot use this flag while holding a mutex.
2188      */
2189     for (i = 0; i < 10; i++) {
2190         size = dn_calc_size();
2191         DUMMYNET_UNLOCK();
2192         buf = malloc(size, M_TEMP, M_WAITOK);
2193         DUMMYNET_LOCK();
2194         if (size == dn_calc_size())
2195                 break;
2196         free(buf, M_TEMP);
2197         buf = NULL;
2198     }
2199     if (buf == NULL) {
2200         DUMMYNET_UNLOCK();
2201         return ENOBUFS ;
2202     }
2203     bp = buf;
2204     for (i = 0; i < HASHSIZE; i++) 
2205         SLIST_FOREACH(pipe, &pipehash[i], next) {
2206                 struct dn_pipe *pipe_bp = (struct dn_pipe *)bp;
2207
2208                 /*
2209                  * Copy pipe descriptor into *bp, convert delay back to ms,
2210                  * then copy the flow_set descriptor(s) one at a time.
2211                  * After each flow_set, copy the queue descriptor it owns.
2212                  */
2213                 bcopy(pipe, bp, sizeof(*pipe));
2214                 pipe_bp->delay = (pipe_bp->delay * 1000) / hz;
2215                 /*
2216                  * XXX the following is a hack based on ->next being the
2217                  * first field in dn_pipe and dn_flow_set. The correct
2218                  * solution would be to move the dn_flow_set to the beginning
2219                  * of struct dn_pipe.
2220                  */
2221                 pipe_bp->next.sle_next = (struct dn_pipe *)DN_IS_PIPE;
2222                 /* Clean pointers. */
2223                 pipe_bp->head = pipe_bp->tail = NULL;
2224                 pipe_bp->fs.next.sle_next = NULL;
2225                 pipe_bp->fs.pipe = NULL;
2226                 pipe_bp->fs.rq = NULL;
2227                 pipe_bp->samples = NULL;
2228
2229                 bp += sizeof(*pipe) ;
2230                 bp = dn_copy_set(&(pipe->fs), bp);
2231         }
2232
2233     for (i = 0; i < HASHSIZE; i++) 
2234         SLIST_FOREACH(fs, &flowsethash[i], next) {
2235                 struct dn_flow_set *fs_bp = (struct dn_flow_set *)bp;
2236
2237                 bcopy(fs, bp, sizeof(*fs));
2238                 /* XXX same hack as above */
2239                 fs_bp->next.sle_next = (struct dn_flow_set *)DN_IS_QUEUE;
2240                 fs_bp->pipe = NULL;
2241                 fs_bp->rq = NULL;
2242                 bp += sizeof(*fs);
2243                 bp = dn_copy_set(fs, bp);
2244         }
2245
2246     DUMMYNET_UNLOCK();
2247
2248     error = sooptcopyout(sopt, buf, size);
2249     free(buf, M_TEMP);
2250     return error ;
2251 }
2252
2253 /*
2254  * Handler for the various dummynet socket options (get, flush, config, del)
2255  */
2256 static int
2257 ip_dn_ctl(struct sockopt *sopt)
2258 {
2259     int error;
2260     struct dn_pipe *p = NULL;
2261
2262     error = priv_check(sopt->sopt_td, PRIV_NETINET_DUMMYNET);
2263     if (error)
2264         return (error);
2265
2266     /* Disallow sets in really-really secure mode. */
2267     if (sopt->sopt_dir == SOPT_SET) {
2268 #if __FreeBSD_version >= 500034
2269         error =  securelevel_ge(sopt->sopt_td->td_ucred, 3);
2270         if (error)
2271             return (error);
2272 #else
2273         if (securelevel >= 3)
2274             return (EPERM);
2275 #endif
2276     }
2277
2278     switch (sopt->sopt_name) {
2279     default :
2280         printf("dummynet: -- unknown option %d", sopt->sopt_name);
2281         error = EINVAL ;
2282         break ;
2283
2284     case IP_DUMMYNET_GET :
2285         error = dummynet_get(sopt);
2286         break ;
2287
2288     case IP_DUMMYNET_FLUSH :
2289         dummynet_flush() ;
2290         break ;
2291
2292     case IP_DUMMYNET_CONFIGURE :
2293         p = malloc(sizeof(struct dn_pipe_max), M_TEMP, M_WAITOK);
2294         error = sooptcopyin(sopt, p, sizeof(struct dn_pipe_max), sizeof *p);
2295         if (error)
2296             break ;
2297         if (p->samples_no > 0)
2298             p->samples = &( ((struct dn_pipe_max*) p)->samples[0] );
2299
2300         error = config_pipe(p);
2301         break ;
2302
2303     case IP_DUMMYNET_DEL :      /* remove a pipe or queue */
2304         p = malloc(sizeof(struct dn_pipe_max), M_TEMP, M_WAITOK);
2305         error = sooptcopyin(sopt, p, sizeof *p, sizeof *p);
2306         if (error)
2307             break ;
2308
2309         error = delete_pipe(p);
2310         break ;
2311     }
2312
2313     if (p != NULL)
2314         free(p, M_TEMP);
2315
2316     return error ;
2317 }
2318
2319 static void
2320 ip_dn_init(void)
2321 {
2322         int i;
2323
2324         if (bootverbose)
2325                 printf("DUMMYNET with IPv6 initialized (040826)\n");
2326
2327         DUMMYNET_LOCK_INIT();
2328
2329         for (i = 0; i < HASHSIZE; i++) {
2330                 SLIST_INIT(&pipehash[i]);
2331                 SLIST_INIT(&flowsethash[i]);
2332         }
2333         ready_heap.size = ready_heap.elements = 0;
2334         ready_heap.offset = 0;
2335
2336         wfq_ready_heap.size = wfq_ready_heap.elements = 0;
2337         wfq_ready_heap.offset = 0;
2338
2339         extract_heap.size = extract_heap.elements = 0;
2340         extract_heap.offset = 0;
2341
2342         ip_dn_ctl_ptr = ip_dn_ctl;
2343         ip_dn_io_ptr = dummynet_io;
2344         ip_dn_ruledel_ptr = dn_rule_delete;
2345
2346         TASK_INIT(&dn_task, 0, dummynet_task, NULL);
2347         dn_tq = taskqueue_create_fast("dummynet", M_NOWAIT,
2348             taskqueue_thread_enqueue, &dn_tq);
2349         taskqueue_start_threads(&dn_tq, 1, PI_NET, "dummynet");
2350
2351         callout_init(&dn_timeout, CALLOUT_MPSAFE);
2352         callout_reset(&dn_timeout, 1, dummynet, NULL);
2353  
2354         /* Initialize curr_time adjustment mechanics. */
2355         getmicrouptime(&prev_t);
2356 }
2357
2358 #ifdef KLD_MODULE
2359 static void
2360 ip_dn_destroy(void)
2361 {
2362         ip_dn_ctl_ptr = NULL;
2363         ip_dn_io_ptr = NULL;
2364         ip_dn_ruledel_ptr = NULL;
2365
2366         DUMMYNET_LOCK();
2367         callout_stop(&dn_timeout);
2368         DUMMYNET_UNLOCK();
2369         taskqueue_drain(dn_tq, &dn_task);
2370         taskqueue_free(dn_tq);
2371
2372         dummynet_flush();
2373
2374         DUMMYNET_LOCK_DESTROY();
2375 }
2376 #endif /* KLD_MODULE */
2377
2378 static int
2379 dummynet_modevent(module_t mod, int type, void *data)
2380 {
2381
2382         switch (type) {
2383         case MOD_LOAD:
2384                 if (ip_dn_io_ptr) {
2385                     printf("DUMMYNET already loaded\n");
2386                     return EEXIST ;
2387                 }
2388                 ip_dn_init();
2389                 break;
2390
2391         case MOD_UNLOAD:
2392 #if !defined(KLD_MODULE)
2393                 printf("dummynet statically compiled, cannot unload\n");
2394                 return EINVAL ;
2395 #else
2396                 ip_dn_destroy();
2397 #endif
2398                 break ;
2399         default:
2400                 return EOPNOTSUPP;
2401                 break ;
2402         }
2403         return 0 ;
2404 }
2405
2406 static moduledata_t dummynet_mod = {
2407         "dummynet",
2408         dummynet_modevent,
2409         NULL
2410 };
2411 DECLARE_MODULE(dummynet, dummynet_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
2412 MODULE_DEPEND(dummynet, ipfw, 2, 2, 2);
2413 MODULE_VERSION(dummynet, 1);