| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 1998-2010 Luigi Rizzo, Universita` di Pisa |
| 5 | * Portions Copyright (c) 2000 Akamba Corp. |
| 6 | * All rights reserved |
| 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions |
| 10 | * are met: |
| 11 | * 1. Redistributions of source code must retain the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer. |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer in the |
| 15 | * documentation and/or other materials provided with the distribution. |
| 16 | * |
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 27 | * SUCH DAMAGE. |
| 28 | */ |
| 29 | |
| 30 | #ifndef _IP_DUMMYNET_H |
| 31 | #define _IP_DUMMYNET_H |
| 32 | #define NEW_AQM |
| 33 | /* |
| 34 | * Definition of the kernel-userland API for dummynet. |
| 35 | * |
| 36 | * Setsockopt() and getsockopt() pass a batch of objects, each |
| 37 | * of them starting with a "struct dn_id" which should fully identify |
| 38 | * the object and its relation with others in the sequence. |
| 39 | * The first object in each request should have |
| 40 | *	 type= DN_CMD_*, id = DN_API_VERSION. |
| 41 | * For other objects, type and subtype specify the object, len indicates |
| 42 | * the total length including the header, and 'id' identifies the specific |
| 43 | * object. |
| 44 | * |
| 45 | * Most objects are numbered with an identifier in the range 1..65535. |
| 46 | * DN_MAX_ID indicates the first value outside the range. |
| 47 | */ |
| 48 | |
| 49 | #define	DN_API_VERSION	12500000 |
| 50 | #define	DN_MAX_ID	0x10000 |
| 51 | |
| 52 | struct dn_id { |
| 53 | 	uint16_t	len;	/* total obj len including this header */ |
| 54 | 	uint8_t		type; |
| 55 | 	uint8_t		subtype; |
| 56 | 	uint32_t	id;	/* generic id */ |
| 57 | }; |
| 58 | |
| 59 | /* |
| 60 | * These values are in the type field of struct dn_id. |
| 61 | * To preserve the ABI, never rearrange the list or delete |
| 62 | * entries with the exception of DN_LAST |
| 63 | */ |
| 64 | enum { |
| 65 | 	DN_NONE = 0, |
| 66 | 	DN_LINK = 1, |
| 67 | 	DN_FS, |
| 68 | 	DN_SCH, |
| 69 | 	DN_SCH_I, |
| 70 | 	DN_QUEUE, |
| 71 | 	DN_DELAY_LINE, |
| 72 | 	DN_PROFILE, |
| 73 | 	DN_FLOW,		/* struct dn_flow */ |
| 74 | 	DN_TEXT,		/* opaque text is the object */ |
| 75 | |
| 76 | 	DN_CMD_CONFIG = 0x80,	/* objects follow */ |
| 77 | 	DN_CMD_DELETE,		/* subtype + list of entries */ |
| 78 | 	DN_CMD_GET,		/* subtype + list of entries */ |
| 79 | 	DN_CMD_FLUSH, |
| 80 | 	/* for compatibility with FreeBSD 7.2/8 */ |
| 81 | 	DN_COMPAT_PIPE, |
| 82 | 	DN_COMPAT_QUEUE, |
| 83 | 	DN_GET_COMPAT, |
| 84 | |
| 85 | 	/* special commands for emulation of sysctl variables */ |
| 86 | 	DN_SYSCTL_GET, |
| 87 | 	DN_SYSCTL_SET, |
| 88 | #ifdef NEW_AQM |
| 89 | 	/* subtypes used for setting/getting extra parameters. |
| 90 | 	 * these subtypes used with IP_DUMMYNET3 command (get) |
| 91 | 	 * and DN_TEXT (set). */ |
| 92 | 	DN_AQM_PARAMS, /* AQM extra params */ |
| 93 | 	DN_SCH_PARAMS, /* scheduler extra params */ |
| 94 | #endif |
| 95 | 	DN_LAST, |
| 96 | }; |
| 97 | |
| 98 | enum { /* subtype for schedulers, flowset and the like */ |
| 99 | 	DN_SCHED_UNKNOWN = 0, |
| 100 | 	DN_SCHED_FIFO = 1, |
| 101 | 	DN_SCHED_WF2QP = 2, |
| 102 | 	/* others are in individual modules */ |
| 103 | }; |
| 104 | |
| 105 | enum {	/* user flags */ |
| 106 | 	DN_HAVE_MASK	= 0x0001,	/* fs or sched has a mask */ |
| 107 | 	DN_NOERROR	= 0x0002,	/* do not report errors */ |
| 108 | 	DN_QHT_HASH	= 0x0004,	/* qht is a hash table */ |
| 109 | 	DN_QSIZE_BYTES	= 0x0008,	/* queue size is in bytes */ |
| 110 | 	DN_HAS_PROFILE	= 0x0010,	/* a link has a profile */ |
| 111 | 	DN_IS_RED	= 0x0020, |
| 112 | 	DN_IS_GENTLE_RED= 0x0040, |
| 113 | 	DN_IS_ECN	= 0x0080, |
| 114 | 	#ifdef NEW_AQM |
| 115 | 	DN_IS_AQM = 0x0100, /* AQMs: e.g Codel & PIE */ |
| 116 | 	#endif |
| 117 | 	DN_PIPE_CMD	= 0x1000,	/* pipe config... */ |
| 118 | }; |
| 119 | |
| 120 | /* |
| 121 | * link template. |
| 122 | */ |
| 123 | struct dn_link { |
| 124 | 	struct dn_id oid; |
| 125 | |
| 126 | 	/* |
| 127 | 	 * Userland sets bw and delay in bits/s and milliseconds. |
| 128 | 	 * The kernel converts this back and forth to bits/tick and ticks. |
| 129 | 	 * XXX what about burst ? |
| 130 | 	 */ |
| 131 | 	int32_t		link_nr; |
| 132 | 	uint32_t	bandwidth;	/* bit/s or bits/tick. */ |
| 133 | 	int		delay;		/* ms and ticks */ |
| 134 | 	uint64_t	burst;		/* scaled. bits*Hz XXX */ |
| 135 | }; |
| 136 | |
| 137 | /* |
| 138 | * A flowset, which is a template for flows. Contains parameters |
| 139 | * from the command line: id, target scheduler, queue sizes, plr, |
| 140 | * flow masks, buckets for the flow hash, and possibly scheduler- |
| 141 | * specific parameters (weight, quantum and so on). |
| 142 | */ |
| 143 | struct dn_fs { |
| 144 | 	struct dn_id oid; |
| 145 | 	uint32_t fs_nr;		/* the flowset number */ |
| 146 | 	uint32_t flags;		/* userland flags */ |
| 147 | 	int qsize;		/* queue size in slots or bytes */ |
| 148 | 	int32_t pl_state;	/* packet loss state */ |
| 149 | 	uint32_t buckets;	/* buckets used for the queue hash table */ |
| 150 | |
| 151 | 	struct ipfw_flow_id flow_mask; |
| 152 | 	uint32_t sched_nr;	/* the scheduler we attach to */ |
| 153 | 	/* generic scheduler parameters. Leave them at -1 if unset. |
| 154 | 	 * Now we use 0: weight, 1: lmax, 2: priority |
| 155 | 	 */ |
| 156 | 	int par[4]; |
| 157 | |
| 158 | 	/* RED/GRED parameters. |
| 159 | 	 * weight and probabilities are in the range 0..1 represented |
| 160 | 	 * in fixed point arithmetic with SCALE_RED decimal bits. |
| 161 | 	 */ |
| 162 | #define SCALE_RED	16 |
| 163 | #define SCALE(x)	( (x) << SCALE_RED ) |
| 164 | #define SCALE_VAL(x)	( (x) >> SCALE_RED ) |
| 165 | #define SCALE_MUL(x,y)	( ( (x) * (y) ) >> SCALE_RED ) |
| 166 | 	int w_q ;		/* queue weight (scaled) */ |
| 167 | 	int max_th ;		/* maximum threshold for queue (scaled) */ |
| 168 | 	int min_th ;		/* minimum threshold for queue (scaled) */ |
| 169 | 	int max_p ;		/* maximum value for p_b (scaled) */ |
| 170 | |
| 171 | 	int32_t plr[4];		/* PLR, pkt loss rate (2^31-1 means 100%) */ |
| 172 | }; |
| 173 | |
| 174 | /* |
| 175 | * dn_flow collects flow_id and stats for queues and scheduler |
| 176 | * instances, and is used to pass these info to userland. |
| 177 | * oid.type/oid.subtype describe the object, oid.id is number |
| 178 | * of the parent object. |
| 179 | */ |
| 180 | struct dn_flow { |
| 181 | 	struct dn_id	oid; |
| 182 | 	struct ipfw_flow_id fid; |
| 183 | 	uint64_t	tot_pkts; /* statistics counters */ |
| 184 | 	uint64_t	tot_bytes; |
| 185 | 	uint32_t	length; /* Queue length, in packets */ |
| 186 | 	uint32_t	len_bytes; /* Queue length, in bytes */ |
| 187 | 	uint32_t	drops; |
| 188 | }; |
| 189 | |
| 190 | /* |
| 191 | * Scheduler template, mostly indicating the name, number, |
| 192 | * sched_mask and buckets. |
| 193 | */ |
| 194 | struct dn_sch { |
| 195 | 	struct dn_id	oid; |
| 196 | 	uint32_t	sched_nr; /* N, scheduler number */ |
| 197 | 	uint32_t	buckets; /* number of buckets for the instances */ |
| 198 | 	uint32_t	flags;	/* have_mask, ... */ |
| 199 | |
| 200 | 	char name[16];	/* null terminated */ |
| 201 | 	/* mask to select the appropriate scheduler instance */ |
| 202 | 	struct ipfw_flow_id sched_mask; /* M */ |
| 203 | }; |
| 204 | |
| 205 | /* A delay profile is attached to a link. |
| 206 | * Note that a profile, as any other object, cannot be longer than 2^16 |
| 207 | */ |
| 208 | #define	ED_MAX_SAMPLES_NO	1024 |
| 209 | struct dn_profile { |
| 210 | 	struct dn_id	oid; |
| 211 | 	/* fields to simulate a delay profile */ |
| 212 | #define ED_MAX_NAME_LEN		32 |
| 213 | 	char	name[ED_MAX_NAME_LEN]; |
| 214 | 	int	link_nr; |
| 215 | 	int	loss_level; |
| 216 | 	uint32_t	bandwidth;			// XXX use link bandwidth? |
| 217 | 	int	samples_no;			/* actual len of samples[] */ |
| 218 | 	int	samples[ED_MAX_SAMPLES_NO];	/* may be shorter */ |
| 219 | }; |
| 220 | |
| 221 | #ifdef NEW_AQM |
| 222 | /* Extra parameters for AQM and scheduler. |
| 223 | * This struct is used to pass and retrieve parameters (configurations) |
| 224 | * to/from AQM and Scheduler. |
| 225 | */ |
| 226 | struct dn_extra_parms { |
| 227 | 	struct dn_id oid; |
| 228 | 	char name[16]; |
| 229 | 	uint32_t nr; |
| 230 | #define DN_MAX_EXTRA_PARM	10 |
| 231 | 	int64_t par[DN_MAX_EXTRA_PARM]; |
| 232 | }; |
| 233 | #endif |
| 234 | |
| 235 | /* |
| 236 | * Overall structure of dummynet |
| 237 | |
| 238 | In dummynet, packets are selected with the firewall rules, and passed |
| 239 | to two different objects: PIPE or QUEUE (bad name). |
| 240 | |
| 241 | A QUEUE defines a classifier, which groups packets into flows |
| 242 | according to a 'mask', puts them into independent queues (one |
| 243 | per flow) with configurable size and queue management policy, |
| 244 | and passes flows to a scheduler: |
| 245 | |
| 246 | (flow_mask|sched_mask) sched_mask |
| 247 | 	 +---------+ weight Wx +-------------+ |
| 248 | | |->-[flow]-->--| |-+ |
| 249 | -->--| QUEUE x | ... | | | |
| 250 | | |->-[flow]-->--| SCHEDuler N | | |
| 251 | 	 +---------+ | | | |
| 252 | 	 ... | +--[LINK N]-->-- |
| 253 | 	 +---------+ weight Wy | | +--[LINK N]-->-- |
| 254 | | |->-[flow]-->--| | | |
| 255 | -->--| QUEUE y | ... | | | |
| 256 | | |->-[flow]-->--| | | |
| 257 | 	 +---------+ +-------------+ | |
| 258 | 	 +-------------+ |
| 259 | |
| 260 | Many QUEUE objects can connect to the same scheduler, each |
| 261 | QUEUE object can have its own set of parameters. |
| 262 | |
| 263 | In turn, the SCHEDuler 'forks' multiple instances according |
| 264 | to a 'sched_mask', each instance manages its own set of queues |
| 265 | and transmits on a private instance of a configurable LINK. |
| 266 | |
| 267 | A PIPE is a simplified version of the above, where there |
| 268 | is no flow_mask, and each scheduler instance handles a single queue. |
| 269 | |
| 270 | The following data structures (visible from userland) describe |
| 271 | the objects used by dummynet: |
| 272 | |
| 273 | + dn_link, contains the main configuration parameters related |
| 274 | to delay and bandwidth; |
| 275 | + dn_profile describes a delay profile; |
| 276 | + dn_flow describes the flow status (flow id, statistics) |
| 277 | |
| 278 | + dn_sch describes a scheduler |
| 279 | + dn_fs describes a flowset (msk, weight, queue parameters) |
| 280 | |
| 281 | * |
| 282 | */ |
| 283 | |
| 284 | #endif /* _IP_DUMMYNET_H */ |