Clean up
[dragonfly.git] / sys / net / dummynet / ip_dummynet.h
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.h,v 1.10.2.9 2003/05/13 09:31:06 maxim Exp $
28  * $DragonFly: src/sys/net/dummynet/ip_dummynet.h,v 1.10 2007/11/02 06:27:24 sephe Exp $
29  */
30
31 #ifndef _IP_DUMMYNET_H
32 #define _IP_DUMMYNET_H
33
34 /*
35  * Definition of dummynet data structures. In the structures, I decided
36  * not to use the macros in <sys/queue.h> in the hope of making the code
37  * easier to port to other architectures. The type of lists and queue we
38  * use here is pretty simple anyways.
39  */
40
41 /*
42  * We start with a heap, which is used in the scheduler to decide when
43  * to transmit packets etc.
44  *
45  * The key for the heap is used for two different values:
46  *
47  * 1. timer ticks- max 10K/second, so 32 bits are enough;
48  *
49  * 2. virtual times. These increase in steps of len/x, where len is the
50  *    packet length, and x is either the weight of the flow, or the
51  *    sum of all weights.
52  *    If we limit to max 1000 flows and a max weight of 100, then
53  *    x needs 17 bits. The packet size is 16 bits, so we can easily
54  *    overflow if we do not allow errors.
55  * So we use a key "dn_key" which is 64 bits. Some macros are used to
56  * compare key values and handle wraparounds.
57  * MAX64 returns the largest of two key values.
58  * MY_M is used as a shift count when doing fixed point arithmetic
59  * (a better name would be useful...).
60  */
61 typedef uint64_t dn_key;        /* sorting key */
62 #define DN_KEY_LT(a,b)  ((int64_t)((a)-(b)) < 0)
63 #define DN_KEY_LEQ(a,b) ((int64_t)((a)-(b)) <= 0)
64 #define DN_KEY_GT(a,b)  ((int64_t)((a)-(b)) > 0)
65 #define DN_KEY_GEQ(a,b) ((int64_t)((a)-(b)) >= 0)
66 #define MAX64(x,y)      (((int64_t)((y) - (x))) > 0) ? (y) : (x)
67 #define MY_M    16 /* number of left shift to obtain a larger precision */
68
69 /*
70  * XXX With this scaling, max 1000 flows, max weight 100, 1Gbit/s, the
71  * virtual time wraps every 15 days.
72  */
73
74 /*
75  * The maximum/minimum hash table size for queues.
76  * These values must be a power of 2.
77  */
78 #define DN_MIN_HASH_SIZE        4
79 #define DN_MAX_HASH_SIZE        65536
80
81 /*
82  * A heap entry is made of a key and a pointer to the actual
83  * object stored in the heap.
84  * The heap is an array of dn_heap_entry entries, dynamically allocated.
85  * Current size is "size", with "elements" actually in use.
86  * The heap normally supports only ordered insert and extract from the top.
87  * If we want to extract an object from the middle of the heap, we
88  * have to know where the object itself is located in the heap (or we
89  * need to scan the whole array). To this purpose, an object has a
90  * field (int) which contains the index of the object itself into the
91  * heap. When the object is moved, the field must also be updated.
92  * The offset of the index in the object is stored in the 'offset'
93  * field in the heap descriptor. The assumption is that this offset
94  * is non-zero if we want to support extract from the middle.
95  */
96 struct dn_heap_entry {
97     dn_key key;         /* sorting key. Topmost element is smallest one */
98     void *object;       /* object pointer */
99 };
100
101 struct dn_heap {
102     int size;
103     int elements;
104     int offset; /* XXX if > 0 this is the offset of direct ptr to obj */
105     struct dn_heap_entry *p;    /* really an array of "size" entries */
106 };
107
108 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
109
110 /*
111  * struct dn_pkt identifies a packet in the dummynet queue, but
112  * is also used to tag packets passed back to the various destinations
113  * (ip_input(), ip_output()  and so on).
114  * It is a tag(PACKET_TAG_DUMMYNET) associated with the actual mbuf.
115  */
116 struct dn_pkt {
117     struct mbuf *dn_m;
118     struct dn_pkt *dn_next;
119
120     struct ip_fw *rule;         /* matching rule */
121     int dn_dir;                 /* action when packet comes out. */
122 #define DN_TO_IP_OUT    1
123 #define DN_TO_IP_IN     2
124 #define DN_TO_ETH_DEMUX 4
125 #define DN_TO_ETH_OUT   5
126
127     dn_key output_time;         /* when the pkt is due for delivery */
128     struct ifnet *ifp;          /* interface, for ip_output */
129     struct sockaddr_in *dn_dst;
130     struct route ro;            /* route, for ip_output. MUST COPY */
131     int flags;                  /* flags, for ip_output (IPv6 ?) */
132 };
133
134 #endif
135
136 /*
137  * Overall structure of dummynet (with WF2Q+):
138  * 
139  * In dummynet, packets are selected with the firewall rules, and passed
140  * to two different objects: PIPE or QUEUE.
141  * 
142  * A QUEUE is just a queue with configurable size and queue management
143  * policy. It is also associated with a mask (to discriminate among
144  * different flows), a weight (used to give different shares of the
145  * bandwidth to different flows) and a "pipe", which essentially
146  * supplies the transmit clock for all queues associated with that
147  * pipe.
148  * 
149  * A PIPE emulates a fixed-bandwidth link, whose bandwidth is
150  * configurable.  The "clock" for a pipe can come from either an
151  * internal timer, or from the transmit interrupt of an interface.
152  * A pipe is also associated with one (or more, if masks are used)
153  * queue, where all packets for that pipe are stored.
154  * 
155  * The bandwidth available on the pipe is shared by the queues
156  * associated with that pipe (only one in case the packet is sent
157  * to a PIPE) according to the WF2Q+ scheduling algorithm and the
158  * configured weights.
159  * 
160  * In general, incoming packets are stored in the appropriate queue,
161  * which is then placed into one of a few heaps managed by a scheduler
162  * to decide when the packet should be extracted.
163  * The scheduler (a function called dummynet()) is run at every timer
164  * tick, and grabs queues from the head of the heaps when they are
165  * ready for processing.
166  * 
167  * There are three data structures definining a pipe and associated queues:
168  * 
169  *  + dn_pipe, which contains the main configuration parameters related
170  *    to delay and bandwidth;
171  *  + dn_flow_set, which contains WF2Q+ configuration, flow
172  *    masks, plr and RED configuration;
173  *  + dn_flow_queue, which is the per-flow queue (containing the packets)
174  * 
175  * Multiple dn_flow_set can be linked to the same pipe, and multiple
176  * dn_flow_queue can be linked to the same dn_flow_set.
177  * All data structures are linked in a linear list which is used for
178  * housekeeping purposes.
179  * 
180  * During configuration, we create and initialize the dn_flow_set
181  * and dn_pipe structures (a dn_pipe also contains a dn_flow_set).
182  * 
183  * At runtime: packets are sent to the appropriate dn_flow_set (either
184  * WFQ ones, or the one embedded in the dn_pipe for fixed-rate flows),
185  * which in turn dispatches them to the appropriate dn_flow_queue
186  * (created dynamically according to the masks).
187  * 
188  * The transmit clock for fixed rate flows (ready_event()) selects the
189  * dn_flow_queue to be used to transmit the next packet. For WF2Q,
190  * wfq_ready_event() extract a pipe which in turn selects the right
191  * flow using a number of heaps defined into the pipe itself.
192  */
193
194 /*
195  * per flow queue. This contains the flow identifier, the queue
196  * of packets, counters, and parameters used to support both RED and
197  * WF2Q+.
198  *
199  * A dn_flow_queue is created and initialized whenever a packet for
200  * a new flow arrives.
201  */
202 struct dn_flow_queue {
203     struct dn_flow_queue *next;
204     struct ipfw_flow_id id;
205
206     struct dn_pkt *head, *tail; /* queue of packets */
207     u_int len;
208     u_int len_bytes;
209     u_long numbytes;            /* credit for transmission (dynamic queues) */
210
211     uint64_t tot_pkts;          /* statistics counters */
212     uint64_t tot_bytes;
213     uint32_t drops;
214
215     int hash_slot;              /* debugging/diagnostic */
216
217     /* RED parameters */
218     int avg;                    /* average queue length est. (scaled) */
219     int count;                  /* arrivals since last RED drop */
220     int random;                 /* random value (scaled) */
221     uint32_t q_time;            /* start of queue idle time */
222
223     /* WF2Q+ support */
224     struct dn_flow_set *fs;     /* parent flow set */
225     int heap_pos;               /* position (index) of struct in heap */
226     dn_key sched_time;          /* current time when queue enters ready_heap */
227
228     dn_key S, F;                /* start time, finish time */
229     /*
230      * Setting F < S means the timestamp is invalid. We only need
231      * to test this when the queue is empty.
232      */
233 };
234
235 /*
236  * flow_set descriptor. Contains the "template" parameters for the
237  * queue configuration, and pointers to the hash table of dn_flow_queue's.
238  *
239  * The hash table is an array of lists -- we identify the slot by
240  * hashing the flow-id, then scan the list looking for a match.
241  * The size of the hash table (buckets) is configurable on a per-queue
242  * basis.
243  *
244  * A dn_flow_set is created whenever a new queue or pipe is created (in the
245  * latter case, the structure is located inside the struct dn_pipe).
246  */
247 struct dn_flow_set {
248     struct dn_flow_set *next;   /* next flow set in all_flow_sets list */
249
250     u_short fs_nr;              /* flow_set number */
251     u_short flags_fs;
252 #define DN_HAVE_FLOW_MASK       0x0001
253 #define DN_IS_RED               0x0002
254 #define DN_IS_GENTLE_RED        0x0004
255 #define DN_QSIZE_IS_BYTES       0x0008  /* queue size is measured in bytes */
256 #define DN_NOERROR              0x0010  /* do not report ENOBUFS on drops */
257 #define DN_IS_PIPE              0x4000
258 #define DN_IS_QUEUE             0x8000
259
260     struct dn_pipe *pipe;       /* pointer to parent pipe */
261     u_short parent_nr;          /* parent pipe#, 0 if local to a pipe */
262
263     int weight;                 /* WFQ queue weight */
264     int qsize;                  /* queue size in slots or bytes */
265     int plr;                    /* pkt loss rate (2^31-1 means 100%) */
266
267     struct ipfw_flow_id flow_mask;
268
269     /* hash table of queues onto this flow_set */
270     int rq_size;                /* number of slots */
271     int rq_elements;            /* active elements */
272     struct dn_flow_queue **rq;  /* array of rq_size entries */
273
274     uint32_t last_expired;      /* do not expire too frequently */
275     int backlogged;             /* #active queues for this flowset */
276
277     /* RED parameters */
278 #define SCALE_RED               16
279 #define SCALE(x)                ((x) << SCALE_RED)
280 #define SCALE_VAL(x)            ((x) >> SCALE_RED)
281 #define SCALE_MUL(x, y)         (((x) * (y)) >> SCALE_RED)
282     int w_q;                    /* queue weight (scaled) */
283     int max_th;                 /* maximum threshold for queue (scaled) */
284     int min_th;                 /* minimum threshold for queue (scaled) */
285     int max_p;                  /* maximum value for p_b (scaled) */
286     u_int c_1;                  /* max_p/(max_th-min_th) (scaled) */
287     u_int c_2;                  /* max_p*min_th/(max_th-min_th) (scaled) */
288     u_int c_3;                  /* for GRED, (1-max_p)/max_th (scaled) */
289     u_int c_4;                  /* for GRED, 1 - 2*max_p (scaled) */
290     u_int *w_q_lookup;          /* lookup table for computing (1-w_q)^t */
291     u_int lookup_depth;         /* depth of lookup table */
292     int lookup_step;            /* granularity inside the lookup table */
293     int lookup_weight;          /* equal to (1-w_q)^t / (1-w_q)^(t+1) */
294     int avg_pkt_size;           /* medium packet size */
295     int max_pkt_size;           /* max packet size */
296 };
297
298 /*
299  * Pipe descriptor. Contains global parameters, delay-line queue,
300  * and the flow_set used for fixed-rate queues.
301  *
302  * For WF2Q+ support it also has 3 heaps holding dn_flow_queue:
303  *   not_eligible_heap, for queues whose start time is higher
304  *      than the virtual time. Sorted by start time.
305  *   scheduler_heap, for queues eligible for scheduling. Sorted by
306  *      finish time.
307  *   idle_heap, all flows that are idle and can be removed. We
308  *      do that on each tick so we do not slow down too much
309  *      operations during forwarding.
310  *
311  */
312 struct dn_pipe {                /* a pipe */
313     struct dn_pipe *next;
314
315     int pipe_nr;                /* number */
316     int bandwidth;              /* really, bytes/tick. */
317     int delay;                  /* really, ticks */
318
319     struct dn_pkt *head, *tail; /* packets in delay line */
320
321     /* WF2Q+ */
322     struct dn_heap scheduler_heap; /* top extract - key Finish time*/
323     struct dn_heap not_eligible_heap; /* top extract- key Start time */
324     struct dn_heap idle_heap;   /* random extract - key Start=Finish time */
325
326     dn_key V;                   /* virtual time */
327     int sum;                    /* sum of weights of all active sessions */
328     int numbytes;               /* bits I can transmit (more or less). */
329
330     dn_key sched_time;          /* time pipe was scheduled in ready_heap */
331
332     /*
333      * When the tx clock come from an interface (if_name[0] != '\0'), its name
334      * is stored below, whereas the ifp is filled when the rule is configured.
335      */
336     char if_name[IFNAMSIZ];
337     struct ifnet *ifp;
338     int ready;          /* set if ifp != NULL and we got a signal from it */
339
340     struct dn_flow_set fs;      /* used with fixed-rate flows */
341 };
342
343 #ifdef _KERNEL
344 typedef int ip_dn_ctl_t(struct sockopt *); /* raw_ip.c */
345 typedef void ip_dn_ruledel_t(void *); /* ip_fw2.c */
346 typedef int ip_dn_io_t(struct mbuf *m, int pipe_nr, int dir,
347         struct ip_fw_args *fwa);
348 extern  ip_dn_ctl_t *ip_dn_ctl_ptr;
349 extern  ip_dn_ruledel_t *ip_dn_ruledel_ptr;
350 extern  ip_dn_io_t *ip_dn_io_ptr;
351 #define DUMMYNET_LOADED (ip_dn_io_ptr != NULL)
352 #endif
353
354 #endif /* !_IP_DUMMYNET_H */