]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/pktsched/pktsched.c
xnu-3247.1.106.tar.gz
[apple/xnu.git] / bsd / net / pktsched / pktsched.c
CommitLineData
316670eb
A
1/*
2 * Copyright (c) 2011 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#include <sys/cdefs.h>
30
31#include <sys/param.h>
32#include <sys/malloc.h>
33#include <sys/mbuf.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>
39
40#include <net/if.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#if PKTSCHED_PRIQ
49#include <net/pktsched/pktsched_priq.h>
50#endif /* PKTSCHED_PRIQ */
51#if PKTSCHED_FAIRQ
52#include <net/pktsched/pktsched_fairq.h>
53#endif /* PKTSCHED_FAIRQ */
54#if PKTSCHED_CBQ
55#include <net/pktsched/pktsched_cbq.h>
56#endif /* PKTSCHED_CBQ */
57#if PKTSCHED_HFSC
58#include <net/pktsched/pktsched_hfsc.h>
59#endif /* PKTSCHED_HFSC */
60
61#include <pexpert/pexpert.h>
62
63u_int32_t machclk_freq = 0;
64u_int64_t machclk_per_sec = 0;
65u_int32_t pktsched_verbose; /* more noise if greater than 1 */
66
67static void init_machclk(void);
68
69SYSCTL_NODE(_net, OID_AUTO, pktsched, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "pktsched");
70
71SYSCTL_UINT(_net_pktsched, OID_AUTO, verbose, CTLFLAG_RW|CTLFLAG_LOCKED,
72 &pktsched_verbose, 0, "Packet scheduler verbosity level");
73
74void
75pktsched_init(void)
76{
77 init_machclk();
78 if (machclk_freq == 0) {
79 panic("%s: no CPU clock available!\n", __func__);
80 /* NOTREACHED */
81 }
82
83 tcq_init();
84 qfq_init();
85#if PKTSCHED_PRIQ
86 priq_init();
87#endif /* PKTSCHED_PRIQ */
88#if PKTSCHED_FAIRQ
89 fairq_init();
90#endif /* PKTSCHED_FAIRQ */
91#if PKTSCHED_CBQ
92 cbq_init();
93#endif /* PKTSCHED_CBQ */
94#if PKTSCHED_HFSC
95 hfsc_init();
96#endif /* PKTSCHED_HFSC */
97}
98
99static void
100init_machclk(void)
101{
102 /*
103 * Initialize machclk_freq using the timerbase frequency
104 * value from device specific info.
105 */
106 machclk_freq = gPEClockFrequencyInfo.timebase_frequency_hz;
107
108 clock_interval_to_absolutetime_interval(1, NSEC_PER_SEC,
109 &machclk_per_sec);
110}
111
112u_int64_t
113pktsched_abs_to_nsecs(u_int64_t abstime)
114{
115 u_int64_t nsecs;
116
117 absolutetime_to_nanoseconds(abstime, &nsecs);
118 return (nsecs);
119}
120
121u_int64_t
122pktsched_nsecs_to_abstime(u_int64_t nsecs)
123{
124 u_int64_t abstime;
125
126 nanoseconds_to_absolutetime(nsecs, &abstime);
127 return (abstime);
128}
129
130int
131pktsched_setup(struct ifclassq *ifq, u_int32_t scheduler, u_int32_t sflags)
132{
133 int error = 0;
134 u_int32_t qflags = sflags;
135 u_int32_t rflags;
136
137 IFCQ_LOCK_ASSERT_HELD(ifq);
138
139 VERIFY(machclk_freq != 0);
140
141 /* Nothing to do unless the scheduler type changes */
142 if (ifq->ifcq_type == scheduler)
143 return (0);
144
145 qflags &= (PKTSCHEDF_QALG_RED | PKTSCHEDF_QALG_RIO |
146 PKTSCHEDF_QALG_BLUE | PKTSCHEDF_QALG_SFB);
147
148 /* These are mutually exclusive */
149 if (qflags != 0 &&
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__);
153 /* NOTREACHED */
154 }
155
156 /*
157 * Remember the flags that need to be restored upon success, as
158 * they may be cleared when we tear down existing scheduler.
159 */
160 rflags = (ifq->ifcq_flags & IFCQF_ENABLED);
161
162 if (ifq->ifcq_type != PKTSCHEDT_NONE) {
163 (void) pktsched_teardown(ifq);
164
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);
172 }
173
174 switch (scheduler) {
175#if PKTSCHED_PRIQ
176 case PKTSCHEDT_PRIQ:
177 error = priq_setup_ifclassq(ifq, sflags);
178 break;
179#endif /* PKTSCHED_PRIQ */
180
181 case PKTSCHEDT_TCQ:
182 error = tcq_setup_ifclassq(ifq, sflags);
183 break;
184
185 case PKTSCHEDT_QFQ:
186 error = qfq_setup_ifclassq(ifq, sflags);
187 break;
188
189 default:
190 error = ENXIO;
191 break;
192 }
193
194 if (error == 0)
195 ifq->ifcq_flags |= rflags;
196
197 return (error);
198}
199
200int
201pktsched_teardown(struct ifclassq *ifq)
202{
203 int error = 0;
204
205 IFCQ_LOCK_ASSERT_HELD(ifq);
206
207 if_qflush(ifq->ifcq_ifp, 1);
208 VERIFY(IFCQ_IS_EMPTY(ifq));
209
210 ifq->ifcq_flags &= ~IFCQF_ENABLED;
211
212 switch (ifq->ifcq_type) {
213 case PKTSCHEDT_NONE:
214 break;
215
216#if PKTSCHED_PRIQ
217 case PKTSCHEDT_PRIQ:
218 error = priq_teardown_ifclassq(ifq);
219 break;
220#endif /* PKTSCHED_PRIQ */
221
222 case PKTSCHEDT_TCQ:
223 error = tcq_teardown_ifclassq(ifq);
224 break;
225
226 case PKTSCHEDT_QFQ:
227 error = qfq_teardown_ifclassq(ifq);
228 break;
229
230 default:
231 error = ENXIO;
232 break;
233 }
316670eb
A
234 return (error);
235}
236
237int
238pktsched_getqstats(struct ifclassq *ifq, u_int32_t qid,
239 struct if_ifclassq_stats *ifqs)
240{
241 int error;
242
243 IFCQ_LOCK_ASSERT_HELD(ifq);
244
245 switch (ifq->ifcq_type) {
246#if PKTSCHED_PRIQ
247 case PKTSCHEDT_PRIQ:
248 error = priq_getqstats_ifclassq(ifq, qid, ifqs);
249 break;
250#endif /* PKTSCHED_PRIQ */
251
252 case PKTSCHEDT_TCQ:
253 error = tcq_getqstats_ifclassq(ifq, qid, ifqs);
254 break;
255
256 case PKTSCHEDT_QFQ:
257 error = qfq_getqstats_ifclassq(ifq, qid, ifqs);
258 break;
259
260 default:
261 error = ENXIO;
262 break;
263 }
264
265 return (error);
266}