- Move some macros from ip_dummynet.h to ip_dummynet.c; they are
[dragonfly.git] / sys / net / 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  * $FreeBSD: src/sys/netinet/ip_dummynet.c,v 1.24.2.22 2003/05/13 09:31:06 maxim Exp $
28  * $DragonFly: src/sys/net/dummynet/ip_dummynet.c,v 1.43 2007/11/05 14:06:06 sephe Exp $
29  */
30
31 #ifndef KLD_MODULE
32 #include "opt_ipfw.h"   /* for IPFW2 definition */
33 #endif
34
35 #ifdef DUMMYNET_DEBUG
36 #define DPRINTF(fmt, ...)       kprintf(fmt, __VA_ARGS__)
37 #else
38 #define DPRINTF(fmt, ...)       ((void)0)
39 #endif
40
41 /*
42  * This module implements IP dummynet, a bandwidth limiter/delay emulator
43  * used in conjunction with the ipfw package.
44  * Description of the data structures used is in ip_dummynet.h
45  * Here you mainly find the following blocks of code:
46  *  + variable declarations;
47  *  + heap management functions;
48  *  + scheduler and dummynet functions;
49  *  + configuration and initialization.
50  *
51  * Most important Changes:
52  *
53  * 011004: KLDable
54  * 010124: Fixed WF2Q behaviour
55  * 010122: Fixed spl protection.
56  * 000601: WF2Q support
57  * 000106: Large rewrite, use heaps to handle very many pipes.
58  * 980513: Initial release
59  */
60
61 #include <sys/param.h>
62 #include <sys/kernel.h>
63 #include <sys/malloc.h>
64 #include <sys/mbuf.h>
65 #include <sys/socketvar.h>
66 #include <sys/sysctl.h>
67 #include <sys/systimer.h>
68 #include <sys/thread2.h>
69
70 #include <net/ethernet.h>
71 #include <net/route.h>
72 #include <net/netmsg2.h>
73
74 #include <netinet/in.h>
75 #include <netinet/in_var.h>
76 #include <netinet/ip.h>
77 #include <netinet/ip_var.h>
78
79 #include <net/ipfw/ip_fw.h>
80 #include <net/dummynet/ip_dummynet.h>
81
82 #ifndef DN_CALLOUT_FREQ_MAX
83 #define DN_CALLOUT_FREQ_MAX     10000
84 #endif
85
86 /*
87  * The maximum/minimum hash table size for queues.
88  * These values must be a power of 2.
89  */
90 #define DN_MIN_HASH_SIZE        4
91 #define DN_MAX_HASH_SIZE        65536
92
93 /*
94  * Some macros are used to compare key values and handle wraparounds.
95  * MAX64 returns the largest of two key values.
96  */
97 #define DN_KEY_LT(a, b)         ((int64_t)((a) - (b)) < 0)
98 #define DN_KEY_LEQ(a, b)        ((int64_t)((a) - (b)) <= 0)
99 #define DN_KEY_GT(a, b)         ((int64_t)((a) - (b)) > 0)
100 #define DN_KEY_GEQ(a, b)        ((int64_t)((a) - (b)) >= 0)
101 #define MAX64(x, y)             ((((int64_t)((y) - (x))) > 0) ? (y) : (x))
102
103 /*
104  * We keep a private variable for the simulation time, but we could
105  * probably use an existing one ("softticks" in sys/kern/kern_timer.c)
106  */
107 static dn_key curr_time = 0; /* current simulation time */
108
109 static int dn_hash_size = 64;   /* default hash size */
110
111 /* statistics on number of queue searches and search steps */
112 static int searches, search_steps;
113 static int pipe_expire = 1;   /* expire queue if empty */
114 static int dn_max_ratio = 16; /* max queues/buckets ratio */
115
116 static int red_lookup_depth = 256;      /* RED - default lookup table depth */
117 static int red_avg_pkt_size = 512;      /* RED - default medium packet size */
118 static int red_max_pkt_size = 1500;     /* RED - default max packet size */
119
120 /*
121  * Three heaps contain queues and pipes that the scheduler handles:
122  *
123  * ready_heap contains all dn_flow_queue related to fixed-rate pipes.
124  *
125  * wfq_ready_heap contains the pipes associated with WF2Q flows
126  *
127  * extract_heap contains pipes associated with delay lines.
128  *
129  */
130
131 MALLOC_DEFINE(M_DUMMYNET, "dummynet", "dummynet heap");
132
133 static struct dn_heap ready_heap, extract_heap, wfq_ready_heap;
134
135 static int heap_init(struct dn_heap *h, int size);
136 static int heap_insert (struct dn_heap *h, dn_key key1, void *p);
137 static void heap_extract(struct dn_heap *h, void *obj);
138
139 static void transmit_event(struct dn_pipe *pipe);
140 static void ready_event(struct dn_flow_queue *q);
141
142 static int sysctl_dn_hz(SYSCTL_HANDLER_ARGS);
143
144 static struct dn_pipe *all_pipes = NULL;        /* list of all pipes */
145 static struct dn_flow_set *all_flow_sets = NULL;/* list of all flow_sets */
146
147 static struct netmsg dn_netmsg;
148 static struct systimer dn_clock;
149 static int dn_hz = 1000;
150 static int dn_cpu = 0; /* TODO tunable */
151
152 SYSCTL_NODE(_net_inet_ip, OID_AUTO, dummynet,
153                 CTLFLAG_RW, 0, "Dummynet");
154 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, hash_size,
155             CTLFLAG_RW, &dn_hash_size, 0, "Default hash table size");
156 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, curr_time,
157             CTLFLAG_RD, &curr_time, 0, "Current tick");
158 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, ready_heap,
159             CTLFLAG_RD, &ready_heap.size, 0, "Size of ready heap");
160 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, extract_heap,
161             CTLFLAG_RD, &extract_heap.size, 0, "Size of extract heap");
162 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, searches,
163             CTLFLAG_RD, &searches, 0, "Number of queue searches");
164 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, search_steps,
165             CTLFLAG_RD, &search_steps, 0, "Number of queue search steps");
166 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, expire,
167             CTLFLAG_RW, &pipe_expire, 0, "Expire queue if empty");
168 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, max_chain_len,
169             CTLFLAG_RW, &dn_max_ratio, 0,
170         "Max ratio between dynamic queues and buckets");
171 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, red_lookup_depth,
172         CTLFLAG_RD, &red_lookup_depth, 0, "Depth of RED lookup table");
173 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, red_avg_pkt_size,
174         CTLFLAG_RD, &red_avg_pkt_size, 0, "RED Medium packet size");
175 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, red_max_pkt_size,
176         CTLFLAG_RD, &red_max_pkt_size, 0, "RED Max packet size");
177 SYSCTL_PROC(_net_inet_ip_dummynet, OID_AUTO, hz, CTLTYPE_INT | CTLFLAG_RW,
178             0, 0, sysctl_dn_hz, "I", "Dummynet callout frequency");
179
180 static int config_pipe(struct dn_ioc_pipe *);
181 static int ip_dn_ctl(struct sockopt *sopt);
182
183 static void rt_unref(struct rtentry *);
184 static void dummynet_clock(systimer_t, struct intrframe *);
185 static void dummynet(struct netmsg *);
186 static void dummynet_flush(void);
187 static ip_dn_io_t dummynet_io;
188 static void dn_rule_delete(void *);
189
190 void dummynet_drain(void);      /* XXX unused */
191
192 static void
193 rt_unref(struct rtentry *rt)
194 {
195     if (rt == NULL)
196         return;
197     if (rt->rt_refcnt <= 0)
198         kprintf("-- warning, refcnt now %ld, decreasing\n", rt->rt_refcnt);
199     RTFREE(rt);
200 }
201
202 /*
203  * Heap management functions.
204  *
205  * In the heap, first node is element 0. Children of i are 2i+1 and 2i+2.
206  * Some macros help finding parent/children so we can optimize them.
207  *
208  * heap_init() is called to expand the heap when needed.
209  * Increment size in blocks of 16 entries.
210  * XXX failure to allocate a new element is a pretty bad failure
211  * as we basically stall a whole queue forever!!
212  * Returns 1 on error, 0 on success
213  */
214 #define HEAP_FATHER(x)          (((x) - 1) / 2)
215 #define HEAP_LEFT(x)            (2*(x) + 1)
216 #define HEAP_IS_LEFT(x)         ((x) & 1)
217 #define HEAP_RIGHT(x)           (2*(x) + 2)
218 #define HEAP_SWAP(a, b, buffer) { buffer = a; a = b; b = buffer; }
219 #define HEAP_INCREMENT          15
220
221 static int
222 heap_init(struct dn_heap *h, int new_size)
223 {
224     struct dn_heap_entry *p;
225
226     if (h->size >= new_size) {
227         kprintf("%s, Bogus call, have %d want %d\n", __func__,
228                 h->size, new_size);
229         return 0;
230     }
231
232     new_size = (new_size + HEAP_INCREMENT) & ~HEAP_INCREMENT;
233     p = kmalloc(new_size * sizeof(*p), M_DUMMYNET, M_WAITOK | M_ZERO);
234     if (h->size > 0) {
235         bcopy(h->p, p, h->size * sizeof(*p));
236         kfree(h->p, M_DUMMYNET);
237     }
238     h->p = p;
239     h->size = new_size;
240     return 0;
241 }
242
243 /*
244  * Insert element in heap. Normally, p != NULL, we insert p in
245  * a new position and bubble up.  If p == NULL, then the element is
246  * already in place, and key is the position where to start the
247  * bubble-up.
248  * Returns 1 on failure (cannot allocate new heap entry)
249  *
250  * If offset > 0 the position (index, int) of the element in the heap is
251  * also stored in the element itself at the given offset in bytes.
252  */
253 #define SET_OFFSET(heap, node) \
254     if (heap->offset > 0) \
255         *((int *)((char *)(heap->p[node].object) + heap->offset)) = node;
256
257 /*
258  * RESET_OFFSET is used for sanity checks. It sets offset to an invalid value.
259  */
260 #define RESET_OFFSET(heap, node) \
261     if (heap->offset > 0) \
262         *((int *)((char *)(heap->p[node].object) + heap->offset)) = -1;
263
264 static int
265 heap_insert(struct dn_heap *h, dn_key key1, void *p)
266 {
267     int son = h->elements;
268
269     if (p == NULL) {    /* Data already there, set starting point */
270         son = key1;
271     } else {            /* Insert new element at the end, possibly resize */
272         son = h->elements;
273         if (son == h->size) { /* Need resize... */
274             if (heap_init(h, h->elements + 1))
275                 return 1; /* Failure... */
276         }
277         h->p[son].object = p;
278         h->p[son].key = key1;
279         h->elements++;
280     }
281
282     while (son > 0) {   /* Bubble up */
283         int father = HEAP_FATHER(son);
284         struct dn_heap_entry tmp;
285
286         if (DN_KEY_LT(h->p[father].key, h->p[son].key))
287             break; /* Found right position */
288
289         /* 'son' smaller than 'father', swap and repeat */
290         HEAP_SWAP(h->p[son], h->p[father], tmp);
291         SET_OFFSET(h, son);
292         son = father;
293     }
294     SET_OFFSET(h, son);
295     return 0;
296 }
297
298 /*
299  * Remove top element from heap, or obj if obj != NULL
300  */
301 static void
302 heap_extract(struct dn_heap *h, void *obj)
303 {
304     int child, father, max = h->elements - 1;
305
306     if (max < 0) {
307         kprintf("warning, extract from empty heap 0x%p\n", h);
308         return;
309     }
310
311     father = 0; /* Default: move up smallest child */
312     if (obj != NULL) { /* Extract specific element, index is at offset */
313         if (h->offset <= 0)
314             panic("%s from middle not supported on this heap!!!\n", __func__);
315
316         father = *((int *)((char *)obj + h->offset));
317         if (father < 0 || father >= h->elements) {
318             panic("%s father %d out of bound 0..%d\n", __func__,
319                   father, h->elements);
320         }
321     }
322     RESET_OFFSET(h, father);
323
324     child = HEAP_LEFT(father);          /* Left child */
325     while (child <= max) {              /* Valid entry */
326         if (child != max && DN_KEY_LT(h->p[child + 1].key, h->p[child].key))
327             child = child + 1;          /* Take right child, otherwise left */
328         h->p[father] = h->p[child];
329         SET_OFFSET(h, father);
330         father = child;
331         child = HEAP_LEFT(child);       /* Left child for next loop */
332     }
333     h->elements--;
334     if (father != max) {
335         /*
336          * Fill hole with last entry and bubble up, reusing the insert code
337          */
338         h->p[father] = h->p[max];
339         heap_insert(h, father, NULL);   /* This one cannot fail */
340     }
341 }
342
343 /*
344  * heapify() will reorganize data inside an array to maintain the
345  * heap property.  It is needed when we delete a bunch of entries.
346  */
347 static void
348 heapify(struct dn_heap *h)
349 {
350     int i;
351
352     for (i = 0; i < h->elements; i++)
353         heap_insert(h, i , NULL);
354 }
355
356 /*
357  * Cleanup the heap and free data structure
358  */
359 static void
360 heap_free(struct dn_heap *h)
361 {
362     if (h->size > 0)
363         kfree(h->p, M_DUMMYNET);
364     bzero(h, sizeof(*h));
365 }
366
367 /*
368  * --- End of heap management functions ---
369  */
370
371 /*
372  * Scheduler functions:
373  *
374  * transmit_event() is called when the delay-line needs to enter
375  * the scheduler, either because of existing pkts getting ready,
376  * or new packets entering the queue.  The event handled is the delivery
377  * time of the packet.
378  *
379  * ready_event() does something similar with fixed-rate queues, and the
380  * event handled is the finish time of the head pkt.
381  *
382  * wfq_ready_event() does something similar with WF2Q queues, and the
383  * event handled is the start time of the head pkt.
384  *
385  * In all cases, we make sure that the data structures are consistent
386  * before passing pkts out, because this might trigger recursive
387  * invocations of the procedures.
388  */
389 static void
390 transmit_event(struct dn_pipe *pipe)
391 {
392     struct dn_pkt *pkt;
393
394     while ((pkt = pipe->head) && DN_KEY_LEQ(pkt->output_time, curr_time)) {
395         struct rtentry *rt;
396
397         /*
398          * First unlink, then call procedures, since ip_input() can invoke
399          * ip_output() and viceversa, thus causing nested calls
400          */
401         pipe->head = pkt->dn_next;
402
403         /*
404          * NOTE:
405          * 'pkt' should _not_ be touched after calling
406          * ip_output(), ip_input(), ether_demux() and ether_output_frame()
407          */
408         switch (pkt->dn_dir) {
409         case DN_TO_IP_OUT:
410             /*
411              * 'pkt' will be freed in ip_output, so we keep
412              * a reference of the 'rtentry' beforehand.
413              */
414             rt = pkt->ro.ro_rt;
415             ip_output(pkt->dn_m, NULL, NULL, 0, NULL, NULL);
416             rt_unref(rt);
417             break;
418
419         case DN_TO_IP_IN :
420             ip_input(pkt->dn_m);
421             break;
422
423         case DN_TO_ETH_DEMUX:
424             {
425                 struct mbuf *m = pkt->dn_m;
426                 struct ether_header *eh;
427
428                 if (m->m_len < ETHER_HDR_LEN &&
429                     (m = m_pullup(m, ETHER_HDR_LEN)) == NULL) {
430                     kprintf("dummynet: pullup fail, dropping pkt\n");
431                     break;
432                 }
433                 /*
434                  * Same as ether_input, make eh be a pointer into the mbuf
435                  */
436                 eh = mtod(m, struct ether_header *);
437                 m_adj(m, ETHER_HDR_LEN);
438                 ether_demux(NULL, eh, m);
439             }
440             break;
441
442         case DN_TO_ETH_OUT:
443             ether_output_frame(pkt->ifp, pkt->dn_m);
444             break;
445
446         default:
447             kprintf("dummynet: bad switch %d!\n", pkt->dn_dir);
448             m_freem(pkt->dn_m);
449             break;
450         }
451     }
452
453     /*
454      * If there are leftover packets, put into the heap for next event
455      */
456     if ((pkt = pipe->head)) {
457         /*
458          * XXX should check errors on heap_insert, by draining the
459          * whole pipe and hoping in the future we are more successful
460          */
461         heap_insert(&extract_heap, pkt->output_time, pipe);
462     }
463 }
464
465 /*
466  * The following macro computes how many ticks we have to wait
467  * before being able to transmit a packet. The credit is taken from
468  * either a pipe (WF2Q) or a flow_queue (per-flow queueing)
469  */
470 #define SET_TICKS(pkt, q, p)    \
471     (pkt->dn_m->m_pkthdr.len*8*dn_hz - (q)->numbytes + p->bandwidth - 1 ) / \
472             p->bandwidth;
473
474 /*
475  * Extract pkt from queue, compute output time (could be now)
476  * and put into delay line (p_queue)
477  */
478 static void
479 move_pkt(struct dn_pkt *pkt, struct dn_flow_queue *q,
480          struct dn_pipe *p, int len)
481 {
482     q->head = pkt->dn_next;
483     q->len--;
484     q->len_bytes -= len;
485
486     pkt->output_time = curr_time + p->delay;
487
488     if (p->head == NULL)
489         p->head = pkt;
490     else
491         p->tail->dn_next = pkt;
492     p->tail = pkt;
493     p->tail->dn_next = NULL;
494 }
495
496 /*
497  * ready_event() is invoked every time the queue must enter the
498  * scheduler, either because the first packet arrives, or because
499  * a previously scheduled event fired.
500  * On invokation, drain as many pkts as possible (could be 0) and then
501  * if there are leftover packets reinsert the pkt in the scheduler.
502  */
503 static void
504 ready_event(struct dn_flow_queue *q)
505 {
506     struct dn_pkt *pkt;
507     struct dn_pipe *p = q->fs->pipe;
508     int p_was_empty;
509
510     if (p == NULL) {
511         kprintf("ready_event- pipe is gone\n");
512         return;
513     }
514     p_was_empty = (p->head == NULL);
515
516     /*
517      * Schedule fixed-rate queues linked to this pipe:
518      * Account for the bw accumulated since last scheduling, then
519      * drain as many pkts as allowed by q->numbytes and move to
520      * the delay line (in p) computing output time.
521      * bandwidth==0 (no limit) means we can drain the whole queue,
522      * setting len_scaled = 0 does the job.
523      */
524     q->numbytes += (curr_time - q->sched_time) * p->bandwidth;
525     while ((pkt = q->head) != NULL) {
526         int len = pkt->dn_m->m_pkthdr.len;
527         int len_scaled = p->bandwidth ? len*8*dn_hz : 0;
528
529         if (len_scaled > q->numbytes)
530             break;
531         q->numbytes -= len_scaled;
532         move_pkt(pkt, q, p, len);
533     }
534
535     /*
536      * If we have more packets queued, schedule next ready event
537      * (can only occur when bandwidth != 0, otherwise we would have
538      * flushed the whole queue in the previous loop).
539      * To this purpose we record the current time and compute how many
540      * ticks to go for the finish time of the packet.
541      */
542     if ((pkt = q->head) != NULL) {      /* this implies bandwidth != 0 */
543         dn_key t = SET_TICKS(pkt, q, p); /* ticks i have to wait */
544
545         q->sched_time = curr_time;
546
547         /*
548          * XXX should check errors on heap_insert, and drain the whole
549          * queue on error hoping next time we are luckier.
550          */
551         heap_insert(&ready_heap, curr_time + t, q);
552     } else {    /* RED needs to know when the queue becomes empty */
553         q->q_time = curr_time;
554         q->numbytes = 0;
555     }
556
557     /*
558      * If the delay line was empty call transmit_event(p) now.
559      * Otherwise, the scheduler will take care of it.
560      */
561     if (p_was_empty)
562         transmit_event(p);
563 }
564
565 /*
566  * Called when we can transmit packets on WF2Q queues.  Take pkts out of
567  * the queues at their start time, and enqueue into the delay line.
568  * Packets are drained until p->numbytes < 0.  As long as
569  * len_scaled >= p->numbytes, the packet goes into the delay line
570  * with a deadline p->delay.  For the last packet, if p->numbytes < 0,
571  * there is an additional delay.
572  */
573 static void
574 ready_event_wfq(struct dn_pipe *p)
575 {
576     int p_was_empty = (p->head == NULL);
577     struct dn_heap *sch = &p->scheduler_heap;
578     struct dn_heap *neh = &p->not_eligible_heap;
579
580     p->numbytes += (curr_time - p->sched_time) * p->bandwidth;
581
582     /*
583      * While we have backlogged traffic AND credit, we need to do
584      * something on the queue.
585      */
586     while (p->numbytes >= 0 && (sch->elements > 0 || neh->elements > 0)) {
587         if (sch->elements > 0) { /* Have some eligible pkts to send out */
588             struct dn_flow_queue *q = sch->p[0].object;
589             struct dn_pkt *pkt = q->head;
590             struct dn_flow_set *fs = q->fs;
591             uint64_t len = pkt->dn_m->m_pkthdr.len;
592             int len_scaled = p->bandwidth ? len*8*dn_hz : 0;
593
594             heap_extract(sch, NULL);    /* Remove queue from heap */
595             p->numbytes -= len_scaled;
596             move_pkt(pkt, q, p, len);
597
598             p->V += (len << MY_M) / p->sum;     /* Update V */
599             q->S = q->F;                        /* Update start time */
600
601             if (q->len == 0) {  /* Flow not backlogged any more */
602                 fs->backlogged--;
603                 heap_insert(&p->idle_heap, q->F, q);
604             } else {            /* Still backlogged */
605                 /*
606                  * Update F and position in backlogged queue, then
607                  * put flow in not_eligible_heap (we will fix this later).
608                  */
609                 len = q->head->dn_m->m_pkthdr.len;
610                 q->F += (len << MY_M) / (uint64_t)fs->weight;
611                 if (DN_KEY_LEQ(q->S, p->V))
612                     heap_insert(neh, q->S, q);
613                 else
614                     heap_insert(sch, q->F, q);
615             }
616         }
617
618         /*
619          * Now compute V = max(V, min(S_i)).  Remember that all elements in
620          * sch have by definition S_i <= V so if sch is not empty, V is surely
621          * the max and we must not update it.  Conversely, if sch is empty
622          * we only need to look at neh.
623          */
624         if (sch->elements == 0 && neh->elements > 0)
625             p->V = MAX64(p->V, neh->p[0].key);
626
627         /*
628          * Move from neh to sch any packets that have become eligible
629          */
630         while (neh->elements > 0 && DN_KEY_LEQ(neh->p[0].key, p->V)) {
631             struct dn_flow_queue *q = neh->p[0].object;
632
633             heap_extract(neh, NULL);
634             heap_insert(sch, q->F, q);
635         }
636     }
637
638     if (sch->elements == 0 && neh->elements == 0 && p->numbytes >= 0 &&
639         p->idle_heap.elements > 0) {
640         /*
641          * No traffic and no events scheduled.  We can get rid of idle-heap.
642          */
643         int i;
644
645         for (i = 0; i < p->idle_heap.elements; i++) {
646             struct dn_flow_queue *q = p->idle_heap.p[i].object;
647
648             q->F = 0;
649             q->S = q->F + 1;
650         }
651         p->sum = 0;
652         p->V = 0;
653         p->idle_heap.elements = 0;
654     }
655
656     /*
657      * If we are getting clocks from dummynet and if we are under credit,
658      * schedule the next ready event.
659      * Also fix the delivery time of the last packet.
660      */
661     if (p->numbytes < 0) { /* This implies bandwidth>0 */
662         dn_key t = 0; /* Number of ticks i have to wait */
663
664         if (p->bandwidth > 0)
665             t = (p->bandwidth - 1 - p->numbytes) / p->bandwidth;
666         p->tail->output_time += t;
667         p->sched_time = curr_time;
668
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         heap_insert(&wfq_ready_heap, curr_time + t, p);
674     }
675
676     /*
677      * If the delay line was empty call transmit_event(p) now.
678      * Otherwise, the scheduler will take care of it.
679      */
680     if (p_was_empty)
681         transmit_event(p);
682 }
683
684 /*
685  * This is called once per tick, or dn_hz times per second.  It is used to
686  * increment the current tick counter and schedule expired events.
687  */
688 static void
689 dummynet(struct netmsg *msg)
690 {
691     void *p;
692     struct dn_heap *h;
693     struct dn_heap *heaps[3];
694     int i;
695     struct dn_pipe *pe;
696
697     heaps[0] = &ready_heap;             /* Fixed-rate queues */
698     heaps[1] = &wfq_ready_heap;         /* WF2Q queues */
699     heaps[2] = &extract_heap;           /* Delay line */
700
701     crit_enter();
702
703     /* Reply ASAP */
704     lwkt_replymsg(&msg->nm_lmsg, 0);
705
706     curr_time++;
707     for (i = 0; i < 3; i++) {
708         h = heaps[i];
709         while (h->elements > 0 && DN_KEY_LEQ(h->p[0].key, curr_time)) {
710             if (h->p[0].key > curr_time) {
711                 kprintf("-- dummynet: warning, heap %d is %d ticks late\n",
712                     i, (int)(curr_time - h->p[0].key));
713             }
714
715             p = h->p[0].object;         /* Store a copy before heap_extract */
716             heap_extract(h, NULL);      /* Need to extract before processing */
717
718             if (i == 0)
719                 ready_event(p);
720             else if (i == 1)
721                 ready_event_wfq(p);
722             else
723                 transmit_event(p);
724         }
725     }
726
727     /*
728      * Sweep pipes trying to expire idle flow_queues
729      */
730     for (pe = all_pipes; pe; pe = pe->next) {
731         if (pe->idle_heap.elements > 0 &&
732             DN_KEY_LT(pe->idle_heap.p[0].key, pe->V)) {
733             struct dn_flow_queue *q = pe->idle_heap.p[0].object;
734
735             heap_extract(&pe->idle_heap, NULL);
736             q->S = q->F + 1; /* Mark timestamp as invalid */
737             pe->sum -= q->fs->weight;
738         }
739     }
740
741     crit_exit();
742 }
743
744 /*
745  * Unconditionally expire empty queues in case of shortage.
746  * Returns the number of queues freed.
747  */
748 static int
749 expire_queues(struct dn_flow_set *fs)
750 {
751     struct dn_flow_queue *q, *prev;
752     int i, initial_elements = fs->rq_elements;
753
754     if (fs->last_expired == time_second)
755         return 0;
756
757     fs->last_expired = time_second;
758
759     for (i = 0; i <= fs->rq_size; i++) { /* Last one is overflow */
760         for (prev = NULL, q = fs->rq[i]; q != NULL;) {
761             if (q->head != NULL || q->S != q->F + 1) {
762                 prev = q;
763                 q = q->next;
764             } else {    /* Entry is idle, expire it */
765                 struct dn_flow_queue *old_q = q;
766
767                 if (prev != NULL)
768                     prev->next = q = q->next;
769                 else
770                     fs->rq[i] = q = q->next;
771                 fs->rq_elements-- ;
772                 kfree(old_q, M_DUMMYNET);
773             }
774         }
775     }
776     return initial_elements - fs->rq_elements;
777 }
778
779 /*
780  * If room, create a new queue and put at head of slot i;
781  * otherwise, create or use the default queue.
782  */
783 static struct dn_flow_queue *
784 create_queue(struct dn_flow_set *fs, int i)
785 {
786     struct dn_flow_queue *q;
787
788     if (fs->rq_elements > fs->rq_size * dn_max_ratio &&
789         expire_queues(fs) == 0) {
790         /*
791          * No way to get room, use or create overflow queue.
792          */
793         i = fs->rq_size;
794         if (fs->rq[i] != NULL)
795             return fs->rq[i];
796     }
797
798     q = kmalloc(sizeof(*q), M_DUMMYNET, M_INTWAIT | M_NULLOK | M_ZERO);
799     if (q == NULL)
800         return NULL;
801
802     q->fs = fs;
803     q->hash_slot = i;
804     q->next = fs->rq[i];
805     q->S = q->F + 1;   /* hack - mark timestamp as invalid */
806     fs->rq[i] = q;
807     fs->rq_elements++;
808
809     return q;
810 }
811
812 /*
813  * Given a flow_set and a pkt in last_pkt, find a matching queue
814  * after appropriate masking. The queue is moved to front
815  * so that further searches take less time.
816  */
817 static struct dn_flow_queue *
818 find_queue(struct dn_flow_set *fs, struct ipfw_flow_id *id)
819 {
820     struct dn_flow_queue *q, *prev;
821     int i = 0;
822
823     if (!(fs->flags_fs & DN_HAVE_FLOW_MASK)) {
824         q = fs->rq[0];
825     } else {
826         /* First, do the masking */
827         id->dst_ip &= fs->flow_mask.dst_ip;
828         id->src_ip &= fs->flow_mask.src_ip;
829         id->dst_port &= fs->flow_mask.dst_port;
830         id->src_port &= fs->flow_mask.src_port;
831         id->proto &= fs->flow_mask.proto;
832         id->flags = 0; /* we don't care about this one */
833
834         /* Then, hash function */
835         i = ((id->dst_ip) & 0xffff) ^
836             ((id->dst_ip >> 15) & 0xffff) ^
837             ((id->src_ip << 1) & 0xffff) ^
838             ((id->src_ip >> 16 ) & 0xffff) ^
839             (id->dst_port << 1) ^ (id->src_port) ^
840             (id->proto);
841         i = i % fs->rq_size;
842
843         /* Finally, scan the current list for a match */
844         searches++;
845         for (prev = NULL, q = fs->rq[i]; q;) {
846             search_steps++;
847             if (id->dst_ip == q->id.dst_ip &&
848                 id->src_ip == q->id.src_ip &&
849                 id->dst_port == q->id.dst_port &&
850                 id->src_port == q->id.src_port &&
851                 id->proto == q->id.proto &&
852                 id->flags == q->id.flags) {
853                 break; /* Found */
854             } else if (pipe_expire && q->head == NULL && q->S == q->F + 1) {
855                 /* Entry is idle and not in any heap, expire it */
856                 struct dn_flow_queue *old_q = q;
857
858                 if (prev != NULL)
859                     prev->next = q = q->next;
860                 else
861                     fs->rq[i] = q = q->next;
862                 fs->rq_elements--;
863                 kfree(old_q, M_DUMMYNET);
864                 continue;
865             }
866             prev = q;
867             q = q->next;
868         }
869         if (q && prev != NULL) { /* Found and not in front */
870             prev->next = q->next;
871             q->next = fs->rq[i];
872             fs->rq[i] = q;
873         }
874     }
875     if (q == NULL) {    /* No match, need to allocate a new entry */
876         q = create_queue(fs, i);
877         if (q != NULL)
878             q->id = *id;
879     }
880     return q;
881 }
882
883 static int
884 red_drops(struct dn_flow_set *fs, struct dn_flow_queue *q, int len)
885 {
886     /*
887      * RED algorithm
888      *
889      * RED calculates the average queue size (avg) using a low-pass filter
890      * with an exponential weighted (w_q) moving average:
891      *  avg  <-  (1-w_q) * avg + w_q * q_size
892      * where q_size is the queue length (measured in bytes or * packets).
893      *
894      * If q_size == 0, we compute the idle time for the link, and set
895      *  avg = (1 - w_q)^(idle/s)
896      * where s is the time needed for transmitting a medium-sized packet.
897      *
898      * Now, if avg < min_th the packet is enqueued.
899      * If avg > max_th the packet is dropped. Otherwise, the packet is
900      * dropped with probability P function of avg.
901      */
902
903     int64_t p_b = 0;
904     u_int q_size = (fs->flags_fs & DN_QSIZE_IS_BYTES) ? q->len_bytes : q->len;
905
906     DPRINTF("\n%d q: %2u ", (int)curr_time, q_size);
907
908     /* Average queue size estimation */
909     if (q_size != 0) {
910         /*
911          * Queue is not empty, avg <- avg + (q_size - avg) * w_q
912          */
913         int diff = SCALE(q_size) - q->avg;
914         int64_t v = SCALE_MUL((int64_t)diff, (int64_t)fs->w_q);
915
916         q->avg += (int)v;
917     } else {
918         /*
919          * Queue is empty, find for how long the queue has been
920          * empty and use a lookup table for computing
921          * (1 - * w_q)^(idle_time/s) where s is the time to send a
922          * (small) packet.
923          * XXX check wraps...
924          */
925         if (q->avg) {
926             u_int t = (curr_time - q->q_time) / fs->lookup_step;
927
928             q->avg = (t < fs->lookup_depth) ?
929                      SCALE_MUL(q->avg, fs->w_q_lookup[t]) : 0;
930         }
931     }
932     DPRINTF("avg: %u ", SCALE_VAL(q->avg));
933
934     /* Should i drop? */
935
936     if (q->avg < fs->min_th) {
937         /* Accept packet */
938         q->count = -1;
939         return 0;
940     }
941
942     if (q->avg >= fs->max_th) { /* Average queue >=  Max threshold */
943         if (fs->flags_fs & DN_IS_GENTLE_RED) {
944             /*
945              * According to Gentle-RED, if avg is greater than max_th the
946              * packet is dropped with a probability
947              *  p_b = c_3 * avg - c_4
948              * where c_3 = (1 - max_p) / max_th, and c_4 = 1 - 2 * max_p
949              */
950             p_b = SCALE_MUL((int64_t)fs->c_3, (int64_t)q->avg) - fs->c_4;
951         } else {
952             q->count = -1;
953             kprintf("- drop\n");
954             return 1;
955         }
956     } else if (q->avg > fs->min_th) {
957         /*
958          * We compute p_b using the linear dropping function p_b = c_1 *
959          * avg - c_2, where c_1 = max_p / (max_th - min_th), and c_2 =
960          * max_p * min_th / (max_th - min_th)
961          */
962         p_b = SCALE_MUL((int64_t)fs->c_1, (int64_t)q->avg) - fs->c_2;
963     }
964     if (fs->flags_fs & DN_QSIZE_IS_BYTES)
965         p_b = (p_b * len) / fs->max_pkt_size;
966
967     if (++q->count == 0) {
968         q->random = krandom() & 0xffff;
969     } else {
970         /*
971          * q->count counts packets arrived since last drop, so a greater
972          * value of q->count means a greater packet drop probability.
973          */
974         if (SCALE_MUL(p_b, SCALE((int64_t)q->count)) > q->random) {
975             q->count = 0;
976             DPRINTF("%s", "- red drop");
977             /* After a drop we calculate a new random value */
978             q->random = krandom() & 0xffff;
979             return 1;    /* Drop */
980         }
981     }
982     /* End of RED algorithm */
983     return 0; /* Accept */
984 }
985
986 static __inline struct dn_flow_set *
987 locate_flowset(int pipe_nr, struct ip_fw *rule)
988 {
989     ipfw_insn *cmd = rule->cmd + rule->act_ofs;
990     struct dn_flow_set *fs;
991
992     if (cmd->opcode == O_LOG)
993         cmd += F_LEN(cmd);
994
995     fs = ((ipfw_insn_pipe *)cmd)->pipe_ptr;
996     if (fs != NULL)
997         return fs;
998
999     if (cmd->opcode == O_QUEUE) {
1000         for (fs = all_flow_sets; fs && fs->fs_nr != pipe_nr; fs = fs->next)
1001             ;   /* EMPTY */
1002     } else {
1003         struct dn_pipe *p;
1004
1005         for (p = all_pipes; p && p->pipe_nr != pipe_nr; p = p->next)
1006             ;   /* EMPTY */
1007         if (p != NULL)
1008             fs = &p->fs;
1009     }
1010
1011     /* record for the future */
1012     ((ipfw_insn_pipe *)cmd)->pipe_ptr = fs;
1013     return fs;
1014 }
1015
1016 /*
1017  * Dummynet hook for packets.  Below 'pipe' is a pipe or a queue
1018  * depending on whether WF2Q or fixed bw is used.
1019  *
1020  * pipe_nr      pipe or queue the packet is destined for.
1021  * dir          where shall we send the packet after dummynet.
1022  * m            the mbuf with the packet
1023  * fwa->oif     the 'ifp' parameter from the caller.
1024  *              NULL in ip_input, destination interface in ip_output
1025  * fwa->ro      route parameter (only used in ip_output, NULL otherwise)
1026  * fwa->dst     destination address, only used by ip_output
1027  * fwa->rule    matching rule, in case of multiple passes
1028  * fwa->flags   flags from the caller, only used in ip_output
1029  */
1030 static int
1031 dummynet_io(struct mbuf *m, int pipe_nr, int dir, struct ip_fw_args *fwa)
1032 {
1033     struct dn_pkt *pkt;
1034     struct m_tag *tag;
1035     struct dn_flow_set *fs;
1036     struct dn_pipe *pipe;
1037     uint64_t len = m->m_pkthdr.len;
1038     struct dn_flow_queue *q = NULL;
1039     int is_pipe;
1040     ipfw_insn *cmd;
1041
1042     crit_enter();
1043
1044     cmd = fwa->rule->cmd + fwa->rule->act_ofs;
1045     if (cmd->opcode == O_LOG)
1046         cmd += F_LEN(cmd);
1047
1048     KASSERT(cmd->opcode == O_PIPE || cmd->opcode == O_QUEUE,
1049             ("Rule is not PIPE or QUEUE, opcode %d\n", cmd->opcode));
1050
1051     is_pipe = (cmd->opcode == O_PIPE);
1052     pipe_nr &= 0xffff;
1053
1054     /*
1055      * This is a dummynet rule, so we expect a O_PIPE or O_QUEUE rule
1056      */
1057     fs = locate_flowset(pipe_nr, fwa->rule);
1058     if (fs == NULL)
1059         goto dropit;    /* This queue/pipe does not exist! */
1060
1061     pipe = fs->pipe;
1062     if (pipe == NULL) { /* Must be a queue, try find a matching pipe */
1063         for (pipe = all_pipes; pipe && pipe->pipe_nr != fs->parent_nr;
1064              pipe = pipe->next)
1065             ;   /* EMPTY */
1066         if (pipe != NULL) {
1067             fs->pipe = pipe;
1068         } else {
1069             kprintf("No pipe %d for queue %d, drop pkt\n",
1070                     fs->parent_nr, fs->fs_nr);
1071             goto dropit;
1072         }
1073     }
1074
1075     q = find_queue(fs, &fwa->f_id);
1076     if (q == NULL)
1077         goto dropit;    /* Cannot allocate queue */
1078
1079     /*
1080      * Update statistics, then check reasons to drop pkt
1081      */
1082     q->tot_bytes += len;
1083     q->tot_pkts++;
1084
1085     if (fs->plr && krandom() < fs->plr)
1086         goto dropit;    /* Random pkt drop */
1087
1088     if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
1089         if (q->len_bytes > fs->qsize)
1090             goto dropit;        /* Queue size overflow */
1091     } else {
1092         if (q->len >= fs->qsize)
1093             goto dropit;        /* Queue count overflow */
1094     }
1095
1096     if ((fs->flags_fs & DN_IS_RED) && red_drops(fs, q, len))
1097         goto dropit;
1098
1099     /*
1100      * Build and enqueue packet + parameters
1101      */
1102     tag = m_tag_get(PACKET_TAG_DUMMYNET, sizeof(*pkt), MB_DONTWAIT /* XXX */);
1103     if (tag == NULL)
1104         goto dropit;
1105     m_tag_prepend(m, tag);
1106
1107     pkt = m_tag_data(tag);
1108     bzero(pkt, sizeof(*pkt)); /* XXX expensive to zero */
1109
1110     pkt->rule = fwa->rule;
1111     pkt->dn_next = NULL;
1112     pkt->dn_m = m;
1113     pkt->dn_dir = dir;
1114
1115     pkt->ifp = fwa->oif;
1116     if (dir == DN_TO_IP_OUT) {
1117         /*
1118          * We need to copy *ro because for ICMP pkts (and maybe others)
1119          * the caller passed a pointer into the stack; dst might also be
1120          * a pointer into *ro so it needs to be updated.
1121          */
1122         pkt->ro = *(fwa->ro);
1123         if (fwa->ro->ro_rt)
1124             fwa->ro->ro_rt->rt_refcnt++;
1125         if (fwa->dst == (struct sockaddr_in *)&fwa->ro->ro_dst) {
1126             /* 'dst' points into 'ro' */
1127             fwa->dst = (struct sockaddr_in *)&(pkt->ro.ro_dst);
1128         }
1129
1130         pkt->dn_dst = fwa->dst;
1131         pkt->flags = fwa->flags;
1132     }
1133     if (q->head == NULL)
1134         q->head = pkt;
1135     else
1136         q->tail->dn_next = pkt;
1137     q->tail = pkt;
1138     q->len++;
1139     q->len_bytes += len;
1140
1141     if (q->head != pkt) /* Flow was not idle, we are done */
1142         goto done;
1143
1144     /*
1145      * If we reach this point the flow was previously idle, so we need
1146      * to schedule it.  This involves different actions for fixed-rate
1147      * or WF2Q queues.
1148      */
1149     if (is_pipe) {
1150         /*
1151          * Fixed-rate queue: just insert into the ready_heap.
1152          */
1153         dn_key t = 0;
1154
1155         if (pipe->bandwidth)
1156             t = SET_TICKS(pkt, q, pipe);
1157
1158         q->sched_time = curr_time;
1159         if (t == 0)     /* Must process it now */
1160             ready_event(q);
1161         else
1162             heap_insert(&ready_heap, curr_time + t, q);
1163     } else {
1164         /*
1165          * WF2Q:
1166          * First, compute start time S: if the flow was idle (S=F+1)
1167          * set S to the virtual time V for the controlling pipe, and update
1168          * the sum of weights for the pipe; otherwise, remove flow from
1169          * idle_heap and set S to max(F, V).
1170          * Second, compute finish time F = S + len/weight.
1171          * Third, if pipe was idle, update V = max(S, V).
1172          * Fourth, count one more backlogged flow.
1173          */
1174         if (DN_KEY_GT(q->S, q->F)) { /* Means timestamps are invalid */
1175             q->S = pipe->V;
1176             pipe->sum += fs->weight; /* Add weight of new queue */
1177         } else {
1178             heap_extract(&pipe->idle_heap, q);
1179             q->S = MAX64(q->F, pipe->V);
1180         }
1181         q->F = q->S + (len << MY_M) / (uint64_t)fs->weight;
1182
1183         if (pipe->not_eligible_heap.elements == 0 &&
1184             pipe->scheduler_heap.elements == 0)
1185             pipe->V = MAX64(q->S, pipe->V);
1186
1187         fs->backlogged++;
1188
1189         /*
1190          * Look at eligibility.  A flow is not eligibile if S>V (when
1191          * this happens, it means that there is some other flow already
1192          * scheduled for the same pipe, so the scheduler_heap cannot be
1193          * empty).  If the flow is not eligible we just store it in the
1194          * not_eligible_heap.  Otherwise, we store in the scheduler_heap
1195          * and possibly invoke ready_event_wfq() right now if there is
1196          * leftover credit.
1197          * Note that for all flows in scheduler_heap (SCH), S_i <= V,
1198          * and for all flows in not_eligible_heap (NEH), S_i > V.
1199          * So when we need to compute max(V, min(S_i)) forall i in SCH+NEH,
1200          * we only need to look into NEH.
1201          */
1202         if (DN_KEY_GT(q->S, pipe->V)) { /* Not eligible */
1203             if (pipe->scheduler_heap.elements == 0)
1204                 kprintf("++ ouch! not eligible but empty scheduler!\n");
1205             heap_insert(&pipe->not_eligible_heap, q->S, q);
1206         } else {
1207             heap_insert(&pipe->scheduler_heap, q->F, q);
1208             if (pipe->numbytes >= 0) {  /* Pipe is idle */
1209                 if (pipe->scheduler_heap.elements != 1)
1210                     kprintf("*** OUCH! pipe should have been idle!\n");
1211                 DPRINTF("Waking up pipe %d at %d\n",
1212                         pipe->pipe_nr, (int)(q->F >> MY_M));
1213                 pipe->sched_time = curr_time;
1214                 ready_event_wfq(pipe);
1215             }
1216         }
1217     }
1218 done:
1219     crit_exit();
1220     return 0;
1221
1222 dropit:
1223     crit_exit();
1224     if (q)
1225         q->drops++;
1226     m_freem(m);
1227     return ((fs && (fs->flags_fs & DN_NOERROR)) ? 0 : ENOBUFS);
1228 }
1229
1230 /*
1231  * Below, the rt_unref is only needed when (pkt->dn_dir == DN_TO_IP_OUT)
1232  * Doing this would probably save us the initial bzero of dn_pkt
1233  */
1234 #define DN_FREE_PKT(pkt)        {               \
1235         struct dn_pkt *n = pkt;                 \
1236         pkt = n->dn_next;                       \
1237         rt_unref (n->ro.ro_rt);                 \
1238         m_freem(n->dn_m);       }
1239
1240 /*
1241  * Dispose all packets and flow_queues on a flow_set.
1242  * If all=1, also remove red lookup table and other storage,
1243  * including the descriptor itself.
1244  * For the one in dn_pipe MUST also cleanup ready_heap...
1245  */
1246 static void
1247 purge_flow_set(struct dn_flow_set *fs, int all)
1248 {
1249     int i;
1250
1251     for (i = 0; i <= fs->rq_size; i++) {
1252         struct dn_flow_queue *q, *qn;
1253
1254         for (q = fs->rq[i]; q; q = qn) {
1255             struct dn_pkt *pkt;
1256
1257             for (pkt = q->head; pkt;)
1258                 DN_FREE_PKT(pkt);
1259
1260             qn = q->next;
1261             kfree(q, M_DUMMYNET);
1262         }
1263         fs->rq[i] = NULL;
1264     }
1265     fs->rq_elements = 0;
1266
1267     if (all) {
1268         /* RED - free lookup table */
1269         if (fs->w_q_lookup)
1270             kfree(fs->w_q_lookup, M_DUMMYNET);
1271
1272         if (fs->rq)
1273             kfree(fs->rq, M_DUMMYNET);
1274
1275         /* If this fs is not part of a pipe, free it */
1276         if (fs->pipe && fs != &fs->pipe->fs)
1277             kfree(fs, M_DUMMYNET);
1278     }
1279 }
1280
1281 /*
1282  * Dispose all packets queued on a pipe (not a flow_set).
1283  * Also free all resources associated to a pipe, which is about
1284  * to be deleted.
1285  */
1286 static void
1287 purge_pipe(struct dn_pipe *pipe)
1288 {
1289     struct dn_pkt *pkt;
1290
1291     purge_flow_set(&pipe->fs, 1);
1292
1293     for (pkt = pipe->head; pkt;)
1294         DN_FREE_PKT(pkt);
1295
1296     heap_free(&pipe->scheduler_heap);
1297     heap_free(&pipe->not_eligible_heap);
1298     heap_free(&pipe->idle_heap);
1299 }
1300
1301 /*
1302  * Delete all pipes and heaps returning memory. Must also
1303  * remove references from all ipfw rules to all pipes.
1304  */
1305 static void
1306 dummynet_flush(void)
1307 {
1308     struct dn_pipe *p;
1309     struct dn_flow_set *fs;
1310
1311     crit_enter();
1312
1313     /* Remove all references to pipes ... */
1314     flush_pipe_ptrs(NULL);
1315
1316     /* Prevent future matches... */
1317     p = all_pipes;
1318     all_pipes = NULL;
1319     fs = all_flow_sets;
1320     all_flow_sets = NULL;
1321
1322     /* Free heaps so we don't have unwanted events */
1323     heap_free(&ready_heap);
1324     heap_free(&wfq_ready_heap);
1325     heap_free(&extract_heap);
1326
1327     crit_exit();
1328
1329     /*
1330      * Now purge all queued pkts and delete all pipes
1331      */
1332     /* Scan and purge all flow_sets. */
1333     while (fs != NULL) {
1334         struct dn_flow_set *curr_fs = fs;
1335
1336         fs = curr_fs->next;
1337         purge_flow_set(curr_fs, 1);
1338     }
1339     while (p != NULL) {
1340         struct dn_pipe *curr_p = p;
1341
1342         p = curr_p->next;
1343         purge_pipe(curr_p);
1344         kfree(curr_p, M_DUMMYNET);
1345     }
1346 }
1347
1348
1349 extern struct ip_fw *ip_fw_default_rule;
1350
1351 static void
1352 dn_rule_delete_fs(struct dn_flow_set *fs, void *r)
1353 {
1354     int i;
1355
1356     for (i = 0; i <= fs->rq_size; i++) { /* Last one is ovflow */
1357         struct dn_flow_queue *q;
1358
1359         for (q = fs->rq[i]; q; q = q->next) {
1360             struct dn_pkt *pkt;
1361
1362             for (pkt = q->head; pkt; pkt = pkt->dn_next) {
1363                 if (pkt->rule == r)
1364                     pkt->rule = ip_fw_default_rule;
1365             }
1366         }
1367     }
1368 }
1369
1370 /*
1371  * When a firewall rule is deleted, scan all queues and remove the flow-id
1372  * from packets matching this rule.
1373  */
1374 void
1375 dn_rule_delete(void *r)
1376 {
1377     struct dn_pipe *p;
1378     struct dn_flow_set *fs;
1379
1380     /*
1381      * If the rule references a queue (dn_flow_set), then scan
1382      * the flow set, otherwise scan pipes. Should do either, but doing
1383      * both does not harm.
1384      */
1385
1386     for (fs = all_flow_sets; fs; fs = fs->next)
1387         dn_rule_delete_fs(fs, r);
1388
1389     for (p = all_pipes; p; p = p->next) {
1390         struct dn_pkt *pkt;
1391
1392         fs = &p->fs;
1393         dn_rule_delete_fs(fs, r);
1394
1395         for (pkt = p->head; pkt; pkt = pkt->dn_next) {
1396             if (pkt->rule == r)
1397                 pkt->rule = ip_fw_default_rule;
1398         }
1399     }
1400 }
1401
1402 /*
1403  * setup RED parameters
1404  */
1405 static int
1406 config_red(const struct dn_ioc_flowset *ioc_fs, struct dn_flow_set *x)
1407 {
1408     int i;
1409
1410     x->w_q = ioc_fs->w_q;
1411     x->min_th = SCALE(ioc_fs->min_th);
1412     x->max_th = SCALE(ioc_fs->max_th);
1413     x->max_p = ioc_fs->max_p;
1414
1415     x->c_1 = ioc_fs->max_p / (ioc_fs->max_th - ioc_fs->min_th);
1416     x->c_2 = SCALE_MUL(x->c_1, SCALE(ioc_fs->min_th));
1417     if (x->flags_fs & DN_IS_GENTLE_RED) {
1418         x->c_3 = (SCALE(1) - ioc_fs->max_p) / ioc_fs->max_th;
1419         x->c_4 = (SCALE(1) - 2 * ioc_fs->max_p);
1420     }
1421
1422     /* If the lookup table already exist, free and create it again */
1423     if (x->w_q_lookup) {
1424         kfree(x->w_q_lookup, M_DUMMYNET);
1425         x->w_q_lookup = NULL ;
1426     }
1427
1428     if (red_lookup_depth == 0) {
1429         kprintf("net.inet.ip.dummynet.red_lookup_depth must be > 0\n");
1430         kfree(x, M_DUMMYNET);
1431         return EINVAL;
1432     }
1433     x->lookup_depth = red_lookup_depth;
1434     x->w_q_lookup = kmalloc(x->lookup_depth * sizeof(int),
1435                             M_DUMMYNET, M_WAITOK);
1436
1437     /* Fill the lookup table with (1 - w_q)^x */
1438     x->lookup_step = ioc_fs->lookup_step;
1439     x->lookup_weight = ioc_fs->lookup_weight;
1440
1441     x->w_q_lookup[0] = SCALE(1) - x->w_q;
1442     for (i = 1; i < x->lookup_depth; i++)
1443         x->w_q_lookup[i] = SCALE_MUL(x->w_q_lookup[i - 1], x->lookup_weight);
1444
1445     if (red_avg_pkt_size < 1)
1446         red_avg_pkt_size = 512;
1447     x->avg_pkt_size = red_avg_pkt_size;
1448
1449     if (red_max_pkt_size < 1)
1450         red_max_pkt_size = 1500;
1451     x->max_pkt_size = red_max_pkt_size;
1452
1453     return 0;
1454 }
1455
1456 static void
1457 alloc_hash(struct dn_flow_set *x, const struct dn_ioc_flowset *ioc_fs)
1458 {
1459     if (x->flags_fs & DN_HAVE_FLOW_MASK) {
1460         int l = ioc_fs->rq_size;
1461
1462         /* Allocate some slots */
1463         if (l == 0)
1464             l = dn_hash_size;
1465
1466         if (l < DN_MIN_HASH_SIZE)
1467             l = DN_MIN_HASH_SIZE;
1468         else if (l > DN_MAX_HASH_SIZE)
1469             l = DN_MAX_HASH_SIZE;
1470
1471         x->rq_size = l;
1472     } else {
1473         /* One is enough for null mask */
1474         x->rq_size = 1;
1475     }
1476     x->rq = kmalloc((1 + x->rq_size) * sizeof(struct dn_flow_queue *),
1477                     M_DUMMYNET, M_WAITOK | M_ZERO);
1478     x->rq_elements = 0;
1479 }
1480
1481 static void
1482 set_flowid_parms(struct ipfw_flow_id *id, const struct dn_ioc_flowid *ioc_id)
1483 {
1484     id->dst_ip = ioc_id->u.ip.dst_ip;
1485     id->src_ip = ioc_id->u.ip.src_ip;
1486     id->dst_port = ioc_id->u.ip.dst_port;
1487     id->src_port = ioc_id->u.ip.src_port;
1488     id->proto = ioc_id->u.ip.proto;
1489     id->flags = ioc_id->u.ip.flags;
1490 }
1491
1492 static void
1493 set_fs_parms(struct dn_flow_set *x, const struct dn_ioc_flowset *ioc_fs)
1494 {
1495     x->flags_fs = ioc_fs->flags_fs;
1496     x->qsize = ioc_fs->qsize;
1497     x->plr = ioc_fs->plr;
1498     set_flowid_parms(&x->flow_mask, &ioc_fs->flow_mask);
1499     if (x->flags_fs & DN_QSIZE_IS_BYTES) {
1500         if (x->qsize > 1024 * 1024)
1501             x->qsize = 1024 * 1024;
1502     } else {
1503         if (x->qsize == 0 || x->qsize > 100)
1504             x->qsize = 50;
1505     }
1506
1507     /* Configuring RED */
1508     if (x->flags_fs & DN_IS_RED)
1509         config_red(ioc_fs, x);  /* XXX should check errors */
1510 }
1511
1512 /*
1513  * setup pipe or queue parameters.
1514  */
1515
1516 static int
1517 config_pipe(struct dn_ioc_pipe *ioc_pipe)
1518 {
1519     struct dn_ioc_flowset *ioc_fs = &ioc_pipe->fs;
1520     int error;
1521
1522     /*
1523      * The config program passes parameters as follows:
1524      * bw       bits/second (0 means no limits)
1525      * delay    ms (must be translated into ticks)
1526      * qsize    slots or bytes
1527      */
1528     ioc_pipe->delay = (ioc_pipe->delay * dn_hz) / 1000;
1529
1530     /*
1531      * We need either a pipe number or a flow_set number
1532      */
1533     if (ioc_pipe->pipe_nr == 0 && ioc_fs->fs_nr == 0)
1534         return EINVAL;
1535     if (ioc_pipe->pipe_nr != 0 && ioc_fs->fs_nr != 0)
1536         return EINVAL;
1537
1538     crit_enter();
1539
1540     error = EINVAL;
1541     if (ioc_pipe->pipe_nr != 0) {       /* This is a pipe */
1542         struct dn_pipe *x, *a, *b;
1543
1544         /* Locate pipe */
1545         for (a = NULL, b = all_pipes; b && b->pipe_nr < ioc_pipe->pipe_nr;
1546              a = b, b = b->next)
1547             ;   /* EMPTY */
1548
1549         if (b == NULL || b->pipe_nr != ioc_pipe->pipe_nr) { /* New pipe */
1550             x = kmalloc(sizeof(struct dn_pipe), M_DUMMYNET, M_WAITOK | M_ZERO);
1551             x->pipe_nr = ioc_pipe->pipe_nr;
1552             x->fs.pipe = x;
1553
1554             /*
1555              * idle_heap is the only one from which we extract from the middle.
1556              */
1557             x->idle_heap.size = x->idle_heap.elements = 0;
1558             x->idle_heap.offset = __offsetof(struct dn_flow_queue, heap_pos);
1559         } else {
1560             int i;
1561
1562             x = b;
1563
1564             /* Flush accumulated credit for all queues */
1565             for (i = 0; i <= x->fs.rq_size; i++) {
1566                 struct dn_flow_queue *q;
1567
1568                 for (q = x->fs.rq[i]; q; q = q->next)
1569                     q->numbytes = 0;
1570             }
1571         }
1572
1573         x->bandwidth = ioc_pipe->bandwidth;
1574         x->numbytes = 0; /* Just in case... */
1575         x->delay = ioc_pipe->delay;
1576
1577         set_fs_parms(&x->fs, ioc_fs);
1578
1579         if (x->fs.rq == NULL) { /* A new pipe */
1580             alloc_hash(&x->fs, ioc_fs);
1581
1582             x->next = b;
1583             if (a == NULL)
1584                 all_pipes = x;
1585             else
1586                 a->next = x;
1587         }
1588     } else {    /* Config flow_set */
1589         struct dn_flow_set *x, *a, *b;
1590
1591         /* Locate flow_set */
1592         for (a = NULL, b = all_flow_sets; b && b->fs_nr < ioc_fs->fs_nr;
1593              a = b, b = b->next)
1594             ;   /* EMPTY */
1595
1596         if (b == NULL || b->fs_nr != ioc_fs->fs_nr) { /* New flow_set */
1597             if (ioc_fs->parent_nr == 0) /* Need link to a pipe */
1598                 goto back;
1599
1600             x = kmalloc(sizeof(struct dn_flow_set), M_DUMMYNET,
1601                         M_WAITOK | M_ZERO);
1602             x->fs_nr = ioc_fs->fs_nr;
1603             x->parent_nr = ioc_fs->parent_nr;
1604             x->weight = ioc_fs->weight;
1605             if (x->weight == 0)
1606                 x->weight = 1;
1607             else if (x->weight > 100)
1608                 x->weight = 100;
1609         } else {
1610             /* Change parent pipe not allowed; must delete and recreate */
1611             if (ioc_fs->parent_nr != 0 && b->parent_nr != ioc_fs->parent_nr)
1612                 goto back;
1613             x = b;
1614         }
1615
1616         set_fs_parms(x, ioc_fs);
1617
1618         if (x->rq == NULL) {    /* A new flow_set */
1619             alloc_hash(x, ioc_fs);
1620
1621             x->next = b;
1622             if (a == NULL)
1623                 all_flow_sets = x;
1624             else
1625                 a->next = x;
1626         }
1627     }
1628     error = 0;
1629
1630 back:
1631     crit_exit();
1632     return error;
1633 }
1634
1635 /*
1636  * Helper function to remove from a heap queues which are linked to
1637  * a flow_set about to be deleted.
1638  */
1639 static void
1640 fs_remove_from_heap(struct dn_heap *h, struct dn_flow_set *fs)
1641 {
1642     int i = 0, found = 0;
1643
1644     while (i < h->elements) {
1645         if (((struct dn_flow_queue *)h->p[i].object)->fs == fs) {
1646             h->elements--;
1647             h->p[i] = h->p[h->elements];
1648             found++;
1649         } else {
1650             i++;
1651         }
1652     }
1653     if (found)
1654         heapify(h);
1655 }
1656
1657 /*
1658  * helper function to remove a pipe from a heap (can be there at most once)
1659  */
1660 static void
1661 pipe_remove_from_heap(struct dn_heap *h, struct dn_pipe *p)
1662 {
1663     if (h->elements > 0) {
1664         int i;
1665
1666         for (i = 0; i < h->elements; i++) {
1667             if (h->p[i].object == p) { /* found it */
1668                 h->elements--;
1669                 h->p[i] = h->p[h->elements];
1670                 heapify(h);
1671                 break;
1672             }
1673         }
1674     }
1675 }
1676
1677 /*
1678  * drain all queues. Called in case of severe mbuf shortage.
1679  */
1680 void
1681 dummynet_drain(void)
1682 {
1683     struct dn_flow_set *fs;
1684     struct dn_pipe *p;
1685     struct dn_pkt *pkt;
1686
1687     heap_free(&ready_heap);
1688     heap_free(&wfq_ready_heap);
1689     heap_free(&extract_heap);
1690
1691     /* remove all references to this pipe from flow_sets */
1692     for (fs = all_flow_sets; fs; fs= fs->next)
1693         purge_flow_set(fs, 0);
1694
1695     for (p = all_pipes; p; p= p->next) {
1696         purge_flow_set(&p->fs, 0);
1697         for (pkt = p->head; pkt ;)
1698             DN_FREE_PKT(pkt);
1699         p->head = p->tail = NULL;
1700     }
1701 }
1702
1703 /*
1704  * Fully delete a pipe or a queue, cleaning up associated info.
1705  */
1706 static int
1707 delete_pipe(const struct dn_ioc_pipe *ioc_pipe)
1708 {
1709     int error;
1710
1711     if (ioc_pipe->pipe_nr == 0 && ioc_pipe->fs.fs_nr == 0)
1712         return EINVAL;
1713     if (ioc_pipe->pipe_nr != 0 && ioc_pipe->fs.fs_nr != 0)
1714         return EINVAL;
1715
1716     crit_enter();
1717
1718     error = EINVAL;
1719     if (ioc_pipe->pipe_nr != 0) {       /* This is an old-style pipe */
1720         struct dn_pipe *a, *b;
1721         struct dn_flow_set *fs;
1722
1723         /* Locate pipe */
1724         for (a = NULL, b = all_pipes; b && b->pipe_nr < ioc_pipe->pipe_nr;
1725              a = b, b = b->next)
1726             ;   /* EMPTY */
1727         if (b == NULL || b->pipe_nr != ioc_pipe->pipe_nr)
1728             goto back; /* Not found */
1729
1730         /* Unlink from list of pipes */
1731         if (a == NULL)
1732             all_pipes = b->next;
1733         else
1734             a->next = b->next;
1735
1736         /* Remove references to this pipe from the ip_fw rules. */
1737         flush_pipe_ptrs(&b->fs);
1738
1739         /* Remove all references to this pipe from flow_sets */
1740         for (fs = all_flow_sets; fs; fs = fs->next) {
1741             if (fs->pipe == b) {
1742                 kprintf("++ ref to pipe %d from fs %d\n",
1743                         ioc_pipe->pipe_nr, fs->fs_nr);
1744                 fs->pipe = NULL;
1745                 purge_flow_set(fs, 0);
1746             }
1747         }
1748         fs_remove_from_heap(&ready_heap, &b->fs);
1749         purge_pipe(b);  /* Remove all data associated to this pipe */
1750
1751         /* Remove reference to here from extract_heap and wfq_ready_heap */
1752         pipe_remove_from_heap(&extract_heap, b);
1753         pipe_remove_from_heap(&wfq_ready_heap, b);
1754
1755         kfree(b, M_DUMMYNET);
1756     } else {    /* This is a WF2Q queue (dn_flow_set) */
1757         struct dn_flow_set *a, *b;
1758
1759         /* Locate flow_set */
1760         for (a = NULL, b = all_flow_sets; b && b->fs_nr < ioc_pipe->fs.fs_nr;
1761              a = b, b = b->next)
1762             ;   /* EMPTY */
1763         if (b == NULL || b->fs_nr != ioc_pipe->fs.fs_nr)
1764             goto back; /* Not found */
1765
1766         if (a == NULL)
1767             all_flow_sets = b->next;
1768         else
1769             a->next = b->next;
1770
1771         /* Remove references to this flow_set from the ip_fw rules. */
1772         flush_pipe_ptrs(b);
1773
1774         if (b->pipe != NULL) {
1775             /* Update total weight on parent pipe and cleanup parent heaps */
1776             b->pipe->sum -= b->weight * b->backlogged;
1777             fs_remove_from_heap(&b->pipe->not_eligible_heap, b);
1778             fs_remove_from_heap(&b->pipe->scheduler_heap, b);
1779 #if 1   /* XXX should i remove from idle_heap as well ? */
1780             fs_remove_from_heap(&b->pipe->idle_heap, b);
1781 #endif
1782         }
1783         purge_flow_set(b, 1);
1784     }
1785     error = 0;
1786
1787 back:
1788     crit_exit();
1789     return error;
1790 }
1791
1792 /*
1793  * helper function used to copy data from kernel in DUMMYNET_GET
1794  */
1795 static void
1796 dn_copy_flowid(const struct ipfw_flow_id *id, struct dn_ioc_flowid *ioc_id)
1797 {
1798     ioc_id->type = ETHERTYPE_IP;
1799     ioc_id->u.ip.dst_ip = id->dst_ip;
1800     ioc_id->u.ip.src_ip = id->src_ip;
1801     ioc_id->u.ip.dst_port = id->dst_port;
1802     ioc_id->u.ip.src_port = id->src_port;
1803     ioc_id->u.ip.proto = id->proto;
1804     ioc_id->u.ip.flags = id->flags;
1805 }
1806
1807 static void *
1808 dn_copy_flowqueues(const struct dn_flow_set *fs, void *bp)
1809 {
1810     const struct dn_flow_queue *q;
1811     struct dn_ioc_flowqueue *ioc_fq = bp;
1812     int i, copied = 0;
1813
1814     for (i = 0; i <= fs->rq_size; i++) {
1815         for (q = fs->rq[i]; q; q = q->next, ioc_fq++) {
1816             if (q->hash_slot != i) {    /* XXX ASSERT */
1817                 kprintf("++ at %d: wrong slot (have %d, "
1818                         "should be %d)\n", copied, q->hash_slot, i);
1819             }
1820             if (q->fs != fs) {          /* XXX ASSERT */
1821                 kprintf("++ at %d: wrong fs ptr (have %p, should be %p)\n",
1822                         i, q->fs, fs);
1823             }
1824
1825             copied++;
1826
1827             ioc_fq->len = q->len;
1828             ioc_fq->len_bytes = q->len_bytes;
1829             ioc_fq->tot_pkts = q->tot_pkts;
1830             ioc_fq->tot_bytes = q->tot_bytes;
1831             ioc_fq->drops = q->drops;
1832             ioc_fq->hash_slot = q->hash_slot;
1833             ioc_fq->S = q->S;
1834             ioc_fq->F = q->F;
1835             dn_copy_flowid(&q->id, &ioc_fq->id);
1836         }
1837     }
1838
1839     if (copied != fs->rq_elements) {    /* XXX ASSERT */
1840         kprintf("++ wrong count, have %d should be %d\n",
1841                 copied, fs->rq_elements);
1842     }
1843     return ioc_fq;
1844 }
1845
1846 static void
1847 dn_copy_flowset(const struct dn_flow_set *fs, struct dn_ioc_flowset *ioc_fs,
1848                 u_short fs_type)
1849 {
1850     ioc_fs->fs_type = fs_type;
1851
1852     ioc_fs->fs_nr = fs->fs_nr;
1853     ioc_fs->flags_fs = fs->flags_fs;
1854     ioc_fs->parent_nr = fs->parent_nr;
1855
1856     ioc_fs->weight = fs->weight;
1857     ioc_fs->qsize = fs->qsize;
1858     ioc_fs->plr = fs->plr;
1859
1860     ioc_fs->rq_size = fs->rq_size;
1861     ioc_fs->rq_elements = fs->rq_elements;
1862
1863     ioc_fs->w_q = fs->w_q;
1864     ioc_fs->max_th = fs->max_th;
1865     ioc_fs->min_th = fs->min_th;
1866     ioc_fs->max_p = fs->max_p;
1867
1868     dn_copy_flowid(&fs->flow_mask, &ioc_fs->flow_mask);
1869 }
1870
1871 static int
1872 dummynet_get(struct sockopt *sopt)
1873 {
1874     struct dn_flow_set *fs;
1875     struct dn_pipe *pipe;
1876     char *buf, *bp;
1877     size_t size = 0;
1878     int error = 0;
1879
1880     crit_enter();
1881
1882     /*
1883      * Compute size of data structures: list of pipes and flow_sets.
1884      */
1885     for (pipe = all_pipes; pipe; pipe = pipe->next) {
1886         size += sizeof(struct dn_ioc_pipe) +
1887             pipe->fs.rq_elements * sizeof(struct dn_ioc_flowqueue);
1888     }
1889
1890     for (fs = all_flow_sets; fs; fs = fs->next) {
1891         size += sizeof(struct dn_ioc_flowset) +
1892             fs->rq_elements * sizeof(struct dn_ioc_flowqueue);
1893     }
1894
1895     bp = buf = kmalloc(size, M_TEMP, M_WAITOK | M_ZERO);
1896
1897     for (pipe = all_pipes; pipe; pipe = pipe->next) {
1898         struct dn_ioc_pipe *ioc_pipe = (struct dn_ioc_pipe *)bp;
1899
1900         /*
1901          * Copy flow set descriptor associated with this pipe
1902          */
1903         dn_copy_flowset(&pipe->fs, &ioc_pipe->fs, DN_IS_PIPE);
1904
1905         /*
1906          * Copy pipe descriptor
1907          */
1908         ioc_pipe->bandwidth = pipe->bandwidth;
1909         ioc_pipe->pipe_nr = pipe->pipe_nr;
1910         ioc_pipe->V = pipe->V;
1911         /* Convert delay to milliseconds */
1912         ioc_pipe->delay = (pipe->delay * 1000) / dn_hz;
1913
1914         /*
1915          * Copy flow queue descriptors
1916          */
1917         bp += sizeof(*ioc_pipe);
1918         bp = dn_copy_flowqueues(&pipe->fs, bp);
1919     }
1920
1921     for (fs = all_flow_sets; fs; fs = fs->next) {
1922         struct dn_ioc_flowset *ioc_fs = (struct dn_ioc_flowset *)bp;
1923
1924         /*
1925          * Copy flow set descriptor
1926          */
1927         dn_copy_flowset(fs, ioc_fs, DN_IS_QUEUE);
1928
1929         /*
1930          * Copy flow queue descriptors
1931          */
1932         bp += sizeof(*ioc_fs);
1933         bp = dn_copy_flowqueues(fs, bp);
1934     }
1935
1936     crit_exit();
1937
1938     error = sooptcopyout(sopt, buf, size);
1939     kfree(buf, M_TEMP);
1940     return error;
1941 }
1942
1943 /*
1944  * Handler for the various dummynet socket options (get, flush, config, del)
1945  */
1946 static int
1947 ip_dn_ctl(struct sockopt *sopt)
1948 {
1949     struct dn_ioc_pipe tmp_ioc_pipe;
1950     int error = 0;
1951
1952     /* Disallow sets in really-really secure mode. */
1953     if (sopt->sopt_dir == SOPT_SET) {
1954         if (securelevel >= 3)
1955             return EPERM;
1956     }
1957
1958     switch (sopt->sopt_name) {
1959     case IP_DUMMYNET_GET:
1960         error = dummynet_get(sopt);
1961         break;
1962
1963     case IP_DUMMYNET_FLUSH:
1964         dummynet_flush();
1965         break;
1966
1967     case IP_DUMMYNET_CONFIGURE:
1968         error = sooptcopyin(sopt, &tmp_ioc_pipe, sizeof(tmp_ioc_pipe),
1969                             sizeof(tmp_ioc_pipe));
1970         if (error)
1971             break;
1972         error = config_pipe(&tmp_ioc_pipe);
1973         break;
1974
1975     case IP_DUMMYNET_DEL:       /* Remove a pipe or flow_set */
1976         error = sooptcopyin(sopt, &tmp_ioc_pipe, sizeof(tmp_ioc_pipe),
1977                             sizeof(tmp_ioc_pipe));
1978         if (error)
1979             break;
1980         error = delete_pipe(&tmp_ioc_pipe);
1981         break;
1982
1983     default:
1984         kprintf("%s -- unknown option %d\n", __func__, sopt->sopt_name);
1985         error = EINVAL;
1986         break;
1987     }
1988     return error;
1989 }
1990
1991 static void
1992 dummynet_clock(systimer_t info __unused, struct intrframe *frame __unused)
1993 {
1994     KASSERT(mycpu->gd_cpuid == dn_cpu,
1995             ("systimer comes on a different cpu!\n"));
1996
1997     crit_enter();
1998     if (dn_netmsg.nm_lmsg.ms_flags & MSGF_DONE)
1999         lwkt_sendmsg(cpu_portfn(mycpu->gd_cpuid), &dn_netmsg.nm_lmsg);
2000     crit_exit();
2001 }
2002
2003 static int
2004 sysctl_dn_hz(SYSCTL_HANDLER_ARGS)
2005 {
2006     int error, val;
2007
2008     val = dn_hz;
2009     error = sysctl_handle_int(oidp, &val, 0, req);
2010     if (error || req->newptr == NULL)
2011         return error;
2012     if (val <= 0)
2013         return EINVAL;
2014     else if (val > DN_CALLOUT_FREQ_MAX)
2015         val = DN_CALLOUT_FREQ_MAX;
2016
2017     crit_enter();
2018     dn_hz = val;
2019     systimer_adjust_periodic(&dn_clock, val);
2020     crit_exit();
2021
2022     return 0;
2023 }
2024
2025 static void
2026 ip_dn_register_systimer(struct netmsg *msg)
2027 {
2028     systimer_init_periodic_nq(&dn_clock, dummynet_clock, NULL, dn_hz);
2029     lwkt_replymsg(&msg->nm_lmsg, 0);
2030 }
2031
2032 static void
2033 ip_dn_deregister_systimer(struct netmsg *msg)
2034 {
2035     systimer_del(&dn_clock);
2036     lwkt_replymsg(&msg->nm_lmsg, 0);
2037 }
2038
2039 static void
2040 ip_dn_init(void)
2041 {
2042     struct netmsg smsg;
2043     lwkt_port_t port;
2044
2045     kprintf("DUMMYNET initialized (011031)\n");
2046
2047     all_pipes = NULL;
2048     all_flow_sets = NULL;
2049
2050     ready_heap.size = ready_heap.elements = 0;
2051     ready_heap.offset = 0;
2052
2053     wfq_ready_heap.size = wfq_ready_heap.elements = 0;
2054     wfq_ready_heap.offset = 0;
2055
2056     extract_heap.size = extract_heap.elements = 0;
2057     extract_heap.offset = 0;
2058
2059     ip_dn_ctl_ptr = ip_dn_ctl;
2060     ip_dn_io_ptr = dummynet_io;
2061     ip_dn_ruledel_ptr = dn_rule_delete;
2062
2063     netmsg_init(&dn_netmsg, &netisr_adone_rport, 0, dummynet);
2064
2065     netmsg_init(&smsg, &curthread->td_msgport, 0, ip_dn_register_systimer);
2066     port = cpu_portfn(dn_cpu);
2067     lwkt_domsg(port, &smsg.nm_lmsg, 0);
2068 }
2069
2070 static void
2071 ip_dn_stop(void)
2072 {
2073     struct netmsg smsg;
2074     lwkt_port_t port;
2075
2076     netmsg_init(&smsg, &curthread->td_msgport, 0, ip_dn_deregister_systimer);
2077     port = cpu_portfn(dn_cpu);
2078     lwkt_domsg(port, &smsg.nm_lmsg, 0);
2079
2080     dummynet_flush();
2081
2082     ip_dn_ctl_ptr = NULL;
2083     ip_dn_io_ptr = NULL;
2084     ip_dn_ruledel_ptr = NULL;
2085
2086     netmsg_service_sync();
2087 }
2088
2089 static int
2090 dummynet_modevent(module_t mod, int type, void *data)
2091 {
2092     switch (type) {
2093     case MOD_LOAD:
2094         crit_enter();
2095         if (DUMMYNET_LOADED) {
2096             crit_exit();
2097             kprintf("DUMMYNET already loaded\n");
2098             return EEXIST;
2099         }
2100         ip_dn_init();
2101         crit_exit();
2102         break;
2103     
2104     case MOD_UNLOAD:
2105 #ifndef KLD_MODULE
2106         kprintf("dummynet statically compiled, cannot unload\n");
2107         return EINVAL ;
2108 #else
2109         crit_enter();
2110         ip_dn_stop();
2111         crit_exit();
2112 #endif
2113         break;
2114
2115     default:
2116         break;
2117     }
2118     return 0;
2119 }
2120
2121 static moduledata_t dummynet_mod = {
2122     "dummynet",
2123     dummynet_modevent,
2124     NULL
2125 };
2126 DECLARE_MODULE(dummynet, dummynet_mod, SI_SUB_PROTO_END, SI_ORDER_ANY);
2127 MODULE_DEPEND(dummynet, ipfw, 1, 1, 1);
2128 MODULE_VERSION(dummynet, 1);