2 * Copyright (c) 2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/cdefs.h>
31 #include <sys/param.h>
32 #include <sys/malloc.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/errno.h>
37 #include <sys/mcache.h>
38 #include <sys/sysctl.h>
41 #include <net/if_var.h>
42 #include <net/if_dl.h>
43 #include <net/if_types.h>
44 #include <net/net_osdep.h>
45 #include <net/pktsched/pktsched.h>
46 #include <net/pktsched/pktsched_tcq.h>
47 #include <net/pktsched/pktsched_qfq.h>
48 #include <net/pktsched/pktsched_fq_codel.h>
50 #include <net/pktsched/pktsched_priq.h>
51 #endif /* PKTSCHED_PRIQ */
53 #include <net/pktsched/pktsched_fairq.h>
54 #endif /* PKTSCHED_FAIRQ */
56 #include <net/pktsched/pktsched_cbq.h>
57 #endif /* PKTSCHED_CBQ */
59 #include <net/pktsched/pktsched_hfsc.h>
60 #endif /* PKTSCHED_HFSC */
62 #include <pexpert/pexpert.h>
64 u_int32_t machclk_freq
= 0;
65 u_int64_t machclk_per_sec
= 0;
66 u_int32_t pktsched_verbose
; /* more noise if greater than 1 */
68 static void init_machclk(void);
70 SYSCTL_NODE(_net
, OID_AUTO
, pktsched
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, "pktsched");
72 SYSCTL_UINT(_net_pktsched
, OID_AUTO
, verbose
, CTLFLAG_RW
|CTLFLAG_LOCKED
,
73 &pktsched_verbose
, 0, "Packet scheduler verbosity level");
79 if (machclk_freq
== 0) {
80 panic("%s: no CPU clock available!\n", __func__
);
88 #endif /* PKTSCHED_PRIQ */
91 #endif /* PKTSCHED_FAIRQ */
94 #endif /* PKTSCHED_CBQ */
97 #endif /* PKTSCHED_HFSC */
104 * Initialize machclk_freq using the timerbase frequency
105 * value from device specific info.
107 machclk_freq
= gPEClockFrequencyInfo
.timebase_frequency_hz
;
109 clock_interval_to_absolutetime_interval(1, NSEC_PER_SEC
,
114 pktsched_abs_to_nsecs(u_int64_t abstime
)
118 absolutetime_to_nanoseconds(abstime
, &nsecs
);
123 pktsched_nsecs_to_abstime(u_int64_t nsecs
)
127 nanoseconds_to_absolutetime(nsecs
, &abstime
);
132 pktsched_setup(struct ifclassq
*ifq
, u_int32_t scheduler
, u_int32_t sflags
)
135 u_int32_t qflags
= sflags
;
138 IFCQ_LOCK_ASSERT_HELD(ifq
);
140 VERIFY(machclk_freq
!= 0);
142 /* Nothing to do unless the scheduler type changes */
143 if (ifq
->ifcq_type
== scheduler
)
146 qflags
&= (PKTSCHEDF_QALG_RED
| PKTSCHEDF_QALG_RIO
|
147 PKTSCHEDF_QALG_BLUE
| PKTSCHEDF_QALG_SFB
);
149 /* These are mutually exclusive */
151 qflags
!= PKTSCHEDF_QALG_RED
&& qflags
!= PKTSCHEDF_QALG_RIO
&&
152 qflags
!= PKTSCHEDF_QALG_BLUE
&& qflags
!= PKTSCHEDF_QALG_SFB
) {
153 panic("%s: RED|RIO|BLUE|SFB mutually exclusive\n", __func__
);
158 * Remember the flags that need to be restored upon success, as
159 * they may be cleared when we tear down existing scheduler.
161 rflags
= (ifq
->ifcq_flags
& IFCQF_ENABLED
);
163 if (ifq
->ifcq_type
!= PKTSCHEDT_NONE
) {
164 (void) pktsched_teardown(ifq
);
166 /* Teardown should have succeeded */
167 VERIFY(ifq
->ifcq_type
== PKTSCHEDT_NONE
);
168 VERIFY(ifq
->ifcq_disc
== NULL
);
169 VERIFY(ifq
->ifcq_enqueue
== NULL
);
170 VERIFY(ifq
->ifcq_dequeue
== NULL
);
171 VERIFY(ifq
->ifcq_dequeue_sc
== NULL
);
172 VERIFY(ifq
->ifcq_request
== NULL
);
178 error
= priq_setup_ifclassq(ifq
, sflags
);
180 #endif /* PKTSCHED_PRIQ */
183 error
= tcq_setup_ifclassq(ifq
, sflags
);
187 error
= qfq_setup_ifclassq(ifq
, sflags
);
189 case PKTSCHEDT_FQ_CODEL
:
190 error
= fq_if_setup_ifclassq(ifq
, sflags
);
198 ifq
->ifcq_flags
|= rflags
;
204 pktsched_teardown(struct ifclassq
*ifq
)
208 IFCQ_LOCK_ASSERT_HELD(ifq
);
210 if_qflush(ifq
->ifcq_ifp
, 1);
211 VERIFY(IFCQ_IS_EMPTY(ifq
));
213 ifq
->ifcq_flags
&= ~IFCQF_ENABLED
;
215 switch (ifq
->ifcq_type
) {
221 error
= priq_teardown_ifclassq(ifq
);
223 #endif /* PKTSCHED_PRIQ */
226 error
= tcq_teardown_ifclassq(ifq
);
230 error
= qfq_teardown_ifclassq(ifq
);
233 case PKTSCHEDT_FQ_CODEL
:
234 error
= fq_if_teardown_ifclassq(ifq
);
244 pktsched_getqstats(struct ifclassq
*ifq
, u_int32_t qid
,
245 struct if_ifclassq_stats
*ifqs
)
249 IFCQ_LOCK_ASSERT_HELD(ifq
);
251 switch (ifq
->ifcq_type
) {
254 error
= priq_getqstats_ifclassq(ifq
, qid
, ifqs
);
256 #endif /* PKTSCHED_PRIQ */
259 error
= tcq_getqstats_ifclassq(ifq
, qid
, ifqs
);
263 error
= qfq_getqstats_ifclassq(ifq
, qid
, ifqs
);
266 case PKTSCHEDT_FQ_CODEL
:
267 error
= fq_if_getqstats_ifclassq(ifq
, qid
, ifqs
);