1*5e3eaea3SApple OSS Distributions /* 2*5e3eaea3SApple OSS Distributions * Copyright (c) 2000-2021 Apple Inc. All rights reserved. 3*5e3eaea3SApple OSS Distributions * 4*5e3eaea3SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5*5e3eaea3SApple OSS Distributions * 6*5e3eaea3SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 7*5e3eaea3SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 8*5e3eaea3SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 9*5e3eaea3SApple OSS Distributions * compliance with the License. The rights granted to you under the License 10*5e3eaea3SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 11*5e3eaea3SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 12*5e3eaea3SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 13*5e3eaea3SApple OSS Distributions * terms of an Apple operating system software license agreement. 14*5e3eaea3SApple OSS Distributions * 15*5e3eaea3SApple OSS Distributions * Please obtain a copy of the License at 16*5e3eaea3SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 17*5e3eaea3SApple OSS Distributions * 18*5e3eaea3SApple OSS Distributions * The Original Code and all software distributed under the License are 19*5e3eaea3SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20*5e3eaea3SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21*5e3eaea3SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22*5e3eaea3SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23*5e3eaea3SApple OSS Distributions * Please see the License for the specific language governing rights and 24*5e3eaea3SApple OSS Distributions * limitations under the License. 25*5e3eaea3SApple OSS Distributions * 26*5e3eaea3SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27*5e3eaea3SApple OSS Distributions */ 28*5e3eaea3SApple OSS Distributions /* 29*5e3eaea3SApple OSS Distributions * Copyright (c) 1998-2002 Luigi Rizzo, Universita` di Pisa 30*5e3eaea3SApple OSS Distributions * Portions Copyright (c) 2000 Akamba Corp. 31*5e3eaea3SApple OSS Distributions * All rights reserved 32*5e3eaea3SApple OSS Distributions * 33*5e3eaea3SApple OSS Distributions * Redistribution and use in source and binary forms, with or without 34*5e3eaea3SApple OSS Distributions * modification, are permitted provided that the following conditions 35*5e3eaea3SApple OSS Distributions * are met: 36*5e3eaea3SApple OSS Distributions * 1. Redistributions of source code must retain the above copyright 37*5e3eaea3SApple OSS Distributions * notice, this list of conditions and the following disclaimer. 38*5e3eaea3SApple OSS Distributions * 2. Redistributions in binary form must reproduce the above copyright 39*5e3eaea3SApple OSS Distributions * notice, this list of conditions and the following disclaimer in the 40*5e3eaea3SApple OSS Distributions * documentation and/or other materials provided with the distribution. 41*5e3eaea3SApple OSS Distributions * 42*5e3eaea3SApple OSS Distributions * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 43*5e3eaea3SApple OSS Distributions * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44*5e3eaea3SApple OSS Distributions * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45*5e3eaea3SApple OSS Distributions * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 46*5e3eaea3SApple OSS Distributions * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47*5e3eaea3SApple OSS Distributions * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48*5e3eaea3SApple OSS Distributions * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49*5e3eaea3SApple OSS Distributions * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50*5e3eaea3SApple OSS Distributions * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51*5e3eaea3SApple OSS Distributions * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52*5e3eaea3SApple OSS Distributions * SUCH DAMAGE. 53*5e3eaea3SApple OSS Distributions * 54*5e3eaea3SApple OSS Distributions * $FreeBSD: src/sys/netinet/ip_dummynet.h,v 1.32 2004/08/17 22:05:54 andre Exp $ 55*5e3eaea3SApple OSS Distributions */ 56*5e3eaea3SApple OSS Distributions 57*5e3eaea3SApple OSS Distributions #ifndef _IP_DUMMYNET_H 58*5e3eaea3SApple OSS Distributions #define _IP_DUMMYNET_H 59*5e3eaea3SApple OSS Distributions 60*5e3eaea3SApple OSS Distributions #include <sys/appleapiopts.h> 61*5e3eaea3SApple OSS Distributions 62*5e3eaea3SApple OSS Distributions #ifdef PRIVATE 63*5e3eaea3SApple OSS Distributions #include <netinet/ip_flowid.h> 64*5e3eaea3SApple OSS Distributions 65*5e3eaea3SApple OSS Distributions /* Apply ipv6 mask on ipv6 addr */ 66*5e3eaea3SApple OSS Distributions #define APPLY_MASK(addr, mask) \ 67*5e3eaea3SApple OSS Distributions (addr)->__u6_addr.__u6_addr32[0] &= (mask)->__u6_addr.__u6_addr32[0]; \ 68*5e3eaea3SApple OSS Distributions (addr)->__u6_addr.__u6_addr32[1] &= (mask)->__u6_addr.__u6_addr32[1]; \ 69*5e3eaea3SApple OSS Distributions (addr)->__u6_addr.__u6_addr32[2] &= (mask)->__u6_addr.__u6_addr32[2]; \ 70*5e3eaea3SApple OSS Distributions (addr)->__u6_addr.__u6_addr32[3] &= (mask)->__u6_addr.__u6_addr32[3]; 71*5e3eaea3SApple OSS Distributions 72*5e3eaea3SApple OSS Distributions /* 73*5e3eaea3SApple OSS Distributions * Definition of dummynet data structures. In the structures, I decided 74*5e3eaea3SApple OSS Distributions * not to use the macros in <sys/queue.h> in the hope of making the code 75*5e3eaea3SApple OSS Distributions * easier to port to other architectures. The type of lists and queue we 76*5e3eaea3SApple OSS Distributions * use here is pretty simple anyways. 77*5e3eaea3SApple OSS Distributions */ 78*5e3eaea3SApple OSS Distributions 79*5e3eaea3SApple OSS Distributions /* 80*5e3eaea3SApple OSS Distributions * We start with a heap, which is used in the scheduler to decide when 81*5e3eaea3SApple OSS Distributions * to transmit packets etc. 82*5e3eaea3SApple OSS Distributions * 83*5e3eaea3SApple OSS Distributions * The key for the heap is used for two different values: 84*5e3eaea3SApple OSS Distributions * 85*5e3eaea3SApple OSS Distributions * 1. timer ticks- max 10K/second, so 32 bits are enough; 86*5e3eaea3SApple OSS Distributions * 87*5e3eaea3SApple OSS Distributions * 2. virtual times. These increase in steps of len/x, where len is the 88*5e3eaea3SApple OSS Distributions * packet length, and x is either the weight of the flow, or the 89*5e3eaea3SApple OSS Distributions * sum of all weights. 90*5e3eaea3SApple OSS Distributions * If we limit to max 1000 flows and a max weight of 100, then 91*5e3eaea3SApple OSS Distributions * x needs 17 bits. The packet size is 16 bits, so we can easily 92*5e3eaea3SApple OSS Distributions * overflow if we do not allow errors. 93*5e3eaea3SApple OSS Distributions * So we use a key "dn_key" which is 64 bits. Some macros are used to 94*5e3eaea3SApple OSS Distributions * compare key values and handle wraparounds. 95*5e3eaea3SApple OSS Distributions * MAX64 returns the largest of two key values. 96*5e3eaea3SApple OSS Distributions * MY_M is used as a shift count when doing fixed point arithmetic 97*5e3eaea3SApple OSS Distributions * (a better name would be useful...). 98*5e3eaea3SApple OSS Distributions */ 99*5e3eaea3SApple OSS Distributions typedef u_int64_t dn_key; /* sorting key */ 100*5e3eaea3SApple OSS Distributions #define DN_KEY_LT(a, b) ((int64_t)((a)-(b)) < 0) 101*5e3eaea3SApple OSS Distributions #define DN_KEY_LEQ(a, b) ((int64_t)((a)-(b)) <= 0) 102*5e3eaea3SApple OSS Distributions #define DN_KEY_GT(a, b) ((int64_t)((a)-(b)) > 0) 103*5e3eaea3SApple OSS Distributions #define DN_KEY_GEQ(a, b) ((int64_t)((a)-(b)) >= 0) 104*5e3eaea3SApple OSS Distributions #define MAX64(x, y) (( (int64_t) ( (y)-(x) )) > 0 ) ? (y) : (x) 105*5e3eaea3SApple OSS Distributions #define MY_M 16 /* number of left shift to obtain a larger precision */ 106*5e3eaea3SApple OSS Distributions 107*5e3eaea3SApple OSS Distributions /* 108*5e3eaea3SApple OSS Distributions * XXX With this scaling, max 1000 flows, max weight 100, 1Gbit/s, the 109*5e3eaea3SApple OSS Distributions * virtual time wraps every 15 days. 110*5e3eaea3SApple OSS Distributions */ 111*5e3eaea3SApple OSS Distributions 112*5e3eaea3SApple OSS Distributions /* 113*5e3eaea3SApple OSS Distributions * The maximum hash table size for queues. This value must be a power 114*5e3eaea3SApple OSS Distributions * of 2. 115*5e3eaea3SApple OSS Distributions */ 116*5e3eaea3SApple OSS Distributions #define DN_MAX_HASH_SIZE 65536 117*5e3eaea3SApple OSS Distributions 118*5e3eaea3SApple OSS Distributions /* 119*5e3eaea3SApple OSS Distributions * A heap entry is made of a key and a pointer to the actual 120*5e3eaea3SApple OSS Distributions * object stored in the heap. 121*5e3eaea3SApple OSS Distributions * The heap is an array of dn_heap_entry entries, dynamically allocated. 122*5e3eaea3SApple OSS Distributions * Current size is "size", with "elements" actually in use. 123*5e3eaea3SApple OSS Distributions * The heap normally supports only ordered insert and extract from the top. 124*5e3eaea3SApple OSS Distributions * If we want to extract an object from the middle of the heap, we 125*5e3eaea3SApple OSS Distributions * have to know where the object itself is located in the heap (or we 126*5e3eaea3SApple OSS Distributions * need to scan the whole array). To this purpose, an object has a 127*5e3eaea3SApple OSS Distributions * field (int) which contains the index of the object itself into the 128*5e3eaea3SApple OSS Distributions * heap. When the object is moved, the field must also be updated. 129*5e3eaea3SApple OSS Distributions * The offset of the index in the object is stored in the 'offset' 130*5e3eaea3SApple OSS Distributions * field in the heap descriptor. The assumption is that this offset 131*5e3eaea3SApple OSS Distributions * is non-zero if we want to support extract from the middle. 132*5e3eaea3SApple OSS Distributions */ 133*5e3eaea3SApple OSS Distributions struct dn_heap_entry { 134*5e3eaea3SApple OSS Distributions dn_key key; /* sorting key. Topmost element is smallest one */ 135*5e3eaea3SApple OSS Distributions void *object; /* object pointer */ 136*5e3eaea3SApple OSS Distributions }; 137*5e3eaea3SApple OSS Distributions 138*5e3eaea3SApple OSS Distributions struct dn_heap { 139*5e3eaea3SApple OSS Distributions int size; 140*5e3eaea3SApple OSS Distributions int elements; 141*5e3eaea3SApple OSS Distributions int offset; /* XXX if > 0 this is the offset of direct ptr to obj */ 142*5e3eaea3SApple OSS Distributions struct dn_heap_entry *p; /* really an array of "size" entries */ 143*5e3eaea3SApple OSS Distributions }; 144*5e3eaea3SApple OSS Distributions 145*5e3eaea3SApple OSS Distributions /* 146*5e3eaea3SApple OSS Distributions * Packets processed by dummynet have an mbuf tag associated with 147*5e3eaea3SApple OSS Distributions * them that carries their dummynet state. This is used within 148*5e3eaea3SApple OSS Distributions * the dummynet code as well as outside when checking for special 149*5e3eaea3SApple OSS Distributions * processing requirements. 150*5e3eaea3SApple OSS Distributions */ 151*5e3eaea3SApple OSS Distributions #ifdef KERNEL 152*5e3eaea3SApple OSS Distributions #include <net/if_var.h> 153*5e3eaea3SApple OSS Distributions #include <net/route.h> 154*5e3eaea3SApple OSS Distributions #include <netinet/ip_var.h> /* for ip_out_args */ 155*5e3eaea3SApple OSS Distributions #include <netinet/ip6.h> /* for ip6_out_args */ 156*5e3eaea3SApple OSS Distributions #include <netinet/in.h> 157*5e3eaea3SApple OSS Distributions #include <netinet6/ip6_var.h> /* for ip6_out_args */ 158*5e3eaea3SApple OSS Distributions 159*5e3eaea3SApple OSS Distributions struct dn_pkt_tag { 160*5e3eaea3SApple OSS Distributions void *dn_pf_rule; /* matching PF rule */ 161*5e3eaea3SApple OSS Distributions int dn_dir; /* action when packet comes out. */ 162*5e3eaea3SApple OSS Distributions #define DN_TO_IP_OUT 1 163*5e3eaea3SApple OSS Distributions #define DN_TO_IP_IN 2 164*5e3eaea3SApple OSS Distributions #define DN_TO_BDG_FWD 3 165*5e3eaea3SApple OSS Distributions #define DN_TO_IP6_IN 4 166*5e3eaea3SApple OSS Distributions #define DN_TO_IP6_OUT 5 167*5e3eaea3SApple OSS Distributions dn_key dn_output_time; /* when the pkt is due for delivery */ 168*5e3eaea3SApple OSS Distributions struct ifnet *dn_ifp; /* interface, for ip[6]_output */ 169*5e3eaea3SApple OSS Distributions union { 170*5e3eaea3SApple OSS Distributions struct sockaddr_in _dn_dst; 171*5e3eaea3SApple OSS Distributions struct sockaddr_in6 _dn_dst6; 172*5e3eaea3SApple OSS Distributions } dn_dst_; 173*5e3eaea3SApple OSS Distributions #define dn_dst dn_dst_._dn_dst 174*5e3eaea3SApple OSS Distributions #define dn_dst6 dn_dst_._dn_dst6 175*5e3eaea3SApple OSS Distributions union { 176*5e3eaea3SApple OSS Distributions struct route _dn_ro; /* route, for ip_output. MUST COPY */ 177*5e3eaea3SApple OSS Distributions struct route_in6 _dn_ro6;/* route, for ip6_output. MUST COPY */ 178*5e3eaea3SApple OSS Distributions } dn_ro_; 179*5e3eaea3SApple OSS Distributions #define dn_ro dn_ro_._dn_ro 180*5e3eaea3SApple OSS Distributions #define dn_ro6 dn_ro_._dn_ro6 181*5e3eaea3SApple OSS Distributions struct route_in6 dn_ro6_pmtu; /* for ip6_output */ 182*5e3eaea3SApple OSS Distributions struct ifnet *dn_origifp; /* for ip6_output */ 183*5e3eaea3SApple OSS Distributions u_int32_t dn_mtu; /* for ip6_output */ 184*5e3eaea3SApple OSS Distributions u_int32_t dn_unfragpartlen; /* for ip6_output */ 185*5e3eaea3SApple OSS Distributions struct ip6_exthdrs dn_exthdrs; /* for ip6_output */ 186*5e3eaea3SApple OSS Distributions int dn_flags; /* flags, for ip[6]_output */ 187*5e3eaea3SApple OSS Distributions union { 188*5e3eaea3SApple OSS Distributions struct ip_out_args _dn_ipoa;/* output args, for ip_output. MUST COPY */ 189*5e3eaea3SApple OSS Distributions struct ip6_out_args _dn_ip6oa;/* output args, for ip_output. MUST COPY */ 190*5e3eaea3SApple OSS Distributions } dn_ipoa_; 191*5e3eaea3SApple OSS Distributions #define dn_ipoa dn_ipoa_._dn_ipoa 192*5e3eaea3SApple OSS Distributions #define dn_ip6oa dn_ipoa_._dn_ip6oa 193*5e3eaea3SApple OSS Distributions }; 194*5e3eaea3SApple OSS Distributions #else 195*5e3eaea3SApple OSS Distributions struct dn_pkt; 196*5e3eaea3SApple OSS Distributions #endif /* KERNEL */ 197*5e3eaea3SApple OSS Distributions 198*5e3eaea3SApple OSS Distributions /* 199*5e3eaea3SApple OSS Distributions * Overall structure of dummynet (with WF2Q+): 200*5e3eaea3SApple OSS Distributions * 201*5e3eaea3SApple OSS Distributions * In dummynet, packets are selected with the firewall rules, and passed 202*5e3eaea3SApple OSS Distributions * to two different objects: PIPE or QUEUE. 203*5e3eaea3SApple OSS Distributions * 204*5e3eaea3SApple OSS Distributions * A QUEUE is just a queue with configurable size and queue management 205*5e3eaea3SApple OSS Distributions * policy. It is also associated with a mask (to discriminate among 206*5e3eaea3SApple OSS Distributions * different flows), a weight (used to give different shares of the 207*5e3eaea3SApple OSS Distributions * bandwidth to different flows) and a "pipe", which essentially 208*5e3eaea3SApple OSS Distributions * supplies the transmit clock for all queues associated with that 209*5e3eaea3SApple OSS Distributions * pipe. 210*5e3eaea3SApple OSS Distributions * 211*5e3eaea3SApple OSS Distributions * A PIPE emulates a fixed-bandwidth link, whose bandwidth is 212*5e3eaea3SApple OSS Distributions * configurable. The "clock" for a pipe can come from either an 213*5e3eaea3SApple OSS Distributions * internal timer, or from the transmit interrupt of an interface. 214*5e3eaea3SApple OSS Distributions * A pipe is also associated with one (or more, if masks are used) 215*5e3eaea3SApple OSS Distributions * queue, where all packets for that pipe are stored. 216*5e3eaea3SApple OSS Distributions * 217*5e3eaea3SApple OSS Distributions * The bandwidth available on the pipe is shared by the queues 218*5e3eaea3SApple OSS Distributions * associated with that pipe (only one in case the packet is sent 219*5e3eaea3SApple OSS Distributions * to a PIPE) according to the WF2Q+ scheduling algorithm and the 220*5e3eaea3SApple OSS Distributions * configured weights. 221*5e3eaea3SApple OSS Distributions * 222*5e3eaea3SApple OSS Distributions * In general, incoming packets are stored in the appropriate queue, 223*5e3eaea3SApple OSS Distributions * which is then placed into one of a few heaps managed by a scheduler 224*5e3eaea3SApple OSS Distributions * to decide when the packet should be extracted. 225*5e3eaea3SApple OSS Distributions * The scheduler (a function called dummynet()) is run at every timer 226*5e3eaea3SApple OSS Distributions * tick, and grabs queues from the head of the heaps when they are 227*5e3eaea3SApple OSS Distributions * ready for processing. 228*5e3eaea3SApple OSS Distributions * 229*5e3eaea3SApple OSS Distributions * There are three data structures definining a pipe and associated queues: 230*5e3eaea3SApple OSS Distributions * 231*5e3eaea3SApple OSS Distributions + dn_pipe, which contains the main configuration parameters related 232*5e3eaea3SApple OSS Distributions + to delay and bandwidth; 233*5e3eaea3SApple OSS Distributions + dn_flow_set, which contains WF2Q+ configuration, flow 234*5e3eaea3SApple OSS Distributions + masks, plr and RED configuration; 235*5e3eaea3SApple OSS Distributions + dn_flow_queue, which is the per-flow queue (containing the packets) 236*5e3eaea3SApple OSS Distributions + 237*5e3eaea3SApple OSS Distributions + Multiple dn_flow_set can be linked to the same pipe, and multiple 238*5e3eaea3SApple OSS Distributions + dn_flow_queue can be linked to the same dn_flow_set. 239*5e3eaea3SApple OSS Distributions + All data structures are linked in a linear list which is used for 240*5e3eaea3SApple OSS Distributions + housekeeping purposes. 241*5e3eaea3SApple OSS Distributions + 242*5e3eaea3SApple OSS Distributions + During configuration, we create and initialize the dn_flow_set 243*5e3eaea3SApple OSS Distributions + and dn_pipe structures (a dn_pipe also contains a dn_flow_set). 244*5e3eaea3SApple OSS Distributions + 245*5e3eaea3SApple OSS Distributions + At runtime: packets are sent to the appropriate dn_flow_set (either 246*5e3eaea3SApple OSS Distributions + WFQ ones, or the one embedded in the dn_pipe for fixed-rate flows), 247*5e3eaea3SApple OSS Distributions + which in turn dispatches them to the appropriate dn_flow_queue 248*5e3eaea3SApple OSS Distributions + (created dynamically according to the masks). 249*5e3eaea3SApple OSS Distributions + 250*5e3eaea3SApple OSS Distributions + The transmit clock for fixed rate flows (ready_event()) selects the 251*5e3eaea3SApple OSS Distributions + dn_flow_queue to be used to transmit the next packet. For WF2Q, 252*5e3eaea3SApple OSS Distributions + wfq_ready_event() extract a pipe which in turn selects the right 253*5e3eaea3SApple OSS Distributions + flow using a number of heaps defined into the pipe itself. 254*5e3eaea3SApple OSS Distributions + 255*5e3eaea3SApple OSS Distributions * 256*5e3eaea3SApple OSS Distributions */ 257*5e3eaea3SApple OSS Distributions 258*5e3eaea3SApple OSS Distributions /* 259*5e3eaea3SApple OSS Distributions * per flow queue. This contains the flow identifier, the queue 260*5e3eaea3SApple OSS Distributions * of packets, counters, and parameters used to support both RED and 261*5e3eaea3SApple OSS Distributions * WF2Q+. 262*5e3eaea3SApple OSS Distributions * 263*5e3eaea3SApple OSS Distributions * A dn_flow_queue is created and initialized whenever a packet for 264*5e3eaea3SApple OSS Distributions * a new flow arrives. 265*5e3eaea3SApple OSS Distributions */ 266*5e3eaea3SApple OSS Distributions struct dn_flow_queue { 267*5e3eaea3SApple OSS Distributions struct dn_flow_queue *next; 268*5e3eaea3SApple OSS Distributions struct ip_flow_id id; 269*5e3eaea3SApple OSS Distributions 270*5e3eaea3SApple OSS Distributions struct mbuf *head, *tail; /* queue of packets */ 271*5e3eaea3SApple OSS Distributions u_int len; 272*5e3eaea3SApple OSS Distributions u_int len_bytes; 273*5e3eaea3SApple OSS Distributions u_int32_t numbytes; /* credit for transmission (dynamic queues) */ 274*5e3eaea3SApple OSS Distributions 275*5e3eaea3SApple OSS Distributions u_int64_t tot_pkts; /* statistics counters */ 276*5e3eaea3SApple OSS Distributions u_int64_t tot_bytes; 277*5e3eaea3SApple OSS Distributions u_int32_t drops; 278*5e3eaea3SApple OSS Distributions 279*5e3eaea3SApple OSS Distributions int hash_slot; /* debugging/diagnostic */ 280*5e3eaea3SApple OSS Distributions 281*5e3eaea3SApple OSS Distributions /* RED parameters */ 282*5e3eaea3SApple OSS Distributions int avg; /* average queue length est. (scaled) */ 283*5e3eaea3SApple OSS Distributions int count; /* arrivals since last RED drop */ 284*5e3eaea3SApple OSS Distributions int random; /* random value (scaled) */ 285*5e3eaea3SApple OSS Distributions u_int64_t q_time; /* start of queue idle time */ 286*5e3eaea3SApple OSS Distributions 287*5e3eaea3SApple OSS Distributions /* WF2Q+ support */ 288*5e3eaea3SApple OSS Distributions struct dn_flow_set *fs; /* parent flow set */ 289*5e3eaea3SApple OSS Distributions int heap_pos; /* position (index) of struct in heap */ 290*5e3eaea3SApple OSS Distributions dn_key sched_time; /* current time when queue enters ready_heap */ 291*5e3eaea3SApple OSS Distributions 292*5e3eaea3SApple OSS Distributions dn_key S, F; /* start time, finish time */ 293*5e3eaea3SApple OSS Distributions /* 294*5e3eaea3SApple OSS Distributions * Setting F < S means the timestamp is invalid. We only need 295*5e3eaea3SApple OSS Distributions * to test this when the queue is empty. 296*5e3eaea3SApple OSS Distributions */ 297*5e3eaea3SApple OSS Distributions }; 298*5e3eaea3SApple OSS Distributions 299*5e3eaea3SApple OSS Distributions /* 300*5e3eaea3SApple OSS Distributions * flow_set descriptor. Contains the "template" parameters for the 301*5e3eaea3SApple OSS Distributions * queue configuration, and pointers to the hash table of dn_flow_queue's. 302*5e3eaea3SApple OSS Distributions * 303*5e3eaea3SApple OSS Distributions * The hash table is an array of lists -- we identify the slot by 304*5e3eaea3SApple OSS Distributions * hashing the flow-id, then scan the list looking for a match. 305*5e3eaea3SApple OSS Distributions * The size of the hash table (buckets) is configurable on a per-queue 306*5e3eaea3SApple OSS Distributions * basis. 307*5e3eaea3SApple OSS Distributions * 308*5e3eaea3SApple OSS Distributions * A dn_flow_set is created whenever a new queue or pipe is created (in the 309*5e3eaea3SApple OSS Distributions * latter case, the structure is located inside the struct dn_pipe). 310*5e3eaea3SApple OSS Distributions */ 311*5e3eaea3SApple OSS Distributions struct dn_flow_set { 312*5e3eaea3SApple OSS Distributions SLIST_ENTRY(dn_flow_set) next;/* linked list in a hash slot */ 313*5e3eaea3SApple OSS Distributions 314*5e3eaea3SApple OSS Distributions u_short fs_nr; /* flow_set number */ 315*5e3eaea3SApple OSS Distributions u_short flags_fs; 316*5e3eaea3SApple OSS Distributions #define DN_HAVE_FLOW_MASK 0x0001 317*5e3eaea3SApple OSS Distributions #define DN_IS_RED 0x0002 318*5e3eaea3SApple OSS Distributions #define DN_IS_GENTLE_RED 0x0004 319*5e3eaea3SApple OSS Distributions #define DN_QSIZE_IS_BYTES 0x0008 /* queue size is measured in bytes */ 320*5e3eaea3SApple OSS Distributions #define DN_NOERROR 0x0010 /* do not report ENOBUFS on drops */ 321*5e3eaea3SApple OSS Distributions #define DN_IS_PIPE 0x4000 322*5e3eaea3SApple OSS Distributions #define DN_IS_QUEUE 0x8000 323*5e3eaea3SApple OSS Distributions 324*5e3eaea3SApple OSS Distributions struct dn_pipe *pipe; /* pointer to parent pipe */ 325*5e3eaea3SApple OSS Distributions u_short parent_nr; /* parent pipe#, 0 if local to a pipe */ 326*5e3eaea3SApple OSS Distributions 327*5e3eaea3SApple OSS Distributions int weight; /* WFQ queue weight */ 328*5e3eaea3SApple OSS Distributions int qsize; /* queue size in slots or bytes */ 329*5e3eaea3SApple OSS Distributions int plr; /* pkt loss rate (2^31-1 means 100%) */ 330*5e3eaea3SApple OSS Distributions 331*5e3eaea3SApple OSS Distributions struct ip_flow_id flow_mask; 332*5e3eaea3SApple OSS Distributions 333*5e3eaea3SApple OSS Distributions /* hash table of queues onto this flow_set */ 334*5e3eaea3SApple OSS Distributions int rq_size; /* number of slots */ 335*5e3eaea3SApple OSS Distributions int rq_elements; /* active elements */ 336*5e3eaea3SApple OSS Distributions struct dn_flow_queue **rq; /* array of rq_size entries */ 337*5e3eaea3SApple OSS Distributions 338*5e3eaea3SApple OSS Distributions u_int32_t last_expired; /* do not expire too frequently */ 339*5e3eaea3SApple OSS Distributions int backlogged; /* #active queues for this flowset */ 340*5e3eaea3SApple OSS Distributions 341*5e3eaea3SApple OSS Distributions /* RED parameters */ 342*5e3eaea3SApple OSS Distributions #define SCALE_RED 16 343*5e3eaea3SApple OSS Distributions #define SCALE(x) ( (x) << SCALE_RED ) 344*5e3eaea3SApple OSS Distributions #define SCALE_VAL(x) ( (x) >> SCALE_RED ) 345*5e3eaea3SApple OSS Distributions #define SCALE_MUL(x, y) ( ( (x) * (y) ) >> SCALE_RED ) 346*5e3eaea3SApple OSS Distributions int w_q; /* queue weight (scaled) */ 347*5e3eaea3SApple OSS Distributions int max_th; /* maximum threshold for queue (scaled) */ 348*5e3eaea3SApple OSS Distributions int min_th; /* minimum threshold for queue (scaled) */ 349*5e3eaea3SApple OSS Distributions int max_p; /* maximum value for p_b (scaled) */ 350*5e3eaea3SApple OSS Distributions u_int c_1; /* max_p/(max_th-min_th) (scaled) */ 351*5e3eaea3SApple OSS Distributions u_int c_2; /* max_p*min_th/(max_th-min_th) (scaled) */ 352*5e3eaea3SApple OSS Distributions u_int c_3; /* for GRED, (1-max_p)/max_th (scaled) */ 353*5e3eaea3SApple OSS Distributions u_int c_4; /* for GRED, 1 - 2*max_p (scaled) */ 354*5e3eaea3SApple OSS Distributions u_int * w_q_lookup; /* lookup table for computing (1-w_q)^t */ 355*5e3eaea3SApple OSS Distributions u_int lookup_depth; /* depth of lookup table */ 356*5e3eaea3SApple OSS Distributions int lookup_step; /* granularity inside the lookup table */ 357*5e3eaea3SApple OSS Distributions int lookup_weight; /* equal to (1-w_q)^t / (1-w_q)^(t+1) */ 358*5e3eaea3SApple OSS Distributions int avg_pkt_size; /* medium packet size */ 359*5e3eaea3SApple OSS Distributions int max_pkt_size; /* max packet size */ 360*5e3eaea3SApple OSS Distributions }; 361*5e3eaea3SApple OSS Distributions 362*5e3eaea3SApple OSS Distributions SLIST_HEAD(dn_flow_set_head, dn_flow_set); 363*5e3eaea3SApple OSS Distributions 364*5e3eaea3SApple OSS Distributions /* 365*5e3eaea3SApple OSS Distributions * Pipe descriptor. Contains global parameters, delay-line queue, 366*5e3eaea3SApple OSS Distributions * and the flow_set used for fixed-rate queues. 367*5e3eaea3SApple OSS Distributions * 368*5e3eaea3SApple OSS Distributions * For WF2Q+ support it also has 3 heaps holding dn_flow_queue: 369*5e3eaea3SApple OSS Distributions * not_eligible_heap, for queues whose start time is higher 370*5e3eaea3SApple OSS Distributions * than the virtual time. Sorted by start time. 371*5e3eaea3SApple OSS Distributions * scheduler_heap, for queues eligible for scheduling. Sorted by 372*5e3eaea3SApple OSS Distributions * finish time. 373*5e3eaea3SApple OSS Distributions * idle_heap, all flows that are idle and can be removed. We 374*5e3eaea3SApple OSS Distributions * do that on each tick so we do not slow down too much 375*5e3eaea3SApple OSS Distributions * operations during forwarding. 376*5e3eaea3SApple OSS Distributions * 377*5e3eaea3SApple OSS Distributions */ 378*5e3eaea3SApple OSS Distributions struct dn_pipe { /* a pipe */ 379*5e3eaea3SApple OSS Distributions SLIST_ENTRY(dn_pipe) next;/* linked list in a hash slot */ 380*5e3eaea3SApple OSS Distributions 381*5e3eaea3SApple OSS Distributions int pipe_nr; /* number */ 382*5e3eaea3SApple OSS Distributions int bandwidth; /* really, bytes/tick. */ 383*5e3eaea3SApple OSS Distributions int delay; /* really, ticks */ 384*5e3eaea3SApple OSS Distributions 385*5e3eaea3SApple OSS Distributions struct mbuf *head, *tail; /* packets in delay line */ 386*5e3eaea3SApple OSS Distributions 387*5e3eaea3SApple OSS Distributions /* WF2Q+ */ 388*5e3eaea3SApple OSS Distributions struct dn_heap scheduler_heap; /* top extract - key Finish time*/ 389*5e3eaea3SApple OSS Distributions struct dn_heap not_eligible_heap; /* top extract- key Start time */ 390*5e3eaea3SApple OSS Distributions struct dn_heap idle_heap; /* random extract - key Start=Finish time */ 391*5e3eaea3SApple OSS Distributions 392*5e3eaea3SApple OSS Distributions dn_key V; /* virtual time */ 393*5e3eaea3SApple OSS Distributions int sum; /* sum of weights of all active sessions */ 394*5e3eaea3SApple OSS Distributions int numbytes; /* bits I can transmit (more or less). */ 395*5e3eaea3SApple OSS Distributions 396*5e3eaea3SApple OSS Distributions dn_key sched_time; /* time pipe was scheduled in ready_heap */ 397*5e3eaea3SApple OSS Distributions 398*5e3eaea3SApple OSS Distributions /* 399*5e3eaea3SApple OSS Distributions * When the tx clock come from an interface (if_name[0] != '\0'), its name 400*5e3eaea3SApple OSS Distributions * is stored below, whereas the ifp is filled when the rule is configured. 401*5e3eaea3SApple OSS Distributions */ 402*5e3eaea3SApple OSS Distributions char if_name[IFNAMSIZ]; 403*5e3eaea3SApple OSS Distributions struct ifnet *ifp; 404*5e3eaea3SApple OSS Distributions int ready; /* set if ifp != NULL and we got a signal from it */ 405*5e3eaea3SApple OSS Distributions 406*5e3eaea3SApple OSS Distributions struct dn_flow_set fs; /* used with fixed-rate flows */ 407*5e3eaea3SApple OSS Distributions }; 408*5e3eaea3SApple OSS Distributions 409*5e3eaea3SApple OSS Distributions SLIST_HEAD(dn_pipe_head, dn_pipe); 410*5e3eaea3SApple OSS Distributions 411*5e3eaea3SApple OSS Distributions #ifdef BSD_KERNEL_PRIVATE 412*5e3eaea3SApple OSS Distributions extern uint32_t my_random(void); 413*5e3eaea3SApple OSS Distributions void ip_dn_init(void); 414*5e3eaea3SApple OSS Distributions 415*5e3eaea3SApple OSS Distributions typedef int ip_dn_ctl_t(struct sockopt *); /* raw_ip.c */ 416*5e3eaea3SApple OSS Distributions typedef int ip_dn_io_t(struct mbuf *m, int pipe_nr, int dir, 417*5e3eaea3SApple OSS Distributions struct ip_fw_args *fwa); 418*5e3eaea3SApple OSS Distributions extern ip_dn_ctl_t *ip_dn_ctl_ptr; 419*5e3eaea3SApple OSS Distributions extern ip_dn_io_t *ip_dn_io_ptr; 420*5e3eaea3SApple OSS Distributions #define DUMMYNET_LOADED (ip_dn_io_ptr != NULL) 421*5e3eaea3SApple OSS Distributions 422*5e3eaea3SApple OSS Distributions #pragma pack(4) 423*5e3eaea3SApple OSS Distributions 424*5e3eaea3SApple OSS Distributions struct dn_heap_32 { 425*5e3eaea3SApple OSS Distributions int size; 426*5e3eaea3SApple OSS Distributions int elements; 427*5e3eaea3SApple OSS Distributions int offset; /* XXX if > 0 this is the offset of direct ptr to obj */ 428*5e3eaea3SApple OSS Distributions user32_addr_t p; /* really an array of "size" entries */ 429*5e3eaea3SApple OSS Distributions }; 430*5e3eaea3SApple OSS Distributions 431*5e3eaea3SApple OSS Distributions struct dn_flow_queue_32 { 432*5e3eaea3SApple OSS Distributions user32_addr_t next; 433*5e3eaea3SApple OSS Distributions struct ip_flow_id id; 434*5e3eaea3SApple OSS Distributions 435*5e3eaea3SApple OSS Distributions user32_addr_t head, tail; /* queue of packets */ 436*5e3eaea3SApple OSS Distributions u_int len; 437*5e3eaea3SApple OSS Distributions u_int len_bytes; 438*5e3eaea3SApple OSS Distributions u_int32_t numbytes; /* credit for transmission (dynamic queues) */ 439*5e3eaea3SApple OSS Distributions 440*5e3eaea3SApple OSS Distributions u_int64_t tot_pkts; /* statistics counters */ 441*5e3eaea3SApple OSS Distributions u_int64_t tot_bytes; 442*5e3eaea3SApple OSS Distributions u_int32_t drops; 443*5e3eaea3SApple OSS Distributions 444*5e3eaea3SApple OSS Distributions int hash_slot; /* debugging/diagnostic */ 445*5e3eaea3SApple OSS Distributions 446*5e3eaea3SApple OSS Distributions /* RED parameters */ 447*5e3eaea3SApple OSS Distributions int avg; /* average queue length est. (scaled) */ 448*5e3eaea3SApple OSS Distributions int count; /* arrivals since last RED drop */ 449*5e3eaea3SApple OSS Distributions int random; /* random value (scaled) */ 450*5e3eaea3SApple OSS Distributions u_int32_t q_time; /* start of queue idle time */ 451*5e3eaea3SApple OSS Distributions 452*5e3eaea3SApple OSS Distributions /* WF2Q+ support */ 453*5e3eaea3SApple OSS Distributions user32_addr_t fs; /* parent flow set */ 454*5e3eaea3SApple OSS Distributions int heap_pos; /* position (index) of struct in heap */ 455*5e3eaea3SApple OSS Distributions dn_key sched_time; /* current time when queue enters ready_heap */ 456*5e3eaea3SApple OSS Distributions 457*5e3eaea3SApple OSS Distributions dn_key S, F; /* start time, finish time */ 458*5e3eaea3SApple OSS Distributions /* 459*5e3eaea3SApple OSS Distributions * Setting F < S means the timestamp is invalid. We only need 460*5e3eaea3SApple OSS Distributions * to test this when the queue is empty. 461*5e3eaea3SApple OSS Distributions */ 462*5e3eaea3SApple OSS Distributions }; 463*5e3eaea3SApple OSS Distributions 464*5e3eaea3SApple OSS Distributions struct dn_flow_set_32 { 465*5e3eaea3SApple OSS Distributions user32_addr_t next;/* next flow set in all_flow_sets list */ 466*5e3eaea3SApple OSS Distributions 467*5e3eaea3SApple OSS Distributions u_short fs_nr; /* flow_set number */ 468*5e3eaea3SApple OSS Distributions u_short flags_fs; 469*5e3eaea3SApple OSS Distributions #define DN_HAVE_FLOW_MASK 0x0001 470*5e3eaea3SApple OSS Distributions #define DN_IS_RED 0x0002 471*5e3eaea3SApple OSS Distributions #define DN_IS_GENTLE_RED 0x0004 472*5e3eaea3SApple OSS Distributions #define DN_QSIZE_IS_BYTES 0x0008 /* queue size is measured in bytes */ 473*5e3eaea3SApple OSS Distributions #define DN_NOERROR 0x0010 /* do not report ENOBUFS on drops */ 474*5e3eaea3SApple OSS Distributions #define DN_IS_PIPE 0x4000 475*5e3eaea3SApple OSS Distributions #define DN_IS_QUEUE 0x8000 476*5e3eaea3SApple OSS Distributions 477*5e3eaea3SApple OSS Distributions user32_addr_t pipe; /* pointer to parent pipe */ 478*5e3eaea3SApple OSS Distributions u_short parent_nr; /* parent pipe#, 0 if local to a pipe */ 479*5e3eaea3SApple OSS Distributions 480*5e3eaea3SApple OSS Distributions int weight; /* WFQ queue weight */ 481*5e3eaea3SApple OSS Distributions int qsize; /* queue size in slots or bytes */ 482*5e3eaea3SApple OSS Distributions int plr; /* pkt loss rate (2^31-1 means 100%) */ 483*5e3eaea3SApple OSS Distributions 484*5e3eaea3SApple OSS Distributions struct ip_flow_id flow_mask; 485*5e3eaea3SApple OSS Distributions 486*5e3eaea3SApple OSS Distributions /* hash table of queues onto this flow_set */ 487*5e3eaea3SApple OSS Distributions int rq_size; /* number of slots */ 488*5e3eaea3SApple OSS Distributions int rq_elements; /* active elements */ 489*5e3eaea3SApple OSS Distributions user32_addr_t rq; /* array of rq_size entries */ 490*5e3eaea3SApple OSS Distributions 491*5e3eaea3SApple OSS Distributions u_int32_t last_expired; /* do not expire too frequently */ 492*5e3eaea3SApple OSS Distributions int backlogged; /* #active queues for this flowset */ 493*5e3eaea3SApple OSS Distributions 494*5e3eaea3SApple OSS Distributions /* RED parameters */ 495*5e3eaea3SApple OSS Distributions #define SCALE_RED 16 496*5e3eaea3SApple OSS Distributions #define SCALE(x) ( (x) << SCALE_RED ) 497*5e3eaea3SApple OSS Distributions #define SCALE_VAL(x) ( (x) >> SCALE_RED ) 498*5e3eaea3SApple OSS Distributions #define SCALE_MUL(x, y) ( ( (x) * (y) ) >> SCALE_RED ) 499*5e3eaea3SApple OSS Distributions int w_q; /* queue weight (scaled) */ 500*5e3eaea3SApple OSS Distributions int max_th; /* maximum threshold for queue (scaled) */ 501*5e3eaea3SApple OSS Distributions int min_th; /* minimum threshold for queue (scaled) */ 502*5e3eaea3SApple OSS Distributions int max_p; /* maximum value for p_b (scaled) */ 503*5e3eaea3SApple OSS Distributions u_int c_1; /* max_p/(max_th-min_th) (scaled) */ 504*5e3eaea3SApple OSS Distributions u_int c_2; /* max_p*min_th/(max_th-min_th) (scaled) */ 505*5e3eaea3SApple OSS Distributions u_int c_3; /* for GRED, (1-max_p)/max_th (scaled) */ 506*5e3eaea3SApple OSS Distributions u_int c_4; /* for GRED, 1 - 2*max_p (scaled) */ 507*5e3eaea3SApple OSS Distributions user32_addr_t w_q_lookup; /* lookup table for computing (1-w_q)^t */ 508*5e3eaea3SApple OSS Distributions u_int lookup_depth; /* depth of lookup table */ 509*5e3eaea3SApple OSS Distributions int lookup_step; /* granularity inside the lookup table */ 510*5e3eaea3SApple OSS Distributions int lookup_weight; /* equal to (1-w_q)^t / (1-w_q)^(t+1) */ 511*5e3eaea3SApple OSS Distributions int avg_pkt_size; /* medium packet size */ 512*5e3eaea3SApple OSS Distributions int max_pkt_size; /* max packet size */ 513*5e3eaea3SApple OSS Distributions }; 514*5e3eaea3SApple OSS Distributions 515*5e3eaea3SApple OSS Distributions struct dn_pipe_32 { /* a pipe */ 516*5e3eaea3SApple OSS Distributions user32_addr_t next; 517*5e3eaea3SApple OSS Distributions 518*5e3eaea3SApple OSS Distributions int pipe_nr; /* number */ 519*5e3eaea3SApple OSS Distributions int bandwidth; /* really, bytes/tick. */ 520*5e3eaea3SApple OSS Distributions int delay; /* really, ticks */ 521*5e3eaea3SApple OSS Distributions 522*5e3eaea3SApple OSS Distributions user32_addr_t head, tail; /* packets in delay line */ 523*5e3eaea3SApple OSS Distributions 524*5e3eaea3SApple OSS Distributions /* WF2Q+ */ 525*5e3eaea3SApple OSS Distributions struct dn_heap_32 scheduler_heap; /* top extract - key Finish time*/ 526*5e3eaea3SApple OSS Distributions struct dn_heap_32 not_eligible_heap; /* top extract- key Start time */ 527*5e3eaea3SApple OSS Distributions struct dn_heap_32 idle_heap; /* random extract - key Start=Finish time */ 528*5e3eaea3SApple OSS Distributions 529*5e3eaea3SApple OSS Distributions dn_key V; /* virtual time */ 530*5e3eaea3SApple OSS Distributions int sum; /* sum of weights of all active sessions */ 531*5e3eaea3SApple OSS Distributions int numbytes; /* bits I can transmit (more or less). */ 532*5e3eaea3SApple OSS Distributions 533*5e3eaea3SApple OSS Distributions dn_key sched_time; /* time pipe was scheduled in ready_heap */ 534*5e3eaea3SApple OSS Distributions 535*5e3eaea3SApple OSS Distributions /* 536*5e3eaea3SApple OSS Distributions * When the tx clock come from an interface (if_name[0] != '\0'), its name 537*5e3eaea3SApple OSS Distributions * is stored below, whereas the ifp is filled when the rule is configured. 538*5e3eaea3SApple OSS Distributions */ 539*5e3eaea3SApple OSS Distributions char if_name[IFNAMSIZ]; 540*5e3eaea3SApple OSS Distributions user32_addr_t ifp; 541*5e3eaea3SApple OSS Distributions int ready; /* set if ifp != NULL and we got a signal from it */ 542*5e3eaea3SApple OSS Distributions 543*5e3eaea3SApple OSS Distributions struct dn_flow_set_32 fs; /* used with fixed-rate flows */ 544*5e3eaea3SApple OSS Distributions }; 545*5e3eaea3SApple OSS Distributions #pragma pack() 546*5e3eaea3SApple OSS Distributions 547*5e3eaea3SApple OSS Distributions 548*5e3eaea3SApple OSS Distributions struct dn_heap_64 { 549*5e3eaea3SApple OSS Distributions int size; 550*5e3eaea3SApple OSS Distributions int elements; 551*5e3eaea3SApple OSS Distributions int offset; /* XXX if > 0 this is the offset of direct ptr to obj */ 552*5e3eaea3SApple OSS Distributions user64_addr_t p; /* really an array of "size" entries */ 553*5e3eaea3SApple OSS Distributions }; 554*5e3eaea3SApple OSS Distributions 555*5e3eaea3SApple OSS Distributions 556*5e3eaea3SApple OSS Distributions struct dn_flow_queue_64 { 557*5e3eaea3SApple OSS Distributions user64_addr_t next; 558*5e3eaea3SApple OSS Distributions struct ip_flow_id id; 559*5e3eaea3SApple OSS Distributions 560*5e3eaea3SApple OSS Distributions user64_addr_t head, tail; /* queue of packets */ 561*5e3eaea3SApple OSS Distributions u_int len; 562*5e3eaea3SApple OSS Distributions u_int len_bytes; 563*5e3eaea3SApple OSS Distributions u_int32_t numbytes; /* credit for transmission (dynamic queues) */ 564*5e3eaea3SApple OSS Distributions 565*5e3eaea3SApple OSS Distributions u_int64_t tot_pkts; /* statistics counters */ 566*5e3eaea3SApple OSS Distributions u_int64_t tot_bytes; 567*5e3eaea3SApple OSS Distributions u_int32_t drops; 568*5e3eaea3SApple OSS Distributions 569*5e3eaea3SApple OSS Distributions int hash_slot; /* debugging/diagnostic */ 570*5e3eaea3SApple OSS Distributions 571*5e3eaea3SApple OSS Distributions /* RED parameters */ 572*5e3eaea3SApple OSS Distributions int avg; /* average queue length est. (scaled) */ 573*5e3eaea3SApple OSS Distributions int count; /* arrivals since last RED drop */ 574*5e3eaea3SApple OSS Distributions int random; /* random value (scaled) */ 575*5e3eaea3SApple OSS Distributions u_int32_t q_time; /* start of queue idle time */ 576*5e3eaea3SApple OSS Distributions 577*5e3eaea3SApple OSS Distributions /* WF2Q+ support */ 578*5e3eaea3SApple OSS Distributions user64_addr_t fs; /* parent flow set */ 579*5e3eaea3SApple OSS Distributions int heap_pos; /* position (index) of struct in heap */ 580*5e3eaea3SApple OSS Distributions dn_key sched_time; /* current time when queue enters ready_heap */ 581*5e3eaea3SApple OSS Distributions 582*5e3eaea3SApple OSS Distributions dn_key S, F; /* start time, finish time */ 583*5e3eaea3SApple OSS Distributions /* 584*5e3eaea3SApple OSS Distributions * Setting F < S means the timestamp is invalid. We only need 585*5e3eaea3SApple OSS Distributions * to test this when the queue is empty. 586*5e3eaea3SApple OSS Distributions */ 587*5e3eaea3SApple OSS Distributions }; 588*5e3eaea3SApple OSS Distributions 589*5e3eaea3SApple OSS Distributions struct dn_flow_set_64 { 590*5e3eaea3SApple OSS Distributions user64_addr_t next; /* next flow set in all_flow_sets list */ 591*5e3eaea3SApple OSS Distributions 592*5e3eaea3SApple OSS Distributions u_short fs_nr; /* flow_set number */ 593*5e3eaea3SApple OSS Distributions u_short flags_fs; 594*5e3eaea3SApple OSS Distributions #define DN_HAVE_FLOW_MASK 0x0001 595*5e3eaea3SApple OSS Distributions #define DN_IS_RED 0x0002 596*5e3eaea3SApple OSS Distributions #define DN_IS_GENTLE_RED 0x0004 597*5e3eaea3SApple OSS Distributions #define DN_QSIZE_IS_BYTES 0x0008 /* queue size is measured in bytes */ 598*5e3eaea3SApple OSS Distributions #define DN_NOERROR 0x0010 /* do not report ENOBUFS on drops */ 599*5e3eaea3SApple OSS Distributions #define DN_IS_PIPE 0x4000 600*5e3eaea3SApple OSS Distributions #define DN_IS_QUEUE 0x8000 601*5e3eaea3SApple OSS Distributions 602*5e3eaea3SApple OSS Distributions user64_addr_t pipe; /* pointer to parent pipe */ 603*5e3eaea3SApple OSS Distributions u_short parent_nr; /* parent pipe#, 0 if local to a pipe */ 604*5e3eaea3SApple OSS Distributions 605*5e3eaea3SApple OSS Distributions int weight; /* WFQ queue weight */ 606*5e3eaea3SApple OSS Distributions int qsize; /* queue size in slots or bytes */ 607*5e3eaea3SApple OSS Distributions int plr; /* pkt loss rate (2^31-1 means 100%) */ 608*5e3eaea3SApple OSS Distributions 609*5e3eaea3SApple OSS Distributions struct ip_flow_id flow_mask; 610*5e3eaea3SApple OSS Distributions 611*5e3eaea3SApple OSS Distributions /* hash table of queues onto this flow_set */ 612*5e3eaea3SApple OSS Distributions int rq_size; /* number of slots */ 613*5e3eaea3SApple OSS Distributions int rq_elements; /* active elements */ 614*5e3eaea3SApple OSS Distributions user64_addr_t rq; /* array of rq_size entries */ 615*5e3eaea3SApple OSS Distributions 616*5e3eaea3SApple OSS Distributions u_int32_t last_expired; /* do not expire too frequently */ 617*5e3eaea3SApple OSS Distributions int backlogged; /* #active queues for this flowset */ 618*5e3eaea3SApple OSS Distributions 619*5e3eaea3SApple OSS Distributions /* RED parameters */ 620*5e3eaea3SApple OSS Distributions #define SCALE_RED 16 621*5e3eaea3SApple OSS Distributions #define SCALE(x) ( (x) << SCALE_RED ) 622*5e3eaea3SApple OSS Distributions #define SCALE_VAL(x) ( (x) >> SCALE_RED ) 623*5e3eaea3SApple OSS Distributions #define SCALE_MUL(x, y) ( ( (x) * (y) ) >> SCALE_RED ) 624*5e3eaea3SApple OSS Distributions int w_q; /* queue weight (scaled) */ 625*5e3eaea3SApple OSS Distributions int max_th; /* maximum threshold for queue (scaled) */ 626*5e3eaea3SApple OSS Distributions int min_th; /* minimum threshold for queue (scaled) */ 627*5e3eaea3SApple OSS Distributions int max_p; /* maximum value for p_b (scaled) */ 628*5e3eaea3SApple OSS Distributions u_int c_1; /* max_p/(max_th-min_th) (scaled) */ 629*5e3eaea3SApple OSS Distributions u_int c_2; /* max_p*min_th/(max_th-min_th) (scaled) */ 630*5e3eaea3SApple OSS Distributions u_int c_3; /* for GRED, (1-max_p)/max_th (scaled) */ 631*5e3eaea3SApple OSS Distributions u_int c_4; /* for GRED, 1 - 2*max_p (scaled) */ 632*5e3eaea3SApple OSS Distributions user64_addr_t w_q_lookup; /* lookup table for computing (1-w_q)^t */ 633*5e3eaea3SApple OSS Distributions u_int lookup_depth; /* depth of lookup table */ 634*5e3eaea3SApple OSS Distributions int lookup_step; /* granularity inside the lookup table */ 635*5e3eaea3SApple OSS Distributions int lookup_weight; /* equal to (1-w_q)^t / (1-w_q)^(t+1) */ 636*5e3eaea3SApple OSS Distributions int avg_pkt_size; /* medium packet size */ 637*5e3eaea3SApple OSS Distributions int max_pkt_size; /* max packet size */ 638*5e3eaea3SApple OSS Distributions }; 639*5e3eaea3SApple OSS Distributions 640*5e3eaea3SApple OSS Distributions struct dn_pipe_64 { /* a pipe */ 641*5e3eaea3SApple OSS Distributions user64_addr_t next; 642*5e3eaea3SApple OSS Distributions 643*5e3eaea3SApple OSS Distributions int pipe_nr; /* number */ 644*5e3eaea3SApple OSS Distributions int bandwidth; /* really, bytes/tick. */ 645*5e3eaea3SApple OSS Distributions int delay; /* really, ticks */ 646*5e3eaea3SApple OSS Distributions 647*5e3eaea3SApple OSS Distributions user64_addr_t head, tail; /* packets in delay line */ 648*5e3eaea3SApple OSS Distributions 649*5e3eaea3SApple OSS Distributions /* WF2Q+ */ 650*5e3eaea3SApple OSS Distributions struct dn_heap_64 scheduler_heap; /* top extract - key Finish time*/ 651*5e3eaea3SApple OSS Distributions struct dn_heap_64 not_eligible_heap; /* top extract- key Start time */ 652*5e3eaea3SApple OSS Distributions struct dn_heap_64 idle_heap; /* random extract - key Start=Finish time */ 653*5e3eaea3SApple OSS Distributions 654*5e3eaea3SApple OSS Distributions dn_key V; /* virtual time */ 655*5e3eaea3SApple OSS Distributions int sum; /* sum of weights of all active sessions */ 656*5e3eaea3SApple OSS Distributions int numbytes; /* bits I can transmit (more or less). */ 657*5e3eaea3SApple OSS Distributions 658*5e3eaea3SApple OSS Distributions dn_key sched_time; /* time pipe was scheduled in ready_heap */ 659*5e3eaea3SApple OSS Distributions 660*5e3eaea3SApple OSS Distributions /* 661*5e3eaea3SApple OSS Distributions * When the tx clock come from an interface (if_name[0] != '\0'), its name 662*5e3eaea3SApple OSS Distributions * is stored below, whereas the ifp is filled when the rule is configured. 663*5e3eaea3SApple OSS Distributions */ 664*5e3eaea3SApple OSS Distributions char if_name[IFNAMSIZ]; 665*5e3eaea3SApple OSS Distributions user64_addr_t ifp; 666*5e3eaea3SApple OSS Distributions int ready; /* set if ifp != NULL and we got a signal from it */ 667*5e3eaea3SApple OSS Distributions 668*5e3eaea3SApple OSS Distributions struct dn_flow_set_64 fs; /* used with fixed-rate flows */ 669*5e3eaea3SApple OSS Distributions }; 670*5e3eaea3SApple OSS Distributions 671*5e3eaea3SApple OSS Distributions #include <sys/eventhandler.h> 672*5e3eaea3SApple OSS Distributions /* Dummynet event handling declarations */ 673*5e3eaea3SApple OSS Distributions extern struct eventhandler_lists_ctxt dummynet_evhdlr_ctxt; 674*5e3eaea3SApple OSS Distributions extern void dummynet_init(void); 675*5e3eaea3SApple OSS Distributions 676*5e3eaea3SApple OSS Distributions extern void dummynet_register_m_tag(void); 677*5e3eaea3SApple OSS Distributions 678*5e3eaea3SApple OSS Distributions struct dn_pipe_mini_config { 679*5e3eaea3SApple OSS Distributions uint32_t bandwidth; 680*5e3eaea3SApple OSS Distributions uint32_t delay; 681*5e3eaea3SApple OSS Distributions uint32_t plr; 682*5e3eaea3SApple OSS Distributions }; 683*5e3eaea3SApple OSS Distributions 684*5e3eaea3SApple OSS Distributions struct dn_rule_mini_config { 685*5e3eaea3SApple OSS Distributions uint32_t dir; 686*5e3eaea3SApple OSS Distributions uint32_t af; 687*5e3eaea3SApple OSS Distributions uint32_t proto; 688*5e3eaea3SApple OSS Distributions /* 689*5e3eaea3SApple OSS Distributions * XXX PF rules actually define ranges of ports and 690*5e3eaea3SApple OSS Distributions * along with range goes an opcode ((not) equal to, less than 691*5e3eaea3SApple OSS Distributions * greater than, etc. 692*5e3eaea3SApple OSS Distributions * For now the following works assuming there's no port range 693*5e3eaea3SApple OSS Distributions * and the rule is for specific port. 694*5e3eaea3SApple OSS Distributions * Also the operation is assumed as equal to. 695*5e3eaea3SApple OSS Distributions */ 696*5e3eaea3SApple OSS Distributions uint32_t src_port; 697*5e3eaea3SApple OSS Distributions uint32_t dst_port; 698*5e3eaea3SApple OSS Distributions char ifname[IFXNAMSIZ]; 699*5e3eaea3SApple OSS Distributions }; 700*5e3eaea3SApple OSS Distributions 701*5e3eaea3SApple OSS Distributions struct dummynet_event { 702*5e3eaea3SApple OSS Distributions uint32_t dn_event_code; 703*5e3eaea3SApple OSS Distributions union { 704*5e3eaea3SApple OSS Distributions struct dn_pipe_mini_config _dnev_pipe_config; 705*5e3eaea3SApple OSS Distributions struct dn_rule_mini_config _dnev_rule_config; 706*5e3eaea3SApple OSS Distributions } dn_event; 707*5e3eaea3SApple OSS Distributions }; 708*5e3eaea3SApple OSS Distributions 709*5e3eaea3SApple OSS Distributions #define dn_event_pipe_config dn_event._dnev_pipe_config 710*5e3eaea3SApple OSS Distributions #define dn_event_rule_config dn_event._dnev_rule_config 711*5e3eaea3SApple OSS Distributions 712*5e3eaea3SApple OSS Distributions extern void dummynet_event_enqueue_nwk_wq_entry(struct dummynet_event *); 713*5e3eaea3SApple OSS Distributions 714*5e3eaea3SApple OSS Distributions enum { 715*5e3eaea3SApple OSS Distributions DUMMYNET_RULE_CONFIG, 716*5e3eaea3SApple OSS Distributions DUMMYNET_RULE_DELETE, 717*5e3eaea3SApple OSS Distributions DUMMYNET_PIPE_CONFIG, 718*5e3eaea3SApple OSS Distributions DUMMYNET_PIPE_DELETE, 719*5e3eaea3SApple OSS Distributions DUMMYNET_NLC_DISABLED, 720*5e3eaea3SApple OSS Distributions }; 721*5e3eaea3SApple OSS Distributions 722*5e3eaea3SApple OSS Distributions enum { DN_INOUT, DN_IN, DN_OUT }; 723*5e3eaea3SApple OSS Distributions /* 724*5e3eaea3SApple OSS Distributions * The signature for the callback is: 725*5e3eaea3SApple OSS Distributions * eventhandler_entry_arg __unused 726*5e3eaea3SApple OSS Distributions * dummynet_event pointer to dummynet event object 727*5e3eaea3SApple OSS Distributions */ 728*5e3eaea3SApple OSS Distributions typedef void (*dummynet_event_fn) (struct eventhandler_entry_arg, struct dummynet_event *); 729*5e3eaea3SApple OSS Distributions EVENTHANDLER_DECLARE(dummynet_event, dummynet_event_fn); 730*5e3eaea3SApple OSS Distributions #endif /* BSD_KERNEL_PRIVATE */ 731*5e3eaea3SApple OSS Distributions #endif /* PRIVATE */ 732*5e3eaea3SApple OSS Distributions #endif /* _IP_DUMMYNET_H */ 733