X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/ff6e181ae92fc6f1e89841290f461d1f2f9badd9..fe8ab488e9161c46dd9885d58fc52996dc0249ff:/bsd/netinet/ip_dummynet.h diff --git a/bsd/netinet/ip_dummynet.h b/bsd/netinet/ip_dummynet.h index b2aa46c50..dde647d0b 100644 --- a/bsd/netinet/ip_dummynet.h +++ b/bsd/netinet/ip_dummynet.h @@ -1,14 +1,19 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2013 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER @@ -18,7 +23,7 @@ * Please see the License for the specific language governing rights and * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1998-2002 Luigi Rizzo, Universita` di Pisa @@ -51,9 +56,20 @@ #ifndef _IP_DUMMYNET_H #define _IP_DUMMYNET_H + #include #ifdef PRIVATE + +#include + +/* Apply ipv6 mask on ipv6 addr */ +#define APPLY_MASK(addr,mask) \ + (addr)->__u6_addr.__u6_addr32[0] &= (mask)->__u6_addr.__u6_addr32[0]; \ + (addr)->__u6_addr.__u6_addr32[1] &= (mask)->__u6_addr.__u6_addr32[1]; \ + (addr)->__u6_addr.__u6_addr32[2] &= (mask)->__u6_addr.__u6_addr32[2]; \ + (addr)->__u6_addr.__u6_addr32[3] &= (mask)->__u6_addr.__u6_addr32[3]; + /* * Definition of dummynet data structures. In the structures, I decided * not to use the macros in in the hope of making the code @@ -140,18 +156,49 @@ struct dn_heap { * processing requirements. */ #ifdef KERNEL +#include /* for ip_out_args */ +#include /* for ip6_out_args */ +#include /* for ip6_out_args */ + struct dn_pkt_tag { - struct ip_fw *rule; /* matching rule */ - int dn_dir; /* action when packet comes out. */ + struct ip_fw *dn_ipfw_rule; /* matching IPFW rule */ + void *dn_pf_rule; /* matching PF rule */ + int dn_dir; /* action when packet comes out. */ #define DN_TO_IP_OUT 1 #define DN_TO_IP_IN 2 #define DN_TO_BDG_FWD 3 - - dn_key output_time; /* when the pkt is due for delivery */ - struct ifnet *ifp; /* interface, for ip_output */ - struct sockaddr_in *dn_dst ; - struct route ro; /* route, for ip_output. MUST COPY */ - int flags ; /* flags, for ip_output (IPv6 ?) */ +#define DN_TO_IP6_IN 4 +#define DN_TO_IP6_OUT 5 + dn_key dn_output_time; /* when the pkt is due for delivery */ + struct ifnet *dn_ifp; /* interface, for ip[6]_output */ + union { + struct sockaddr_in _dn_dst; + struct sockaddr_in6 _dn_dst6 ; + } dn_dst_; +#define dn_dst dn_dst_._dn_dst +#define dn_dst6 dn_dst_._dn_dst6 + union { + struct route _dn_ro; /* route, for ip_output. MUST COPY */ + struct route_in6 _dn_ro6; /* route, for ip6_output. MUST COPY */ + } dn_ro_; +#define dn_ro dn_ro_._dn_ro +#define dn_ro6 dn_ro_._dn_ro6 + struct route_in6 dn_ro6_pmtu; /* for ip6_output */ + struct ifnet *dn_origifp; /* for ip6_output */ + u_int32_t dn_mtu; /* for ip6_output */ + int dn_alwaysfrag; /* for ip6_output */ + u_int32_t dn_unfragpartlen; /* for ip6_output */ + struct ip6_exthdrs dn_exthdrs; /* for ip6_output */ + int dn_flags ; /* flags, for ip[6]_output */ + int dn_client; +#define DN_CLIENT_IPFW 1 +#define DN_CLIENT_PF 2 + union { + struct ip_out_args _dn_ipoa; /* output args, for ip_output. MUST COPY */ + struct ip6_out_args _dn_ip6oa; /* output args, for ip_output. MUST COPY */ + } dn_ipoa_; +#define dn_ipoa dn_ipoa_._dn_ipoa +#define dn_ip6oa dn_ipoa_._dn_ip6oa }; #else struct dn_pkt; @@ -227,12 +274,12 @@ flow using a number of heaps defined into the pipe itself. */ struct dn_flow_queue { struct dn_flow_queue *next ; - struct ipfw_flow_id id ; + struct ip_flow_id id ; struct mbuf *head, *tail ; /* queue of packets */ u_int len ; u_int len_bytes ; - u_long numbytes ; /* credit for transmission (dynamic queues) */ + u_int32_t numbytes ; /* credit for transmission (dynamic queues) */ u_int64_t tot_pkts ; /* statistics counters */ u_int64_t tot_bytes ; @@ -271,7 +318,7 @@ struct dn_flow_queue { * latter case, the structure is located inside the struct dn_pipe). */ struct dn_flow_set { - struct dn_flow_set *next; /* next flow set in all_flow_sets list */ + SLIST_ENTRY(dn_flow_set) next; /* linked list in a hash slot */ u_short fs_nr ; /* flow_set number */ u_short flags_fs; @@ -290,7 +337,7 @@ struct dn_flow_set { int qsize ; /* queue size in slots or bytes */ int plr ; /* pkt loss rate (2^31-1 means 100%) */ - struct ipfw_flow_id flow_mask ; + struct ip_flow_id flow_mask ; /* hash table of queues onto this flow_set */ int rq_size ; /* number of slots */ @@ -321,6 +368,8 @@ struct dn_flow_set { int max_pkt_size ; /* max packet size */ } ; +SLIST_HEAD(dn_flow_set_head, dn_flow_set); + /* * Pipe descriptor. Contains global parameters, delay-line queue, * and the flow_set used for fixed-rate queues. @@ -336,7 +385,7 @@ struct dn_flow_set { * */ struct dn_pipe { /* a pipe */ - struct dn_pipe *next ; + SLIST_ENTRY(dn_pipe) next; /* linked list in a hash slot */ int pipe_nr ; /* number */ int bandwidth; /* really, bytes/tick. */ @@ -366,19 +415,271 @@ struct dn_pipe { /* a pipe */ struct dn_flow_set fs ; /* used with fixed-rate flows */ }; -#ifdef KERNEL +SLIST_HEAD(dn_pipe_head, dn_pipe); + +#ifdef BSD_KERNEL_PRIVATE void ip_dn_init(void); /* called from raw_ip.c:load_ipfw() */ typedef int ip_dn_ctl_t(struct sockopt *); /* raw_ip.c */ -typedef void ip_dn_ruledel_t(void *); /* ip_fw.c */ typedef int ip_dn_io_t(struct mbuf *m, int pipe_nr, int dir, - struct ip_fw_args *fwa); + struct ip_fw_args *fwa, int ); extern ip_dn_ctl_t *ip_dn_ctl_ptr; -extern ip_dn_ruledel_t *ip_dn_ruledel_ptr; extern ip_dn_io_t *ip_dn_io_ptr; +void dn_ipfw_rule_delete(void *); #define DUMMYNET_LOADED (ip_dn_io_ptr != NULL) +#pragma pack(4) + +struct dn_heap_32 { + int size ; + int elements ; + int offset ; /* XXX if > 0 this is the offset of direct ptr to obj */ + user32_addr_t p ; /* really an array of "size" entries */ +} ; + +struct dn_flow_queue_32 { + user32_addr_t next ; + struct ip_flow_id id ; + + user32_addr_t head, tail ; /* queue of packets */ + u_int len ; + u_int len_bytes ; + u_int32_t numbytes ; /* credit for transmission (dynamic queues) */ + + u_int64_t tot_pkts ; /* statistics counters */ + u_int64_t tot_bytes ; + u_int32_t drops ; + + int hash_slot ; /* debugging/diagnostic */ + + /* RED parameters */ + int avg ; /* average queue length est. (scaled) */ + int count ; /* arrivals since last RED drop */ + int random ; /* random value (scaled) */ + u_int32_t q_time ; /* start of queue idle time */ + + /* WF2Q+ support */ + user32_addr_t fs ; /* parent flow set */ + int heap_pos ; /* position (index) of struct in heap */ + dn_key sched_time ; /* current time when queue enters ready_heap */ + + dn_key S,F ; /* start time, finish time */ + /* + * Setting F < S means the timestamp is invalid. We only need + * to test this when the queue is empty. + */ +} ; + +struct dn_flow_set_32 { + user32_addr_t next; /* next flow set in all_flow_sets list */ + + u_short fs_nr ; /* flow_set number */ + u_short flags_fs; +#define DN_HAVE_FLOW_MASK 0x0001 +#define DN_IS_RED 0x0002 +#define DN_IS_GENTLE_RED 0x0004 +#define DN_QSIZE_IS_BYTES 0x0008 /* queue size is measured in bytes */ +#define DN_NOERROR 0x0010 /* do not report ENOBUFS on drops */ +#define DN_IS_PIPE 0x4000 +#define DN_IS_QUEUE 0x8000 + + user32_addr_t pipe ; /* pointer to parent pipe */ + u_short parent_nr ; /* parent pipe#, 0 if local to a pipe */ + + int weight ; /* WFQ queue weight */ + int qsize ; /* queue size in slots or bytes */ + int plr ; /* pkt loss rate (2^31-1 means 100%) */ + + struct ip_flow_id flow_mask ; + + /* hash table of queues onto this flow_set */ + int rq_size ; /* number of slots */ + int rq_elements ; /* active elements */ + user32_addr_t rq; /* array of rq_size entries */ + + u_int32_t last_expired ; /* do not expire too frequently */ + int backlogged ; /* #active queues for this flowset */ + + /* RED parameters */ +#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) */ + u_int c_1 ; /* max_p/(max_th-min_th) (scaled) */ + u_int c_2 ; /* max_p*min_th/(max_th-min_th) (scaled) */ + u_int c_3 ; /* for GRED, (1-max_p)/max_th (scaled) */ + u_int c_4 ; /* for GRED, 1 - 2*max_p (scaled) */ + user32_addr_t w_q_lookup ; /* lookup table for computing (1-w_q)^t */ + u_int lookup_depth ; /* depth of lookup table */ + int lookup_step ; /* granularity inside the lookup table */ + int lookup_weight ; /* equal to (1-w_q)^t / (1-w_q)^(t+1) */ + int avg_pkt_size ; /* medium packet size */ + int max_pkt_size ; /* max packet size */ +} ; + +struct dn_pipe_32 { /* a pipe */ + user32_addr_t next ; + + int pipe_nr ; /* number */ + int bandwidth; /* really, bytes/tick. */ + int delay ; /* really, ticks */ + + user32_addr_t head, tail ; /* packets in delay line */ + + /* WF2Q+ */ + struct dn_heap_32 scheduler_heap ; /* top extract - key Finish time*/ + struct dn_heap_32 not_eligible_heap; /* top extract- key Start time */ + struct dn_heap_32 idle_heap ; /* random extract - key Start=Finish time */ + + dn_key V ; /* virtual time */ + int sum; /* sum of weights of all active sessions */ + int numbytes; /* bits I can transmit (more or less). */ + + dn_key sched_time ; /* time pipe was scheduled in ready_heap */ + + /* + * When the tx clock come from an interface (if_name[0] != '\0'), its name + * is stored below, whereas the ifp is filled when the rule is configured. + */ + char if_name[IFNAMSIZ]; + user32_addr_t ifp ; + int ready ; /* set if ifp != NULL and we got a signal from it */ + + struct dn_flow_set_32 fs ; /* used with fixed-rate flows */ +}; +#pragma pack() + + +struct dn_heap_64 { + int size ; + int elements ; + int offset ; /* XXX if > 0 this is the offset of direct ptr to obj */ + user64_addr_t p ; /* really an array of "size" entries */ +} ; + + +struct dn_flow_queue_64 { + user64_addr_t next ; + struct ip_flow_id id ; + + user64_addr_t head, tail ; /* queue of packets */ + u_int len ; + u_int len_bytes ; + u_int32_t numbytes ; /* credit for transmission (dynamic queues) */ + + u_int64_t tot_pkts ; /* statistics counters */ + u_int64_t tot_bytes ; + u_int32_t drops ; + + int hash_slot ; /* debugging/diagnostic */ + + /* RED parameters */ + int avg ; /* average queue length est. (scaled) */ + int count ; /* arrivals since last RED drop */ + int random ; /* random value (scaled) */ + u_int32_t q_time ; /* start of queue idle time */ + + /* WF2Q+ support */ + user64_addr_t fs ; /* parent flow set */ + int heap_pos ; /* position (index) of struct in heap */ + dn_key sched_time ; /* current time when queue enters ready_heap */ + + dn_key S,F ; /* start time, finish time */ + /* + * Setting F < S means the timestamp is invalid. We only need + * to test this when the queue is empty. + */ +} ; + +struct dn_flow_set_64 { + user64_addr_t next; /* next flow set in all_flow_sets list */ + + u_short fs_nr ; /* flow_set number */ + u_short flags_fs; +#define DN_HAVE_FLOW_MASK 0x0001 +#define DN_IS_RED 0x0002 +#define DN_IS_GENTLE_RED 0x0004 +#define DN_QSIZE_IS_BYTES 0x0008 /* queue size is measured in bytes */ +#define DN_NOERROR 0x0010 /* do not report ENOBUFS on drops */ +#define DN_IS_PIPE 0x4000 +#define DN_IS_QUEUE 0x8000 + + user64_addr_t pipe ; /* pointer to parent pipe */ + u_short parent_nr ; /* parent pipe#, 0 if local to a pipe */ + + int weight ; /* WFQ queue weight */ + int qsize ; /* queue size in slots or bytes */ + int plr ; /* pkt loss rate (2^31-1 means 100%) */ + + struct ip_flow_id flow_mask ; + + /* hash table of queues onto this flow_set */ + int rq_size ; /* number of slots */ + int rq_elements ; /* active elements */ + user64_addr_t rq; /* array of rq_size entries */ + + u_int32_t last_expired ; /* do not expire too frequently */ + int backlogged ; /* #active queues for this flowset */ + + /* RED parameters */ +#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) */ + u_int c_1 ; /* max_p/(max_th-min_th) (scaled) */ + u_int c_2 ; /* max_p*min_th/(max_th-min_th) (scaled) */ + u_int c_3 ; /* for GRED, (1-max_p)/max_th (scaled) */ + u_int c_4 ; /* for GRED, 1 - 2*max_p (scaled) */ + user64_addr_t w_q_lookup ; /* lookup table for computing (1-w_q)^t */ + u_int lookup_depth ; /* depth of lookup table */ + int lookup_step ; /* granularity inside the lookup table */ + int lookup_weight ; /* equal to (1-w_q)^t / (1-w_q)^(t+1) */ + int avg_pkt_size ; /* medium packet size */ + int max_pkt_size ; /* max packet size */ +} ; + +struct dn_pipe_64 { /* a pipe */ + user64_addr_t next ; + + int pipe_nr ; /* number */ + int bandwidth; /* really, bytes/tick. */ + int delay ; /* really, ticks */ + + user64_addr_t head, tail ; /* packets in delay line */ + + /* WF2Q+ */ + struct dn_heap_64 scheduler_heap ; /* top extract - key Finish time*/ + struct dn_heap_64 not_eligible_heap; /* top extract- key Start time */ + struct dn_heap_64 idle_heap ; /* random extract - key Start=Finish time */ + + dn_key V ; /* virtual time */ + int sum; /* sum of weights of all active sessions */ + int numbytes; /* bits I can transmit (more or less). */ + + dn_key sched_time ; /* time pipe was scheduled in ready_heap */ + + /* + * When the tx clock come from an interface (if_name[0] != '\0'), its name + * is stored below, whereas the ifp is filled when the rule is configured. + */ + char if_name[IFNAMSIZ]; + user64_addr_t ifp ; + int ready ; /* set if ifp != NULL and we got a signal from it */ + + struct dn_flow_set_64 fs ; /* used with fixed-rate flows */ +}; + + + /* * Return the IPFW rule associated with the dummynet tag; if any. * Make sure that the dummynet tag is not reused by lower layers. @@ -390,11 +691,10 @@ ip_dn_claim_rule(struct mbuf *m) KERNEL_TAG_TYPE_DUMMYNET, NULL); if (mtag != NULL) { mtag->m_tag_type = KERNEL_TAG_TYPE_NONE; - return (((struct dn_pkt_tag *)(mtag+1))->rule); + return (((struct dn_pkt_tag *)(mtag+1))->dn_ipfw_rule); } else return (NULL); } -#endif /* KERNEL */ - +#endif /* BSD_KERNEL_PRIVATE */ #endif /* PRIVATE */ #endif /* _IP_DUMMYNET_H */