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