HardenedBSD/sys/netinet/ip_dummynet.h
Richard Scheffenegger 31cf66d755 dummynet: add simple gilbert-elliott channel model
Have a simple Gilbert-Elliott channel model in
dummynet to mimick correlated loss behavior of
realistic environments. This allows simpler testing
of burst-loss environments.

Reviewed By:           tuexen, kp, pauamma_gundo.com, #manpages
Sponsored by:          NetApp, Inc.
Differential Revision: https://reviews.freebsd.org/D42980
2023-12-17 13:20:45 +01:00

285 lines
9.0 KiB
C

/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1998-2010 Luigi Rizzo, Universita` di Pisa
* Portions Copyright (c) 2000 Akamba Corp.
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _IP_DUMMYNET_H
#define _IP_DUMMYNET_H
#define NEW_AQM
/*
* Definition of the kernel-userland API for dummynet.
*
* Setsockopt() and getsockopt() pass a batch of objects, each
* of them starting with a "struct dn_id" which should fully identify
* the object and its relation with others in the sequence.
* The first object in each request should have
* type= DN_CMD_*, id = DN_API_VERSION.
* For other objects, type and subtype specify the object, len indicates
* the total length including the header, and 'id' identifies the specific
* object.
*
* Most objects are numbered with an identifier in the range 1..65535.
* DN_MAX_ID indicates the first value outside the range.
*/
#define DN_API_VERSION 12500000
#define DN_MAX_ID 0x10000
struct dn_id {
uint16_t len; /* total obj len including this header */
uint8_t type;
uint8_t subtype;
uint32_t id; /* generic id */
};
/*
* These values are in the type field of struct dn_id.
* To preserve the ABI, never rearrange the list or delete
* entries with the exception of DN_LAST
*/
enum {
DN_NONE = 0,
DN_LINK = 1,
DN_FS,
DN_SCH,
DN_SCH_I,
DN_QUEUE,
DN_DELAY_LINE,
DN_PROFILE,
DN_FLOW, /* struct dn_flow */
DN_TEXT, /* opaque text is the object */
DN_CMD_CONFIG = 0x80, /* objects follow */
DN_CMD_DELETE, /* subtype + list of entries */
DN_CMD_GET, /* subtype + list of entries */
DN_CMD_FLUSH,
/* for compatibility with FreeBSD 7.2/8 */
DN_COMPAT_PIPE,
DN_COMPAT_QUEUE,
DN_GET_COMPAT,
/* special commands for emulation of sysctl variables */
DN_SYSCTL_GET,
DN_SYSCTL_SET,
#ifdef NEW_AQM
/* subtypes used for setting/getting extra parameters.
* these subtypes used with IP_DUMMYNET3 command (get)
* and DN_TEXT (set). */
DN_AQM_PARAMS, /* AQM extra params */
DN_SCH_PARAMS, /* scheduler extra params */
#endif
DN_LAST,
};
enum { /* subtype for schedulers, flowset and the like */
DN_SCHED_UNKNOWN = 0,
DN_SCHED_FIFO = 1,
DN_SCHED_WF2QP = 2,
/* others are in individual modules */
};
enum { /* user flags */
DN_HAVE_MASK = 0x0001, /* fs or sched has a mask */
DN_NOERROR = 0x0002, /* do not report errors */
DN_QHT_HASH = 0x0004, /* qht is a hash table */
DN_QSIZE_BYTES = 0x0008, /* queue size is in bytes */
DN_HAS_PROFILE = 0x0010, /* a link has a profile */
DN_IS_RED = 0x0020,
DN_IS_GENTLE_RED= 0x0040,
DN_IS_ECN = 0x0080,
#ifdef NEW_AQM
DN_IS_AQM = 0x0100, /* AQMs: e.g Codel & PIE */
#endif
DN_PIPE_CMD = 0x1000, /* pipe config... */
};
/*
* link template.
*/
struct dn_link {
struct dn_id oid;
/*
* Userland sets bw and delay in bits/s and milliseconds.
* The kernel converts this back and forth to bits/tick and ticks.
* XXX what about burst ?
*/
int32_t link_nr;
uint32_t bandwidth; /* bit/s or bits/tick. */
int delay; /* ms and ticks */
uint64_t burst; /* scaled. bits*Hz XXX */
};
/*
* A flowset, which is a template for flows. Contains parameters
* from the command line: id, target scheduler, queue sizes, plr,
* flow masks, buckets for the flow hash, and possibly scheduler-
* specific parameters (weight, quantum and so on).
*/
struct dn_fs {
struct dn_id oid;
uint32_t fs_nr; /* the flowset number */
uint32_t flags; /* userland flags */
int qsize; /* queue size in slots or bytes */
int32_t pl_state; /* packet loss state */
uint32_t buckets; /* buckets used for the queue hash table */
struct ipfw_flow_id flow_mask;
uint32_t sched_nr; /* the scheduler we attach to */
/* generic scheduler parameters. Leave them at -1 if unset.
* Now we use 0: weight, 1: lmax, 2: priority
*/
int par[4];
/* RED/GRED parameters.
* weight and probabilities are in the range 0..1 represented
* in fixed point arithmetic with SCALE_RED decimal bits.
*/
#define SCALE_RED 16
#define SCALE(x) ( (x) << SCALE_RED )
#define SCALE_VAL(x) ( (x) >> SCALE_RED )
#define SCALE_MUL(x,y) ( ( (x) * (y) ) >> SCALE_RED )
int w_q ; /* queue weight (scaled) */
int max_th ; /* maximum threshold for queue (scaled) */
int min_th ; /* minimum threshold for queue (scaled) */
int max_p ; /* maximum value for p_b (scaled) */
int32_t plr[4]; /* PLR, pkt loss rate (2^31-1 means 100%) */
};
/*
* dn_flow collects flow_id and stats for queues and scheduler
* instances, and is used to pass these info to userland.
* oid.type/oid.subtype describe the object, oid.id is number
* of the parent object.
*/
struct dn_flow {
struct dn_id oid;
struct ipfw_flow_id fid;
uint64_t tot_pkts; /* statistics counters */
uint64_t tot_bytes;
uint32_t length; /* Queue length, in packets */
uint32_t len_bytes; /* Queue length, in bytes */
uint32_t drops;
};
/*
* Scheduler template, mostly indicating the name, number,
* sched_mask and buckets.
*/
struct dn_sch {
struct dn_id oid;
uint32_t sched_nr; /* N, scheduler number */
uint32_t buckets; /* number of buckets for the instances */
uint32_t flags; /* have_mask, ... */
char name[16]; /* null terminated */
/* mask to select the appropriate scheduler instance */
struct ipfw_flow_id sched_mask; /* M */
};
/* A delay profile is attached to a link.
* Note that a profile, as any other object, cannot be longer than 2^16
*/
#define ED_MAX_SAMPLES_NO 1024
struct dn_profile {
struct dn_id oid;
/* fields to simulate a delay profile */
#define ED_MAX_NAME_LEN 32
char name[ED_MAX_NAME_LEN];
int link_nr;
int loss_level;
uint32_t bandwidth; // XXX use link bandwidth?
int samples_no; /* actual len of samples[] */
int samples[ED_MAX_SAMPLES_NO]; /* may be shorter */
};
#ifdef NEW_AQM
/* Extra parameters for AQM and scheduler.
* This struct is used to pass and retrieve parameters (configurations)
* to/from AQM and Scheduler.
*/
struct dn_extra_parms {
struct dn_id oid;
char name[16];
uint32_t nr;
#define DN_MAX_EXTRA_PARM 10
int64_t par[DN_MAX_EXTRA_PARM];
};
#endif
/*
* Overall structure of dummynet
In dummynet, packets are selected with the firewall rules, and passed
to two different objects: PIPE or QUEUE (bad name).
A QUEUE defines a classifier, which groups packets into flows
according to a 'mask', puts them into independent queues (one
per flow) with configurable size and queue management policy,
and passes flows to a scheduler:
(flow_mask|sched_mask) sched_mask
+---------+ weight Wx +-------------+
| |->-[flow]-->--| |-+
-->--| QUEUE x | ... | | |
| |->-[flow]-->--| SCHEDuler N | |
+---------+ | | |
... | +--[LINK N]-->--
+---------+ weight Wy | | +--[LINK N]-->--
| |->-[flow]-->--| | |
-->--| QUEUE y | ... | | |
| |->-[flow]-->--| | |
+---------+ +-------------+ |
+-------------+
Many QUEUE objects can connect to the same scheduler, each
QUEUE object can have its own set of parameters.
In turn, the SCHEDuler 'forks' multiple instances according
to a 'sched_mask', each instance manages its own set of queues
and transmits on a private instance of a configurable LINK.
A PIPE is a simplified version of the above, where there
is no flow_mask, and each scheduler instance handles a single queue.
The following data structures (visible from userland) describe
the objects used by dummynet:
+ dn_link, contains the main configuration parameters related
to delay and bandwidth;
+ dn_profile describes a delay profile;
+ dn_flow describes the flow status (flow id, statistics)
+ dn_sch describes a scheduler
+ dn_fs describes a flowset (msk, weight, queue parameters)
*
*/
#endif /* _IP_DUMMYNET_H */