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