b8cbc2ef1fb09faf24ff117bcabdd5bd601591ce
[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 #define DN_FREE_PKT(_m) do {                            \
1553         m_freem(_m);                                    \
1554 } while (0)
1555
1556 /*
1557  * Dispose all packets and flow_queues on a flow_set.
1558  * If all=1, also remove red lookup table and other storage,
1559  * including the descriptor itself.
1560  * For the one in dn_pipe MUST also cleanup ready_heap...
1561  */
1562 static void
1563 purge_flow_set(struct dn_flow_set *fs, int all)
1564 {
1565         struct dn_flow_queue *q, *qn;
1566         int i;
1567
1568         DUMMYNET_LOCK_ASSERT();
1569
1570         for (i = 0; i <= fs->rq_size; i++) {
1571                 for (q = fs->rq[i]; q != NULL; q = qn) {
1572                         struct mbuf *m, *mnext;
1573
1574                         mnext = q->head;
1575                         while ((m = mnext) != NULL) {
1576                                 mnext = m->m_nextpkt;
1577                                 DN_FREE_PKT(m);
1578                         }
1579                         qn = q->next;
1580                         free(q, M_DUMMYNET);
1581                 }
1582                 fs->rq[i] = NULL;
1583         }
1584
1585         fs->rq_elements = 0;
1586         if (all) {
1587                 /* RED - free lookup table. */
1588                 if (fs->w_q_lookup != NULL)
1589                         free(fs->w_q_lookup, M_DUMMYNET);
1590                 if (fs->rq != NULL)
1591                         free(fs->rq, M_DUMMYNET);
1592                 /* If this fs is not part of a pipe, free it. */
1593                 if (fs->pipe == NULL || fs != &(fs->pipe->fs))
1594                         free(fs, M_DUMMYNET);
1595         }
1596 }
1597
1598 /*
1599  * Dispose all packets queued on a pipe (not a flow_set).
1600  * Also free all resources associated to a pipe, which is about
1601  * to be deleted.
1602  */
1603 static void
1604 purge_pipe(struct dn_pipe *pipe)
1605 {
1606     struct mbuf *m, *mnext;
1607
1608     purge_flow_set( &(pipe->fs), 1 );
1609
1610     mnext = pipe->head;
1611     while ((m = mnext) != NULL) {
1612         mnext = m->m_nextpkt;
1613         DN_FREE_PKT(m);
1614     }
1615
1616     heap_free( &(pipe->scheduler_heap) );
1617     heap_free( &(pipe->not_eligible_heap) );
1618     heap_free( &(pipe->idle_heap) );
1619 }
1620
1621 /*
1622  * Delete all pipes and heaps returning memory. Must also
1623  * remove references from all ipfw rules to all pipes.
1624  */
1625 static void
1626 dummynet_flush(void)
1627 {
1628         struct dn_pipe *pipe, *pipe1;
1629         struct dn_flow_set *fs, *fs1;
1630         int i;
1631
1632         DUMMYNET_LOCK();
1633         /* Free heaps so we don't have unwanted events. */
1634         heap_free(&ready_heap);
1635         heap_free(&wfq_ready_heap);
1636         heap_free(&extract_heap);
1637
1638         /*
1639          * Now purge all queued pkts and delete all pipes.
1640          *
1641          * XXXGL: can we merge the for(;;) cycles into one or not?
1642          */
1643         for (i = 0; i < HASHSIZE; i++)
1644                 SLIST_FOREACH_SAFE(fs, &flowsethash[i], next, fs1) {
1645                         SLIST_REMOVE(&flowsethash[i], fs, dn_flow_set, next);
1646                         purge_flow_set(fs, 1);
1647                 }
1648         for (i = 0; i < HASHSIZE; i++)
1649                 SLIST_FOREACH_SAFE(pipe, &pipehash[i], next, pipe1) {
1650                         SLIST_REMOVE(&pipehash[i], pipe, dn_pipe, next);
1651                         purge_pipe(pipe);
1652                         free_pipe(pipe);
1653                 }
1654         DUMMYNET_UNLOCK();
1655 }
1656
1657 extern struct ip_fw *ip_fw_default_rule;
1658 static void
1659 dn_rule_delete_fs(struct dn_flow_set *fs, void *r)
1660 {
1661     int i ;
1662     struct dn_flow_queue *q ;
1663     struct mbuf *m ;
1664
1665     for (i = 0 ; i <= fs->rq_size ; i++) /* last one is ovflow */
1666         for (q = fs->rq[i] ; q ; q = q->next )
1667             for (m = q->head ; m ; m = m->m_nextpkt ) {
1668                 struct dn_pkt_tag *pkt = dn_tag_get(m) ;
1669                 if (pkt->rule == r)
1670                     pkt->rule = ip_fw_default_rule ;
1671             }
1672 }
1673
1674 /*
1675  * When a firewall rule is deleted, scan all queues and remove the pointer
1676  * to the rule from matching packets, making them point to the default rule.
1677  * The pointer is used to reinject packets in case one_pass = 0.
1678  */
1679 void
1680 dn_rule_delete(void *r)
1681 {
1682     struct dn_pipe *pipe;
1683     struct dn_flow_set *fs;
1684     struct dn_pkt_tag *pkt;
1685     struct mbuf *m;
1686     int i;
1687
1688     DUMMYNET_LOCK();
1689     /*
1690      * If the rule references a queue (dn_flow_set), then scan
1691      * the flow set, otherwise scan pipes. Should do either, but doing
1692      * both does not harm.
1693      */
1694     for (i = 0; i < HASHSIZE; i++)
1695         SLIST_FOREACH(fs, &flowsethash[i], next)
1696                 dn_rule_delete_fs(fs, r);
1697
1698     for (i = 0; i < HASHSIZE; i++)
1699         SLIST_FOREACH(pipe, &pipehash[i], next) {
1700                 fs = &(pipe->fs);
1701                 dn_rule_delete_fs(fs, r);
1702                 for (m = pipe->head ; m ; m = m->m_nextpkt ) {
1703                         pkt = dn_tag_get(m);
1704                         if (pkt->rule == r)
1705                                 pkt->rule = ip_fw_default_rule;
1706                 }
1707         }
1708     DUMMYNET_UNLOCK();
1709 }
1710
1711 /*
1712  * setup RED parameters
1713  */
1714 static int
1715 config_red(struct dn_flow_set *p, struct dn_flow_set *x)
1716 {
1717         int i;
1718
1719         x->w_q = p->w_q;
1720         x->min_th = SCALE(p->min_th);
1721         x->max_th = SCALE(p->max_th);
1722         x->max_p = p->max_p;
1723
1724         x->c_1 = p->max_p / (p->max_th - p->min_th);
1725         x->c_2 = SCALE_MUL(x->c_1, SCALE(p->min_th));
1726
1727         if (x->flags_fs & DN_IS_GENTLE_RED) {
1728                 x->c_3 = (SCALE(1) - p->max_p) / p->max_th;
1729                 x->c_4 = SCALE(1) - 2 * p->max_p;
1730         }
1731
1732         /* If the lookup table already exist, free and create it again. */
1733         if (x->w_q_lookup) {
1734                 free(x->w_q_lookup, M_DUMMYNET);
1735                 x->w_q_lookup = NULL;
1736         }
1737         if (red_lookup_depth == 0) {
1738                 printf("\ndummynet: net.inet.ip.dummynet.red_lookup_depth"
1739                     "must be > 0\n");
1740                 free(x, M_DUMMYNET);
1741                 return (EINVAL);
1742         }
1743         x->lookup_depth = red_lookup_depth;
1744         x->w_q_lookup = (u_int *)malloc(x->lookup_depth * sizeof(int),
1745             M_DUMMYNET, M_NOWAIT);
1746         if (x->w_q_lookup == NULL) {
1747                 printf("dummynet: sorry, cannot allocate red lookup table\n");
1748                 free(x, M_DUMMYNET);
1749                 return(ENOSPC);
1750         }
1751
1752         /* Fill the lookup table with (1 - w_q)^x */
1753         x->lookup_step = p->lookup_step;
1754         x->lookup_weight = p->lookup_weight;
1755         x->w_q_lookup[0] = SCALE(1) - x->w_q;
1756
1757         for (i = 1; i < x->lookup_depth; i++)
1758                 x->w_q_lookup[i] =
1759                     SCALE_MUL(x->w_q_lookup[i - 1], x->lookup_weight);
1760
1761         if (red_avg_pkt_size < 1)
1762                 red_avg_pkt_size = 512;
1763         x->avg_pkt_size = red_avg_pkt_size;
1764         if (red_max_pkt_size < 1)
1765                 red_max_pkt_size = 1500;
1766         x->max_pkt_size = red_max_pkt_size;
1767         return (0);
1768 }
1769
1770 static int
1771 alloc_hash(struct dn_flow_set *x, struct dn_flow_set *pfs)
1772 {
1773     if (x->flags_fs & DN_HAVE_FLOW_MASK) {     /* allocate some slots */
1774         int l = pfs->rq_size;
1775
1776         if (l == 0)
1777             l = dn_hash_size;
1778         if (l < 4)
1779             l = 4;
1780         else if (l > DN_MAX_HASH_SIZE)
1781             l = DN_MAX_HASH_SIZE;
1782         x->rq_size = l;
1783     } else                  /* one is enough for null mask */
1784         x->rq_size = 1;
1785     x->rq = malloc((1 + x->rq_size) * sizeof(struct dn_flow_queue *),
1786             M_DUMMYNET, M_NOWAIT | M_ZERO);
1787     if (x->rq == NULL) {
1788         printf("dummynet: sorry, cannot allocate queue\n");
1789         return (ENOMEM);
1790     }
1791     x->rq_elements = 0;
1792     return 0 ;
1793 }
1794
1795 static void
1796 set_fs_parms(struct dn_flow_set *x, struct dn_flow_set *src)
1797 {
1798         x->flags_fs = src->flags_fs;
1799         x->qsize = src->qsize;
1800         x->plr = src->plr;
1801         x->flow_mask = src->flow_mask;
1802         if (x->flags_fs & DN_QSIZE_IS_BYTES) {
1803                 if (x->qsize > pipe_byte_limit)
1804                         x->qsize = 1024 * 1024;
1805         } else {
1806                 if (x->qsize == 0)
1807                         x->qsize = 50;
1808                 if (x->qsize > pipe_slot_limit)
1809                         x->qsize = 50;
1810         }
1811         /* Configuring RED. */
1812         if (x->flags_fs & DN_IS_RED)
1813                 config_red(src, x);     /* XXX should check errors */
1814 }
1815
1816 /*
1817  * Setup pipe or queue parameters.
1818  */
1819 static int
1820 config_pipe(struct dn_pipe *p)
1821 {
1822         struct dn_flow_set *pfs = &(p->fs);
1823         struct dn_flow_queue *q;
1824         int i, error;
1825
1826         /*
1827          * The config program passes parameters as follows:
1828          * bw = bits/second (0 means no limits),
1829          * delay = ms, must be translated into ticks.
1830          * qsize = slots/bytes
1831          */
1832         p->delay = (p->delay * hz) / 1000;
1833         /* We need either a pipe number or a flow_set number. */
1834         if (p->pipe_nr == 0 && pfs->fs_nr == 0)
1835                 return (EINVAL);
1836         if (p->pipe_nr != 0 && pfs->fs_nr != 0)
1837                 return (EINVAL);
1838         if (p->pipe_nr != 0) {                  /* this is a pipe */
1839                 struct dn_pipe *pipe;
1840
1841                 DUMMYNET_LOCK();
1842                 pipe = locate_pipe(p->pipe_nr); /* locate pipe */
1843
1844                 if (pipe == NULL) {             /* new pipe */
1845                         pipe = malloc(sizeof(struct dn_pipe), M_DUMMYNET,
1846                             M_NOWAIT | M_ZERO);
1847                         if (pipe == NULL) {
1848                                 DUMMYNET_UNLOCK();
1849                                 printf("dummynet: no memory for new pipe\n");
1850                                 return (ENOMEM);
1851                         }
1852                         pipe->pipe_nr = p->pipe_nr;
1853                         pipe->fs.pipe = pipe;
1854                         /*
1855                          * idle_heap is the only one from which
1856                          * we extract from the middle.
1857                          */
1858                         pipe->idle_heap.size = pipe->idle_heap.elements = 0;
1859                         pipe->idle_heap.offset =
1860                             offsetof(struct dn_flow_queue, heap_pos);
1861                 } else
1862                         /* Flush accumulated credit for all queues. */
1863                         for (i = 0; i <= pipe->fs.rq_size; i++)
1864                                 for (q = pipe->fs.rq[i]; q; q = q->next)
1865                                         q->numbytes = io_fast ? p->bandwidth : 0;
1866
1867                 pipe->bandwidth = p->bandwidth;
1868                 pipe->numbytes = 0;             /* just in case... */
1869                 bcopy(p->if_name, pipe->if_name, sizeof(p->if_name));
1870                 pipe->ifp = NULL;               /* reset interface ptr */
1871                 pipe->delay = p->delay;
1872                 set_fs_parms(&(pipe->fs), pfs);
1873
1874                 /* Handle changes in the delay profile. */
1875                 if (p->samples_no > 0) {
1876                         if (pipe->samples_no != p->samples_no) {
1877                                 if (pipe->samples != NULL)
1878                                         free(pipe->samples, M_DUMMYNET);
1879                                 pipe->samples =
1880                                     malloc(p->samples_no*sizeof(dn_key),
1881                                         M_DUMMYNET, M_NOWAIT | M_ZERO);
1882                                 if (pipe->samples == NULL) {
1883                                         DUMMYNET_UNLOCK();
1884                                         printf("dummynet: no memory "
1885                                                 "for new samples\n");
1886                                         return (ENOMEM);
1887                                 }
1888                                 pipe->samples_no = p->samples_no;
1889                         }
1890
1891                         strncpy(pipe->name,p->name,sizeof(pipe->name));
1892                         pipe->loss_level = p->loss_level;
1893                         for (i = 0; i<pipe->samples_no; ++i)
1894                                 pipe->samples[i] = p->samples[i];
1895                 } else if (pipe->samples != NULL) {
1896                         free(pipe->samples, M_DUMMYNET);
1897                         pipe->samples = NULL;
1898                         pipe->samples_no = 0;
1899                 }
1900
1901                 if (pipe->fs.rq == NULL) {      /* a new pipe */
1902                         error = alloc_hash(&(pipe->fs), pfs);
1903                         if (error) {
1904                                 DUMMYNET_UNLOCK();
1905                                 free_pipe(pipe);
1906                                 return (error);
1907                         }
1908                         SLIST_INSERT_HEAD(&pipehash[HASH(pipe->pipe_nr)],
1909                             pipe, next);
1910                 }
1911                 DUMMYNET_UNLOCK();
1912         } else {                                /* config queue */
1913                 struct dn_flow_set *fs;
1914
1915                 DUMMYNET_LOCK();
1916                 fs = locate_flowset(pfs->fs_nr); /* locate flow_set */
1917
1918                 if (fs == NULL) {               /* new */
1919                         if (pfs->parent_nr == 0) { /* need link to a pipe */
1920                                 DUMMYNET_UNLOCK();
1921                                 return (EINVAL);
1922                         }
1923                         fs = malloc(sizeof(struct dn_flow_set), M_DUMMYNET,
1924                             M_NOWAIT | M_ZERO);
1925                         if (fs == NULL) {
1926                                 DUMMYNET_UNLOCK();
1927                                 printf(
1928                                     "dummynet: no memory for new flow_set\n");
1929                                 return (ENOMEM);
1930                         }
1931                         fs->fs_nr = pfs->fs_nr;
1932                         fs->parent_nr = pfs->parent_nr;
1933                         fs->weight = pfs->weight;
1934                         if (fs->weight == 0)
1935                                 fs->weight = 1;
1936                         else if (fs->weight > 100)
1937                                 fs->weight = 100;
1938                 } else {
1939                         /*
1940                          * Change parent pipe not allowed;
1941                          * must delete and recreate.
1942                          */
1943                         if (pfs->parent_nr != 0 &&
1944                             fs->parent_nr != pfs->parent_nr) {
1945                                 DUMMYNET_UNLOCK();
1946                                 return (EINVAL);
1947                         }
1948                 }
1949
1950                 set_fs_parms(fs, pfs);
1951
1952                 if (fs->rq == NULL) {           /* a new flow_set */
1953                         error = alloc_hash(fs, pfs);
1954                         if (error) {
1955                                 DUMMYNET_UNLOCK();
1956                                 free(fs, M_DUMMYNET);
1957                                 return (error);
1958                         }
1959                         SLIST_INSERT_HEAD(&flowsethash[HASH(fs->fs_nr)],
1960                             fs, next);
1961                 }
1962                 DUMMYNET_UNLOCK();
1963         }
1964         return (0);
1965 }
1966
1967 /*
1968  * Helper function to remove from a heap queues which are linked to
1969  * a flow_set about to be deleted.
1970  */
1971 static void
1972 fs_remove_from_heap(struct dn_heap *h, struct dn_flow_set *fs)
1973 {
1974     int i = 0, found = 0 ;
1975     for (; i < h->elements ;)
1976         if ( ((struct dn_flow_queue *)h->p[i].object)->fs == fs) {
1977             h->elements-- ;
1978             h->p[i] = h->p[h->elements] ;
1979             found++ ;
1980         } else
1981             i++ ;
1982     if (found)
1983         heapify(h);
1984 }
1985
1986 /*
1987  * helper function to remove a pipe from a heap (can be there at most once)
1988  */
1989 static void
1990 pipe_remove_from_heap(struct dn_heap *h, struct dn_pipe *p)
1991 {
1992     if (h->elements > 0) {
1993         int i = 0 ;
1994         for (i=0; i < h->elements ; i++ ) {
1995             if (h->p[i].object == p) { /* found it */
1996                 h->elements-- ;
1997                 h->p[i] = h->p[h->elements] ;
1998                 heapify(h);
1999                 break ;
2000             }
2001         }
2002     }
2003 }
2004
2005 /*
2006  * drain all queues. Called in case of severe mbuf shortage.
2007  */
2008 void
2009 dummynet_drain(void)
2010 {
2011     struct dn_flow_set *fs;
2012     struct dn_pipe *pipe;
2013     struct mbuf *m, *mnext;
2014     int i;
2015
2016     DUMMYNET_LOCK_ASSERT();
2017
2018     heap_free(&ready_heap);
2019     heap_free(&wfq_ready_heap);
2020     heap_free(&extract_heap);
2021     /* remove all references to this pipe from flow_sets */
2022     for (i = 0; i < HASHSIZE; i++)
2023         SLIST_FOREACH(fs, &flowsethash[i], next)
2024                 purge_flow_set(fs, 0);
2025
2026     for (i = 0; i < HASHSIZE; i++) {
2027         SLIST_FOREACH(pipe, &pipehash[i], next) {
2028                 purge_flow_set(&(pipe->fs), 0);
2029
2030                 mnext = pipe->head;
2031                 while ((m = mnext) != NULL) {
2032                         mnext = m->m_nextpkt;
2033                         DN_FREE_PKT(m);
2034                 }
2035                 pipe->head = pipe->tail = NULL;
2036         }
2037     }
2038 }
2039
2040 /*
2041  * Fully delete a pipe or a queue, cleaning up associated info.
2042  */
2043 static int
2044 delete_pipe(struct dn_pipe *p)
2045 {
2046
2047     if (p->pipe_nr == 0 && p->fs.fs_nr == 0)
2048         return EINVAL ;
2049     if (p->pipe_nr != 0 && p->fs.fs_nr != 0)
2050         return EINVAL ;
2051     if (p->pipe_nr != 0) { /* this is an old-style pipe */
2052         struct dn_pipe *pipe;
2053         struct dn_flow_set *fs;
2054         int i;
2055
2056         DUMMYNET_LOCK();
2057         pipe = locate_pipe(p->pipe_nr); /* locate pipe */
2058
2059         if (pipe == NULL) {
2060             DUMMYNET_UNLOCK();
2061             return (ENOENT);    /* not found */
2062         }
2063
2064         /* Unlink from list of pipes. */
2065         SLIST_REMOVE(&pipehash[HASH(pipe->pipe_nr)], pipe, dn_pipe, next);
2066
2067         /* Remove all references to this pipe from flow_sets. */
2068         for (i = 0; i < HASHSIZE; i++)
2069             SLIST_FOREACH(fs, &flowsethash[i], next)
2070                 if (fs->pipe == pipe) {
2071                         printf("dummynet: ++ ref to pipe %d from fs %d\n",
2072                             p->pipe_nr, fs->fs_nr);
2073                         fs->pipe = NULL ;
2074                         purge_flow_set(fs, 0);
2075                 }
2076         fs_remove_from_heap(&ready_heap, &(pipe->fs));
2077         purge_pipe(pipe); /* remove all data associated to this pipe */
2078         /* remove reference to here from extract_heap and wfq_ready_heap */
2079         pipe_remove_from_heap(&extract_heap, pipe);
2080         pipe_remove_from_heap(&wfq_ready_heap, pipe);
2081         DUMMYNET_UNLOCK();
2082
2083         free_pipe(pipe);
2084     } else { /* this is a WF2Q queue (dn_flow_set) */
2085         struct dn_flow_set *fs;
2086
2087         DUMMYNET_LOCK();
2088         fs = locate_flowset(p->fs.fs_nr); /* locate set */
2089
2090         if (fs == NULL) {
2091             DUMMYNET_UNLOCK();
2092             return (ENOENT); /* not found */
2093         }
2094
2095         /* Unlink from list of flowsets. */
2096         SLIST_REMOVE( &flowsethash[HASH(fs->fs_nr)], fs, dn_flow_set, next);
2097
2098         if (fs->pipe != NULL) {
2099             /* Update total weight on parent pipe and cleanup parent heaps. */
2100             fs->pipe->sum -= fs->weight * fs->backlogged ;
2101             fs_remove_from_heap(&(fs->pipe->not_eligible_heap), fs);
2102             fs_remove_from_heap(&(fs->pipe->scheduler_heap), fs);
2103 #if 1   /* XXX should i remove from idle_heap as well ? */
2104             fs_remove_from_heap(&(fs->pipe->idle_heap), fs);
2105 #endif
2106         }
2107         purge_flow_set(fs, 1);
2108         DUMMYNET_UNLOCK();
2109     }
2110     return 0 ;
2111 }
2112
2113 /*
2114  * helper function used to copy data from kernel in DUMMYNET_GET
2115  */
2116 static char *
2117 dn_copy_set(struct dn_flow_set *set, char *bp)
2118 {
2119     int i, copied = 0 ;
2120     struct dn_flow_queue *q, *qp = (struct dn_flow_queue *)bp;
2121
2122     DUMMYNET_LOCK_ASSERT();
2123
2124     for (i = 0 ; i <= set->rq_size ; i++)
2125         for (q = set->rq[i] ; q ; q = q->next, qp++ ) {
2126             if (q->hash_slot != i)
2127                 printf("dummynet: ++ at %d: wrong slot (have %d, "
2128                     "should be %d)\n", copied, q->hash_slot, i);
2129             if (q->fs != set)
2130                 printf("dummynet: ++ at %d: wrong fs ptr (have %p, should be %p)\n",
2131                         i, q->fs, set);
2132             copied++ ;
2133             bcopy(q, qp, sizeof( *q ) );
2134             /* cleanup pointers */
2135             qp->next = NULL ;
2136             qp->head = qp->tail = NULL ;
2137             qp->fs = NULL ;
2138         }
2139     if (copied != set->rq_elements)
2140         printf("dummynet: ++ wrong count, have %d should be %d\n",
2141             copied, set->rq_elements);
2142     return (char *)qp ;
2143 }
2144
2145 static size_t
2146 dn_calc_size(void)
2147 {
2148     struct dn_flow_set *fs;
2149     struct dn_pipe *pipe;
2150     size_t size = 0;
2151     int i;
2152
2153     DUMMYNET_LOCK_ASSERT();
2154     /*
2155      * Compute size of data structures: list of pipes and flow_sets.
2156      */
2157     for (i = 0; i < HASHSIZE; i++) {
2158         SLIST_FOREACH(pipe, &pipehash[i], next)
2159                 size += sizeof(*pipe) +
2160                     pipe->fs.rq_elements * sizeof(struct dn_flow_queue);
2161         SLIST_FOREACH(fs, &flowsethash[i], next)
2162                 size += sizeof (*fs) +
2163                     fs->rq_elements * sizeof(struct dn_flow_queue);
2164     }
2165     return size;
2166 }
2167
2168 static int
2169 dummynet_get(struct sockopt *sopt)
2170 {
2171     char *buf, *bp ; /* bp is the "copy-pointer" */
2172     size_t size ;
2173     struct dn_flow_set *fs;
2174     struct dn_pipe *pipe;
2175     int error=0, i ;
2176
2177     /* XXX lock held too long */
2178     DUMMYNET_LOCK();
2179     /*
2180      * XXX: Ugly, but we need to allocate memory with M_WAITOK flag and we
2181      *      cannot use this flag while holding a mutex.
2182      */
2183     for (i = 0; i < 10; i++) {
2184         size = dn_calc_size();
2185         DUMMYNET_UNLOCK();
2186         buf = malloc(size, M_TEMP, M_WAITOK);
2187         DUMMYNET_LOCK();
2188         if (size == dn_calc_size())
2189                 break;
2190         free(buf, M_TEMP);
2191         buf = NULL;
2192     }
2193     if (buf == NULL) {
2194         DUMMYNET_UNLOCK();
2195         return ENOBUFS ;
2196     }
2197     bp = buf;
2198     for (i = 0; i < HASHSIZE; i++) 
2199         SLIST_FOREACH(pipe, &pipehash[i], next) {
2200                 struct dn_pipe *pipe_bp = (struct dn_pipe *)bp;
2201
2202                 /*
2203                  * Copy pipe descriptor into *bp, convert delay back to ms,
2204                  * then copy the flow_set descriptor(s) one at a time.
2205                  * After each flow_set, copy the queue descriptor it owns.
2206                  */
2207                 bcopy(pipe, bp, sizeof(*pipe));
2208                 pipe_bp->delay = (pipe_bp->delay * 1000) / hz;
2209                 /*
2210                  * XXX the following is a hack based on ->next being the
2211                  * first field in dn_pipe and dn_flow_set. The correct
2212                  * solution would be to move the dn_flow_set to the beginning
2213                  * of struct dn_pipe.
2214                  */
2215                 pipe_bp->next.sle_next = (struct dn_pipe *)DN_IS_PIPE;
2216                 /* Clean pointers. */
2217                 pipe_bp->head = pipe_bp->tail = NULL;
2218                 pipe_bp->fs.next.sle_next = NULL;
2219                 pipe_bp->fs.pipe = NULL;
2220                 pipe_bp->fs.rq = NULL;
2221                 pipe_bp->samples = NULL;
2222
2223                 bp += sizeof(*pipe) ;
2224                 bp = dn_copy_set(&(pipe->fs), bp);
2225         }
2226
2227     for (i = 0; i < HASHSIZE; i++) 
2228         SLIST_FOREACH(fs, &flowsethash[i], next) {
2229                 struct dn_flow_set *fs_bp = (struct dn_flow_set *)bp;
2230
2231                 bcopy(fs, bp, sizeof(*fs));
2232                 /* XXX same hack as above */
2233                 fs_bp->next.sle_next = (struct dn_flow_set *)DN_IS_QUEUE;
2234                 fs_bp->pipe = NULL;
2235                 fs_bp->rq = NULL;
2236                 bp += sizeof(*fs);
2237                 bp = dn_copy_set(fs, bp);
2238         }
2239
2240     DUMMYNET_UNLOCK();
2241
2242     error = sooptcopyout(sopt, buf, size);
2243     free(buf, M_TEMP);
2244     return error ;
2245 }
2246
2247 /*
2248  * Handler for the various dummynet socket options (get, flush, config, del)
2249  */
2250 static int
2251 ip_dn_ctl(struct sockopt *sopt)
2252 {
2253     int error;
2254     struct dn_pipe *p = NULL;
2255
2256     error = priv_check(sopt->sopt_td, PRIV_NETINET_DUMMYNET);
2257     if (error)
2258         return (error);
2259
2260     /* Disallow sets in really-really secure mode. */
2261     if (sopt->sopt_dir == SOPT_SET) {
2262 #if __FreeBSD_version >= 500034
2263         error =  securelevel_ge(sopt->sopt_td->td_ucred, 3);
2264         if (error)
2265             return (error);
2266 #else
2267         if (securelevel >= 3)
2268             return (EPERM);
2269 #endif
2270     }
2271
2272     switch (sopt->sopt_name) {
2273     default :
2274         printf("dummynet: -- unknown option %d", sopt->sopt_name);
2275         error = EINVAL ;
2276         break ;
2277
2278     case IP_DUMMYNET_GET :
2279         error = dummynet_get(sopt);
2280         break ;
2281
2282     case IP_DUMMYNET_FLUSH :
2283         dummynet_flush() ;
2284         break ;
2285
2286     case IP_DUMMYNET_CONFIGURE :
2287         p = malloc(sizeof(struct dn_pipe_max), M_TEMP, M_WAITOK);
2288         error = sooptcopyin(sopt, p, sizeof(struct dn_pipe_max), sizeof *p);
2289         if (error)
2290             break ;
2291         if (p->samples_no > 0)
2292             p->samples = &( ((struct dn_pipe_max*) p)->samples[0] );
2293
2294         error = config_pipe(p);
2295         break ;
2296
2297     case IP_DUMMYNET_DEL :      /* remove a pipe or queue */
2298         p = malloc(sizeof(struct dn_pipe_max), M_TEMP, M_WAITOK);
2299         error = sooptcopyin(sopt, p, sizeof *p, sizeof *p);
2300         if (error)
2301             break ;
2302
2303         error = delete_pipe(p);
2304         break ;
2305     }
2306
2307     if (p != NULL)
2308         free(p, M_TEMP);
2309
2310     return error ;
2311 }
2312
2313 static void
2314 ip_dn_init(void)
2315 {
2316         int i;
2317
2318         if (bootverbose)
2319                 printf("DUMMYNET with IPv6 initialized (040826)\n");
2320
2321         DUMMYNET_LOCK_INIT();
2322
2323         for (i = 0; i < HASHSIZE; i++) {
2324                 SLIST_INIT(&pipehash[i]);
2325                 SLIST_INIT(&flowsethash[i]);
2326         }
2327         ready_heap.size = ready_heap.elements = 0;
2328         ready_heap.offset = 0;
2329
2330         wfq_ready_heap.size = wfq_ready_heap.elements = 0;
2331         wfq_ready_heap.offset = 0;
2332
2333         extract_heap.size = extract_heap.elements = 0;
2334         extract_heap.offset = 0;
2335
2336         ip_dn_ctl_ptr = ip_dn_ctl;
2337         ip_dn_io_ptr = dummynet_io;
2338         ip_dn_ruledel_ptr = dn_rule_delete;
2339
2340         TASK_INIT(&dn_task, 0, dummynet_task, NULL);
2341         dn_tq = taskqueue_create_fast("dummynet", M_NOWAIT,
2342             taskqueue_thread_enqueue, &dn_tq);
2343         taskqueue_start_threads(&dn_tq, 1, PI_NET, "dummynet");
2344
2345         callout_init(&dn_timeout, CALLOUT_MPSAFE);
2346         callout_reset(&dn_timeout, 1, dummynet, NULL);
2347  
2348         /* Initialize curr_time adjustment mechanics. */
2349         getmicrouptime(&prev_t);
2350 }
2351
2352 #ifdef KLD_MODULE
2353 static void
2354 ip_dn_destroy(void)
2355 {
2356         ip_dn_ctl_ptr = NULL;
2357         ip_dn_io_ptr = NULL;
2358         ip_dn_ruledel_ptr = NULL;
2359
2360         DUMMYNET_LOCK();
2361         callout_stop(&dn_timeout);
2362         DUMMYNET_UNLOCK();
2363         taskqueue_drain(dn_tq, &dn_task);
2364         taskqueue_free(dn_tq);
2365
2366         dummynet_flush();
2367
2368         DUMMYNET_LOCK_DESTROY();
2369 }
2370 #endif /* KLD_MODULE */
2371
2372 static int
2373 dummynet_modevent(module_t mod, int type, void *data)
2374 {
2375
2376         switch (type) {
2377         case MOD_LOAD:
2378                 if (ip_dn_io_ptr) {
2379                     printf("DUMMYNET already loaded\n");
2380                     return EEXIST ;
2381                 }
2382                 ip_dn_init();
2383                 break;
2384
2385         case MOD_UNLOAD:
2386 #if !defined(KLD_MODULE)
2387                 printf("dummynet statically compiled, cannot unload\n");
2388                 return EINVAL ;
2389 #else
2390                 ip_dn_destroy();
2391 #endif
2392                 break ;
2393         default:
2394                 return EOPNOTSUPP;
2395                 break ;
2396         }
2397         return 0 ;
2398 }
2399
2400 static moduledata_t dummynet_mod = {
2401         "dummynet",
2402         dummynet_modevent,
2403         NULL
2404 };
2405 DECLARE_MODULE(dummynet, dummynet_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
2406 MODULE_DEPEND(dummynet, ipfw, 2, 2, 2);
2407 MODULE_VERSION(dummynet, 1);