xref: /dflybsd-src/sys/net/dummynet/ip_dummynet.h (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*
286d7f5d3SJohn Marino  * Copyright (c) 1998-2002 Luigi Rizzo, Universita` di Pisa
386d7f5d3SJohn Marino  * Portions Copyright (c) 2000 Akamba Corp.
486d7f5d3SJohn Marino  * All rights reserved
586d7f5d3SJohn Marino  *
686d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
786d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
886d7f5d3SJohn Marino  * are met:
986d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
1086d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1186d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1286d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
1386d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
1486d7f5d3SJohn Marino  *
1586d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1686d7f5d3SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1786d7f5d3SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1886d7f5d3SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1986d7f5d3SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2086d7f5d3SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2186d7f5d3SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2286d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2386d7f5d3SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2486d7f5d3SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2586d7f5d3SJohn Marino  * SUCH DAMAGE.
2686d7f5d3SJohn Marino  *
2786d7f5d3SJohn Marino  * $FreeBSD: src/sys/netinet/ip_dummynet.h,v 1.10.2.9 2003/05/13 09:31:06 maxim Exp $
2886d7f5d3SJohn Marino  * $DragonFly: src/sys/net/dummynet/ip_dummynet.h,v 1.19 2008/09/20 04:36:51 sephe Exp $
2986d7f5d3SJohn Marino  */
3086d7f5d3SJohn Marino 
3186d7f5d3SJohn Marino #ifndef _IP_DUMMYNET_H
3286d7f5d3SJohn Marino #define _IP_DUMMYNET_H
3386d7f5d3SJohn Marino 
3486d7f5d3SJohn Marino /*
3586d7f5d3SJohn Marino  * We start with a heap, which is used in the scheduler to decide when to
3686d7f5d3SJohn Marino  * transmit packets etc.
3786d7f5d3SJohn Marino  *
3886d7f5d3SJohn Marino  * The key for the heap is used for two different values:
3986d7f5d3SJohn Marino  *
4086d7f5d3SJohn Marino  * 1. Timer ticks- max 10K/second, so 32 bits are enough;
4186d7f5d3SJohn Marino  *
4286d7f5d3SJohn Marino  * 2. Virtual times.  These increase in steps of len/x, where len is the
4386d7f5d3SJohn Marino  *    packet length, and x is either the weight of the flow, or the sum
4486d7f5d3SJohn Marino  *    of all weights.
4586d7f5d3SJohn Marino  *    If we limit to max 1000 flows and a max weight of 100, then x needs
4686d7f5d3SJohn Marino  *    17 bits.  The packet size is 16 bits, so we can easily overflow if
4786d7f5d3SJohn Marino  *    we do not allow errors.
4886d7f5d3SJohn Marino  *
4986d7f5d3SJohn Marino  * So we use a key "dn_key" which is 64 bits.
5086d7f5d3SJohn Marino  *
5186d7f5d3SJohn Marino  * MY_M is used as a shift count when doing fixed point arithmetic
5286d7f5d3SJohn Marino  * (a better name would be useful...).
5386d7f5d3SJohn Marino  */
5486d7f5d3SJohn Marino typedef uint64_t	dn_key;	/* sorting key */
5586d7f5d3SJohn Marino 
5686d7f5d3SJohn Marino /*
5786d7f5d3SJohn Marino  * Number of left shift to obtain a larger precision
5886d7f5d3SJohn Marino  *
5986d7f5d3SJohn Marino  * XXX With this scaling, max 1000 flows, max weight 100, 1Gbit/s, the
6086d7f5d3SJohn Marino  * virtual time wraps every 15 days.
6186d7f5d3SJohn Marino  */
6286d7f5d3SJohn Marino #define MY_M		16
6386d7f5d3SJohn Marino 
6486d7f5d3SJohn Marino #ifdef _KERNEL
6586d7f5d3SJohn Marino 
6686d7f5d3SJohn Marino /*
6786d7f5d3SJohn Marino  * A heap entry is made of a key and a pointer to the actual object stored
6886d7f5d3SJohn Marino  * in the heap.
6986d7f5d3SJohn Marino  *
7086d7f5d3SJohn Marino  * The heap is an array of dn_heap_entry entries, dynamically allocated.
7186d7f5d3SJohn Marino  * Current size is "size", with "elements" actually in use.
7286d7f5d3SJohn Marino  *
7386d7f5d3SJohn Marino  * The heap normally supports only ordered insert and extract from the top.
7486d7f5d3SJohn Marino  * If we want to extract an object from the middle of the heap, we have to
7586d7f5d3SJohn Marino  * know where the object itself is located in the heap (or we need to scan
7686d7f5d3SJohn Marino  * the whole array).  To this purpose, an object has a field (int) which
7786d7f5d3SJohn Marino  * contains the index of the object itself into the heap.  When the object
7886d7f5d3SJohn Marino  * is moved, the field must also be updated.  The offset of the index in the
7986d7f5d3SJohn Marino  * object is stored in the 'offset' field in the heap descriptor.  The
8086d7f5d3SJohn Marino  * assumption is that this offset is non-zero if we want to support extract
8186d7f5d3SJohn Marino  * from the middle.
8286d7f5d3SJohn Marino  */
8386d7f5d3SJohn Marino struct dn_heap_entry {
8486d7f5d3SJohn Marino     dn_key key;		/* sorting key.  Topmost element is smallest one */
8586d7f5d3SJohn Marino     void *object;	/* object pointer */
8686d7f5d3SJohn Marino };
8786d7f5d3SJohn Marino 
8886d7f5d3SJohn Marino struct dn_heap {
8986d7f5d3SJohn Marino     int size;
9086d7f5d3SJohn Marino     int elements;
9186d7f5d3SJohn Marino     int offset; /* XXX if > 0 this is the offset of direct ptr to obj */
9286d7f5d3SJohn Marino     struct dn_heap_entry *p;	/* really an array of "size" entries */
9386d7f5d3SJohn Marino };
9486d7f5d3SJohn Marino 
9586d7f5d3SJohn Marino struct dn_flow_id {
9686d7f5d3SJohn Marino     uint16_t fid_type;	/* ETHERTYPE_ */
9786d7f5d3SJohn Marino     uint16_t pad;
9886d7f5d3SJohn Marino     union {
9986d7f5d3SJohn Marino 	struct {
10086d7f5d3SJohn Marino 	    uint32_t dst_ip;
10186d7f5d3SJohn Marino 	    uint32_t src_ip;
10286d7f5d3SJohn Marino 	    uint16_t dst_port;
10386d7f5d3SJohn Marino 	    uint16_t src_port;
10486d7f5d3SJohn Marino 	    uint8_t proto;
10586d7f5d3SJohn Marino 	    uint8_t flags;
10686d7f5d3SJohn Marino 	} inet;
10786d7f5d3SJohn Marino     } fid_u;
10886d7f5d3SJohn Marino #define fid_dst_ip	fid_u.inet.dst_ip
10986d7f5d3SJohn Marino #define fid_src_ip	fid_u.inet.src_ip
11086d7f5d3SJohn Marino #define fid_dst_port	fid_u.inet.dst_port
11186d7f5d3SJohn Marino #define fid_src_port	fid_u.inet.src_port
11286d7f5d3SJohn Marino #define fid_proto	fid_u.inet.proto
11386d7f5d3SJohn Marino #define fid_flags	fid_u.inet.flags
11486d7f5d3SJohn Marino };
11586d7f5d3SJohn Marino 
11686d7f5d3SJohn Marino typedef void	(*ip_dn_unref_priv_t)(void *);
11786d7f5d3SJohn Marino struct lwkt_port;
11886d7f5d3SJohn Marino 
11986d7f5d3SJohn Marino /*
12086d7f5d3SJohn Marino  * struct dn_pkt identifies a packet in the dummynet queue, but is also used
12186d7f5d3SJohn Marino  * to tag packets passed back to the various destinations (ip_input(),
12286d7f5d3SJohn Marino  * ip_output() and so on).
12386d7f5d3SJohn Marino  *
12486d7f5d3SJohn Marino  * It is a tag (PACKET_TAG_DUMMYNET) associated with the actual mbuf.
12586d7f5d3SJohn Marino  */
12686d7f5d3SJohn Marino struct dn_pkt {
12786d7f5d3SJohn Marino     struct mbuf *dn_m;
12886d7f5d3SJohn Marino     TAILQ_ENTRY(dn_pkt) dn_next;
12986d7f5d3SJohn Marino 
13086d7f5d3SJohn Marino     void *dn_priv;
13186d7f5d3SJohn Marino     ip_dn_unref_priv_t dn_unref_priv;
13286d7f5d3SJohn Marino 
13386d7f5d3SJohn Marino     uint32_t dn_flags;		/* action when packet comes out. */
13486d7f5d3SJohn Marino #define DN_FLAGS_IS_PIPE	0x10
13586d7f5d3SJohn Marino #define DN_FLAGS_DIR_MASK	0x0f
13686d7f5d3SJohn Marino #define DN_TO_IP_OUT		1
13786d7f5d3SJohn Marino #define DN_TO_IP_IN		2
13886d7f5d3SJohn Marino #define DN_TO_ETH_DEMUX		4
13986d7f5d3SJohn Marino #define DN_TO_ETH_OUT		5
14086d7f5d3SJohn Marino #define DN_TO_MAX		6
14186d7f5d3SJohn Marino 
14286d7f5d3SJohn Marino     dn_key output_time;		/* when the pkt is due for delivery */
14386d7f5d3SJohn Marino     struct ifnet *ifp;		/* interface, for ip_output */
14486d7f5d3SJohn Marino     struct sockaddr_in *dn_dst;
14586d7f5d3SJohn Marino     struct route ro;		/* route, for ip_output. MUST COPY */
14686d7f5d3SJohn Marino     int flags;			/* flags, for ip_output (IPv6 ?) */
14786d7f5d3SJohn Marino 
14886d7f5d3SJohn Marino     u_short pipe_nr;		/* pipe/flow_set number */
14986d7f5d3SJohn Marino     u_short pad;
15086d7f5d3SJohn Marino 
15186d7f5d3SJohn Marino     struct dn_flow_id id;	/* flow id */
15286d7f5d3SJohn Marino     int cpuid;			/* target cpuid, for assertion */
15386d7f5d3SJohn Marino     struct lwkt_port *msgport;	/* target msgport */
15486d7f5d3SJohn Marino };
15586d7f5d3SJohn Marino TAILQ_HEAD(dn_pkt_queue, dn_pkt);
15686d7f5d3SJohn Marino 
15786d7f5d3SJohn Marino /*
15886d7f5d3SJohn Marino  * Overall structure of dummynet (with WF2Q+):
15986d7f5d3SJohn Marino  *
16086d7f5d3SJohn Marino  * In dummynet, packets are selected with the firewall rules, and passed to
16186d7f5d3SJohn Marino  * two different objects: PIPE or QUEUE.
16286d7f5d3SJohn Marino  *
16386d7f5d3SJohn Marino  * A QUEUE is just a queue with configurable size and queue management policy.
16486d7f5d3SJohn Marino  * It is also associated with a mask (to discriminate among different flows),
16586d7f5d3SJohn Marino  * a weight (used to give different shares of the bandwidth to different flows)
16686d7f5d3SJohn Marino  * and a "pipe", which essentially supplies the transmit clock for all queues
16786d7f5d3SJohn Marino  * associated with that pipe.
16886d7f5d3SJohn Marino  *
16986d7f5d3SJohn Marino  * A PIPE emulates a fixed-bandwidth link, whose bandwidth is configurable.
17086d7f5d3SJohn Marino  * The "clock" for a pipe comes from an internal timer.  A pipe is also
17186d7f5d3SJohn Marino  * associated with one (or more, if masks are used) queue, where all packets
17286d7f5d3SJohn Marino  * for that pipe are stored.
17386d7f5d3SJohn Marino  *
17486d7f5d3SJohn Marino  * The bandwidth available on the pipe is shared by the queues associated with
17586d7f5d3SJohn Marino  * that pipe (only one in case the packet is sent to a PIPE) according to the
17686d7f5d3SJohn Marino  * WF2Q+ scheduling algorithm and the configured weights.
17786d7f5d3SJohn Marino  *
17886d7f5d3SJohn Marino  * In general, incoming packets are stored in the appropriate queue, which is
17986d7f5d3SJohn Marino  * then placed into one of a few heaps managed by a scheduler to decide when
18086d7f5d3SJohn Marino  * the packet should be extracted.  The scheduler (a function called dummynet())
18186d7f5d3SJohn Marino  * is run at every timer tick, and grabs queues from the head of the heaps when
18286d7f5d3SJohn Marino  * they are ready for processing.
18386d7f5d3SJohn Marino  *
18486d7f5d3SJohn Marino  * There are three data structures definining a pipe and associated queues:
18586d7f5d3SJohn Marino  *
18686d7f5d3SJohn Marino  *  + dn_pipe, which contains the main configuration parameters related to
18786d7f5d3SJohn Marino  *    delay and bandwidth;
18886d7f5d3SJohn Marino  *  + dn_flow_set, which contains WF2Q+ configuration, flow masks, plr and
18986d7f5d3SJohn Marino  *    RED configuration;
19086d7f5d3SJohn Marino  *  + dn_flow_queue, which is the per-flow queue (containing the packets)
19186d7f5d3SJohn Marino  *
19286d7f5d3SJohn Marino  * Multiple dn_flow_set can be linked to the same pipe, and multiple
19386d7f5d3SJohn Marino  * dn_flow_queue can be linked to the same dn_flow_set.
19486d7f5d3SJohn Marino  * All data structures are linked in a linear list which is used for
19586d7f5d3SJohn Marino  * housekeeping purposes.
19686d7f5d3SJohn Marino  *
19786d7f5d3SJohn Marino  * During configuration, we create and initialize the dn_flow_set and dn_pipe
19886d7f5d3SJohn Marino  * structures (a dn_pipe also contains a dn_flow_set).
19986d7f5d3SJohn Marino  *
20086d7f5d3SJohn Marino  * At runtime: packets are sent to the appropriate dn_flow_set (either WFQ
20186d7f5d3SJohn Marino  * ones, or the one embedded in the dn_pipe for fixed-rate flows), which in
20286d7f5d3SJohn Marino  * turn dispatches them to the appropriate dn_flow_queue (created dynamically
20386d7f5d3SJohn Marino  * according to the masks).
20486d7f5d3SJohn Marino  *
20586d7f5d3SJohn Marino  * The transmit clock for fixed rate flows (ready_event()) selects the
20686d7f5d3SJohn Marino  * dn_flow_queue to be used to transmit the next packet. For WF2Q,
20786d7f5d3SJohn Marino  * wfq_ready_event() extract a pipe which in turn selects the right flow using
20886d7f5d3SJohn Marino  * a number of heaps defined into the pipe itself.
20986d7f5d3SJohn Marino  */
21086d7f5d3SJohn Marino 
21186d7f5d3SJohn Marino /*
21286d7f5d3SJohn Marino  * Per flow queue.  This contains the flow identifier, the queue of packets,
21386d7f5d3SJohn Marino  * counters, and parameters used to support both RED and WF2Q+.
21486d7f5d3SJohn Marino  *
21586d7f5d3SJohn Marino  * A dn_flow_queue is created and initialized whenever a packet for a new
21686d7f5d3SJohn Marino  * flow arrives.
21786d7f5d3SJohn Marino  */
21886d7f5d3SJohn Marino struct dn_flow_queue {
21986d7f5d3SJohn Marino     struct dn_flow_id id;
22086d7f5d3SJohn Marino     LIST_ENTRY(dn_flow_queue) q_link;
22186d7f5d3SJohn Marino 
22286d7f5d3SJohn Marino     struct dn_pkt_queue queue;	/* queue of packets */
22386d7f5d3SJohn Marino     u_int len;
22486d7f5d3SJohn Marino     u_int len_bytes;
22586d7f5d3SJohn Marino     u_long numbytes;		/* credit for transmission (dynamic queues) */
22686d7f5d3SJohn Marino 
22786d7f5d3SJohn Marino     uint64_t tot_pkts;		/* statistics counters */
22886d7f5d3SJohn Marino     uint64_t tot_bytes;
22986d7f5d3SJohn Marino     uint32_t drops;
23086d7f5d3SJohn Marino 
23186d7f5d3SJohn Marino     int hash_slot;		/* debugging/diagnostic */
23286d7f5d3SJohn Marino 
23386d7f5d3SJohn Marino     /* RED parameters */
23486d7f5d3SJohn Marino     int avg;			/* average queue length est. (scaled) */
23586d7f5d3SJohn Marino     int count;			/* arrivals since last RED drop */
23686d7f5d3SJohn Marino     int random;			/* random value (scaled) */
23786d7f5d3SJohn Marino     uint32_t q_time;		/* start of queue idle time */
23886d7f5d3SJohn Marino 
23986d7f5d3SJohn Marino     /* WF2Q+ support */
24086d7f5d3SJohn Marino     struct dn_flow_set *fs;	/* parent flow set */
24186d7f5d3SJohn Marino     int heap_pos;		/* position (index) of struct in heap */
24286d7f5d3SJohn Marino     dn_key sched_time;		/* current time when queue enters ready_heap */
24386d7f5d3SJohn Marino 
24486d7f5d3SJohn Marino     dn_key S, F;		/* start time, finish time */
24586d7f5d3SJohn Marino     /*
24686d7f5d3SJohn Marino      * Setting F < S means the timestamp is invalid. We only need
24786d7f5d3SJohn Marino      * to test this when the queue is empty.
24886d7f5d3SJohn Marino      */
24986d7f5d3SJohn Marino };
25086d7f5d3SJohn Marino LIST_HEAD(dn_flowqueue_head, dn_flow_queue);
25186d7f5d3SJohn Marino 
25286d7f5d3SJohn Marino /*
25386d7f5d3SJohn Marino  * flow_set descriptor.  Contains the "template" parameters for the queue
25486d7f5d3SJohn Marino  * configuration, and pointers to the hash table of dn_flow_queue's.
25586d7f5d3SJohn Marino  *
25686d7f5d3SJohn Marino  * The hash table is an array of lists -- we identify the slot by hashing
25786d7f5d3SJohn Marino  * the flow-id, then scan the list looking for a match.
25886d7f5d3SJohn Marino  * The size of the hash table (buckets) is configurable on a per-queue basis.
25986d7f5d3SJohn Marino  *
26086d7f5d3SJohn Marino  * A dn_flow_set is created whenever a new queue or pipe is created (in the
26186d7f5d3SJohn Marino  * latter case, the structure is located inside the struct dn_pipe).
26286d7f5d3SJohn Marino  */
26386d7f5d3SJohn Marino struct dn_flow_set {
26486d7f5d3SJohn Marino     u_short fs_nr;		/* flow_set number */
26586d7f5d3SJohn Marino     u_short flags_fs;		/* see 'Flow set flags' */
26686d7f5d3SJohn Marino 
26786d7f5d3SJohn Marino     LIST_ENTRY(dn_flow_set) fs_link;
26886d7f5d3SJohn Marino 
26986d7f5d3SJohn Marino     struct dn_pipe *pipe;	/* pointer to parent pipe */
27086d7f5d3SJohn Marino     u_short parent_nr;		/* parent pipe#, 0 if local to a pipe */
27186d7f5d3SJohn Marino 
27286d7f5d3SJohn Marino     int weight;			/* WFQ queue weight */
27386d7f5d3SJohn Marino     int qsize;			/* queue size in slots or bytes */
27486d7f5d3SJohn Marino     int plr;			/* pkt loss rate (2^31-1 means 100%) */
27586d7f5d3SJohn Marino 
27686d7f5d3SJohn Marino     struct dn_flow_id flow_mask;
27786d7f5d3SJohn Marino 
27886d7f5d3SJohn Marino     /* hash table of queues onto this flow_set */
27986d7f5d3SJohn Marino     int rq_size;		/* number of slots */
28086d7f5d3SJohn Marino     int rq_elements;		/* active elements */
28186d7f5d3SJohn Marino     struct dn_flowqueue_head *rq;/* array of rq_size entries */
28286d7f5d3SJohn Marino 
28386d7f5d3SJohn Marino     uint32_t last_expired;	/* do not expire too frequently */
28486d7f5d3SJohn Marino     int backlogged;		/* #active queues for this flowset */
28586d7f5d3SJohn Marino 
28686d7f5d3SJohn Marino     /* RED parameters */
28786d7f5d3SJohn Marino     int w_q;			/* queue weight (scaled) */
28886d7f5d3SJohn Marino     int max_th;			/* maximum threshold for queue (scaled) */
28986d7f5d3SJohn Marino     int min_th;			/* minimum threshold for queue (scaled) */
29086d7f5d3SJohn Marino     int max_p;			/* maximum value for p_b (scaled) */
29186d7f5d3SJohn Marino     u_int c_1;			/* max_p/(max_th-min_th) (scaled) */
29286d7f5d3SJohn Marino     u_int c_2;			/* max_p*min_th/(max_th-min_th) (scaled) */
29386d7f5d3SJohn Marino     u_int c_3;			/* for GRED, (1-max_p)/max_th (scaled) */
29486d7f5d3SJohn Marino     u_int c_4;			/* for GRED, 1 - 2*max_p (scaled) */
29586d7f5d3SJohn Marino     u_int *w_q_lookup;		/* lookup table for computing (1-w_q)^t */
29686d7f5d3SJohn Marino     u_int lookup_depth;		/* depth of lookup table */
29786d7f5d3SJohn Marino     int lookup_step;		/* granularity inside the lookup table */
29886d7f5d3SJohn Marino     int lookup_weight;		/* equal to (1-w_q)^t / (1-w_q)^(t+1) */
29986d7f5d3SJohn Marino     int avg_pkt_size;		/* medium packet size */
30086d7f5d3SJohn Marino     int max_pkt_size;		/* max packet size */
30186d7f5d3SJohn Marino };
30286d7f5d3SJohn Marino LIST_HEAD(dn_flowset_head, dn_flow_set);
30386d7f5d3SJohn Marino 
30486d7f5d3SJohn Marino /*
30586d7f5d3SJohn Marino  * Pipe descriptor. Contains global parameters, delay-line queue, and the
30686d7f5d3SJohn Marino  * flow_set used for fixed-rate queues.
30786d7f5d3SJohn Marino  *
30886d7f5d3SJohn Marino  * For WF2Q+ support it also has 3 heaps holding dn_flow_queue:
30986d7f5d3SJohn Marino  *  + not_eligible_heap, for queues whose start time is higher than the
31086d7f5d3SJohn Marino  *    virtual time. Sorted by start time.
31186d7f5d3SJohn Marino  *  + scheduler_heap, for queues eligible for scheduling.  Sorted by finish
31286d7f5d3SJohn Marino  *    time.
31386d7f5d3SJohn Marino  *  + idle_heap, all flows that are idle and can be removed.  We do that on
31486d7f5d3SJohn Marino  *    each tick so we do not slow down too much operations during forwarding.
31586d7f5d3SJohn Marino  */
31686d7f5d3SJohn Marino struct dn_pipe {		/* a pipe */
31786d7f5d3SJohn Marino     int pipe_nr;		/* number */
31886d7f5d3SJohn Marino     int bandwidth;		/* really, bytes/tick. */
31986d7f5d3SJohn Marino     int delay;			/* really, ticks */
32086d7f5d3SJohn Marino 
32186d7f5d3SJohn Marino     struct dn_pkt_queue p_queue;/* packets in delay line */
32286d7f5d3SJohn Marino     LIST_ENTRY(dn_pipe) p_link;
32386d7f5d3SJohn Marino 
32486d7f5d3SJohn Marino     /* WF2Q+ */
32586d7f5d3SJohn Marino     struct dn_heap scheduler_heap; /* top extract - key Finish time*/
32686d7f5d3SJohn Marino     struct dn_heap not_eligible_heap; /* top extract- key Start time */
32786d7f5d3SJohn Marino     struct dn_heap idle_heap;	/* random extract - key Start=Finish time */
32886d7f5d3SJohn Marino 
32986d7f5d3SJohn Marino     dn_key V;			/* virtual time */
33086d7f5d3SJohn Marino     int sum;			/* sum of weights of all active sessions */
33186d7f5d3SJohn Marino     int numbytes;		/* bits I can transmit (more or less). */
33286d7f5d3SJohn Marino 
33386d7f5d3SJohn Marino     dn_key sched_time;		/* time pipe was scheduled in ready_heap */
33486d7f5d3SJohn Marino 
33586d7f5d3SJohn Marino     struct dn_flow_set fs;	/* used with fixed-rate flows */
33686d7f5d3SJohn Marino };
33786d7f5d3SJohn Marino LIST_HEAD(dn_pipe_head, dn_pipe);
33886d7f5d3SJohn Marino 
33986d7f5d3SJohn Marino struct dn_sopt {
34086d7f5d3SJohn Marino 	int	dn_sopt_name;
34186d7f5d3SJohn Marino 	void	*dn_sopt_arg;
34286d7f5d3SJohn Marino 	size_t	dn_sopt_arglen;
34386d7f5d3SJohn Marino };
34486d7f5d3SJohn Marino 
34586d7f5d3SJohn Marino typedef int	ip_dn_ctl_t(struct dn_sopt *);
34686d7f5d3SJohn Marino typedef int	ip_dn_io_t(struct mbuf *);
34786d7f5d3SJohn Marino 
34886d7f5d3SJohn Marino extern ip_dn_ctl_t	*ip_dn_ctl_ptr;
34986d7f5d3SJohn Marino extern ip_dn_io_t	*ip_dn_io_ptr;
35086d7f5d3SJohn Marino 
35186d7f5d3SJohn Marino void	ip_dn_queue(struct mbuf *);
35286d7f5d3SJohn Marino void	ip_dn_packet_free(struct dn_pkt *);
35386d7f5d3SJohn Marino void	ip_dn_packet_redispatch(struct dn_pkt *);
35486d7f5d3SJohn Marino int	ip_dn_sockopt(struct sockopt *);
35586d7f5d3SJohn Marino 
35686d7f5d3SJohn Marino #define	DUMMYNET_LOADED	(ip_dn_io_ptr != NULL)
35786d7f5d3SJohn Marino 
35886d7f5d3SJohn Marino #endif	/* _KERNEL */
35986d7f5d3SJohn Marino 
36086d7f5d3SJohn Marino struct dn_ioc_flowid {
36186d7f5d3SJohn Marino     uint16_t type;	/* ETHERTYPE_ */
36286d7f5d3SJohn Marino     uint16_t pad;
36386d7f5d3SJohn Marino     union {
36486d7f5d3SJohn Marino 	struct {
36586d7f5d3SJohn Marino 	    uint32_t dst_ip;
36686d7f5d3SJohn Marino 	    uint32_t src_ip;
36786d7f5d3SJohn Marino 	    uint16_t dst_port;
36886d7f5d3SJohn Marino 	    uint16_t src_port;
36986d7f5d3SJohn Marino 	    uint8_t proto;
37086d7f5d3SJohn Marino 	    uint8_t flags;
37186d7f5d3SJohn Marino 	} ip;
37286d7f5d3SJohn Marino 	uint8_t pad[64];
37386d7f5d3SJohn Marino     } u;
37486d7f5d3SJohn Marino };
37586d7f5d3SJohn Marino 
37686d7f5d3SJohn Marino struct dn_ioc_flowqueue {
37786d7f5d3SJohn Marino     u_int len;
37886d7f5d3SJohn Marino     u_int len_bytes;
37986d7f5d3SJohn Marino 
38086d7f5d3SJohn Marino     uint64_t tot_pkts;
38186d7f5d3SJohn Marino     uint64_t tot_bytes;
38286d7f5d3SJohn Marino     uint32_t drops;
38386d7f5d3SJohn Marino 
38486d7f5d3SJohn Marino     int hash_slot;		/* debugging/diagnostic */
38586d7f5d3SJohn Marino     dn_key S;			/* virtual start time */
38686d7f5d3SJohn Marino     dn_key F;			/* virtual finish time */
38786d7f5d3SJohn Marino 
38886d7f5d3SJohn Marino     struct dn_ioc_flowid id;
38986d7f5d3SJohn Marino     uint8_t reserved[16];
39086d7f5d3SJohn Marino };
39186d7f5d3SJohn Marino 
39286d7f5d3SJohn Marino struct dn_ioc_flowset {
39386d7f5d3SJohn Marino     u_short fs_type;		/* DN_IS_{QUEUE,PIPE}, MUST be first */
39486d7f5d3SJohn Marino 
39586d7f5d3SJohn Marino     u_short fs_nr;		/* flow_set number */
39686d7f5d3SJohn Marino     u_short flags_fs;		/* see 'Flow set flags' */
39786d7f5d3SJohn Marino     u_short parent_nr;		/* parent pipe#, 0 if local to a pipe */
39886d7f5d3SJohn Marino 
39986d7f5d3SJohn Marino     int weight;			/* WFQ queue weight */
40086d7f5d3SJohn Marino     int qsize;			/* queue size in slots or bytes */
40186d7f5d3SJohn Marino     int plr;			/* pkt loss rate (2^31-1 means 100%) */
40286d7f5d3SJohn Marino 
40386d7f5d3SJohn Marino     /* Hash table information */
40486d7f5d3SJohn Marino     int rq_size;		/* number of slots */
40586d7f5d3SJohn Marino     int rq_elements;		/* active elements */
40686d7f5d3SJohn Marino 
40786d7f5d3SJohn Marino     /* RED parameters */
40886d7f5d3SJohn Marino     int w_q;			/* queue weight (scaled) */
40986d7f5d3SJohn Marino     int max_th;			/* maximum threshold for queue (scaled) */
41086d7f5d3SJohn Marino     int min_th;			/* minimum threshold for queue (scaled) */
41186d7f5d3SJohn Marino     int max_p;			/* maximum value for p_b (scaled) */
41286d7f5d3SJohn Marino     int lookup_step;		/* granularity inside the lookup table */
41386d7f5d3SJohn Marino     int lookup_weight;		/* equal to (1-w_q)^t / (1-w_q)^(t+1) */
41486d7f5d3SJohn Marino 
41586d7f5d3SJohn Marino     struct dn_ioc_flowid flow_mask;
41686d7f5d3SJohn Marino     uint8_t reserved[16];
41786d7f5d3SJohn Marino };
41886d7f5d3SJohn Marino 
41986d7f5d3SJohn Marino struct dn_ioc_pipe {
42086d7f5d3SJohn Marino     struct dn_ioc_flowset fs;	/* MUST be first */
42186d7f5d3SJohn Marino 
42286d7f5d3SJohn Marino     int pipe_nr;		/* pipe number */
42386d7f5d3SJohn Marino     int bandwidth;		/* bit/second */
42486d7f5d3SJohn Marino     int delay;			/* milliseconds */
42586d7f5d3SJohn Marino 
42686d7f5d3SJohn Marino     dn_key V;			/* virtual time */
42786d7f5d3SJohn Marino 
42886d7f5d3SJohn Marino     uint8_t reserved[16];
42986d7f5d3SJohn Marino };
43086d7f5d3SJohn Marino 
43186d7f5d3SJohn Marino /*
43286d7f5d3SJohn Marino  * Flow set flags
43386d7f5d3SJohn Marino  */
43486d7f5d3SJohn Marino #define DN_HAVE_FLOW_MASK	0x0001
43586d7f5d3SJohn Marino #define DN_IS_RED		0x0002
43686d7f5d3SJohn Marino #define DN_IS_GENTLE_RED	0x0004
43786d7f5d3SJohn Marino #define DN_QSIZE_IS_BYTES	0x0008	/* queue size is measured in bytes */
43886d7f5d3SJohn Marino #define DN_NOERROR		0x0010	/* do not report ENOBUFS on drops */
43986d7f5d3SJohn Marino #define DN_IS_PIPE		0x4000
44086d7f5d3SJohn Marino #define DN_IS_QUEUE		0x8000
44186d7f5d3SJohn Marino 
44286d7f5d3SJohn Marino /*
44386d7f5d3SJohn Marino  * Macros for RED
44486d7f5d3SJohn Marino  */
44586d7f5d3SJohn Marino #define SCALE_RED		16
44686d7f5d3SJohn Marino #define SCALE(x)		((x) << SCALE_RED)
44786d7f5d3SJohn Marino #define SCALE_VAL(x)		((x) >> SCALE_RED)
44886d7f5d3SJohn Marino #define SCALE_MUL(x, y)		(((x) * (y)) >> SCALE_RED)
44986d7f5d3SJohn Marino 
45086d7f5d3SJohn Marino /*
45186d7f5d3SJohn Marino  * Maximum pipe number
45286d7f5d3SJohn Marino  */
45386d7f5d3SJohn Marino #define DN_PIPE_NR_MAX		65536
45486d7f5d3SJohn Marino 
45586d7f5d3SJohn Marino #endif /* !_IP_DUMMYNET_H */
456