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>
49 #include <net/pktsched/pktsched_priq.h>
50 #endif /* PKTSCHED_PRIQ */
52 #include <net/pktsched/pktsched_fairq.h>
53 #endif /* PKTSCHED_FAIRQ */
55 #include <net/pktsched/pktsched_cbq.h>
56 #endif /* PKTSCHED_CBQ */
58 #include <net/pktsched/pktsched_hfsc.h>
59 #endif /* PKTSCHED_HFSC */
61 #include <pexpert/pexpert.h>
63 u_int32_t machclk_freq
= 0;
64 u_int64_t machclk_per_sec
= 0;
65 u_int32_t pktsched_verbose
; /* more noise if greater than 1 */
67 static void init_machclk(void);
69 SYSCTL_NODE(_net
, OID_AUTO
, pktsched
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, "pktsched");
71 SYSCTL_UINT(_net_pktsched
, OID_AUTO
, verbose
, CTLFLAG_RW
|CTLFLAG_LOCKED
,
72 &pktsched_verbose
, 0, "Packet scheduler verbosity level");
78 if (machclk_freq
== 0) {
79 panic("%s: no CPU clock available!\n", __func__
);
87 #endif /* PKTSCHED_PRIQ */
90 #endif /* PKTSCHED_FAIRQ */
93 #endif /* PKTSCHED_CBQ */
96 #endif /* PKTSCHED_HFSC */
103 * Initialize machclk_freq using the timerbase frequency
104 * value from device specific info.
106 machclk_freq
= gPEClockFrequencyInfo
.timebase_frequency_hz
;
108 clock_interval_to_absolutetime_interval(1, NSEC_PER_SEC
,
113 pktsched_abs_to_nsecs(u_int64_t abstime
)
117 absolutetime_to_nanoseconds(abstime
, &nsecs
);
122 pktsched_nsecs_to_abstime(u_int64_t nsecs
)
126 nanoseconds_to_absolutetime(nsecs
, &abstime
);
131 pktsched_setup(struct ifclassq
*ifq
, u_int32_t scheduler
, u_int32_t sflags
)
134 u_int32_t qflags
= sflags
;
137 IFCQ_LOCK_ASSERT_HELD(ifq
);
139 VERIFY(machclk_freq
!= 0);
141 /* Nothing to do unless the scheduler type changes */
142 if (ifq
->ifcq_type
== scheduler
)
145 qflags
&= (PKTSCHEDF_QALG_RED
| PKTSCHEDF_QALG_RIO
|
146 PKTSCHEDF_QALG_BLUE
| PKTSCHEDF_QALG_SFB
);
148 /* These are mutually exclusive */
150 qflags
!= PKTSCHEDF_QALG_RED
&& qflags
!= PKTSCHEDF_QALG_RIO
&&
151 qflags
!= PKTSCHEDF_QALG_BLUE
&& qflags
!= PKTSCHEDF_QALG_SFB
) {
152 panic("%s: RED|RIO|BLUE|SFB mutually exclusive\n", __func__
);
157 * Remember the flags that need to be restored upon success, as
158 * they may be cleared when we tear down existing scheduler.
160 rflags
= (ifq
->ifcq_flags
& IFCQF_ENABLED
);
162 if (ifq
->ifcq_type
!= PKTSCHEDT_NONE
) {
163 (void) pktsched_teardown(ifq
);
165 /* Teardown should have succeeded */
166 VERIFY(ifq
->ifcq_type
== PKTSCHEDT_NONE
);
167 VERIFY(ifq
->ifcq_disc
== NULL
);
168 VERIFY(ifq
->ifcq_enqueue
== NULL
);
169 VERIFY(ifq
->ifcq_dequeue
== NULL
);
170 VERIFY(ifq
->ifcq_dequeue_sc
== NULL
);
171 VERIFY(ifq
->ifcq_request
== NULL
);
177 error
= priq_setup_ifclassq(ifq
, sflags
);
179 #endif /* PKTSCHED_PRIQ */
182 error
= tcq_setup_ifclassq(ifq
, sflags
);
186 error
= qfq_setup_ifclassq(ifq
, sflags
);
195 ifq
->ifcq_flags
|= rflags
;
201 pktsched_teardown(struct ifclassq
*ifq
)
205 IFCQ_LOCK_ASSERT_HELD(ifq
);
207 if_qflush(ifq
->ifcq_ifp
, 1);
208 VERIFY(IFCQ_IS_EMPTY(ifq
));
210 ifq
->ifcq_flags
&= ~IFCQF_ENABLED
;
212 switch (ifq
->ifcq_type
) {
218 error
= priq_teardown_ifclassq(ifq
);
220 #endif /* PKTSCHED_PRIQ */
223 error
= tcq_teardown_ifclassq(ifq
);
227 error
= qfq_teardown_ifclassq(ifq
);
239 pktsched_getqstats(struct ifclassq
*ifq
, u_int32_t qid
,
240 struct if_ifclassq_stats
*ifqs
)
244 IFCQ_LOCK_ASSERT_HELD(ifq
);
246 switch (ifq
->ifcq_type
) {
249 error
= priq_getqstats_ifclassq(ifq
, qid
, ifqs
);
251 #endif /* PKTSCHED_PRIQ */
254 error
= tcq_getqstats_ifclassq(ifq
, qid
, ifqs
);
258 error
= qfq_getqstats_ifclassq(ifq
, qid
, ifqs
);