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