altq_jobs.c revision 1.1.8.2 1 1.1.8.2 yamt /* $NetBSD: altq_jobs.c,v 1.1.8.2 2006/12/10 07:15:44 yamt Exp $ */
2 1.1.8.1 yamt /* $KAME: altq_jobs.c,v 1.11 2005/04/13 03:44:25 suz Exp $ */
3 1.1.8.1 yamt /*
4 1.1.8.1 yamt * Copyright (c) 2001, the Rector and Board of Visitors of the
5 1.1.8.1 yamt * University of Virginia.
6 1.1.8.1 yamt * All rights reserved.
7 1.1.8.1 yamt *
8 1.1.8.1 yamt * Redistribution and use in source and binary forms,
9 1.1.8.1 yamt * with or without modification, are permitted provided
10 1.1.8.1 yamt * that the following conditions are met:
11 1.1.8.1 yamt *
12 1.1.8.1 yamt * Redistributions of source code must retain the above
13 1.1.8.1 yamt * copyright notice, this list of conditions and the following
14 1.1.8.1 yamt * disclaimer.
15 1.1.8.1 yamt *
16 1.1.8.1 yamt * Redistributions in binary form must reproduce the above
17 1.1.8.1 yamt * copyright notice, this list of conditions and the following
18 1.1.8.1 yamt * disclaimer in the documentation and/or other materials provided
19 1.1.8.1 yamt * with the distribution.
20 1.1.8.1 yamt *
21 1.1.8.1 yamt * Neither the name of the University of Virginia nor the names
22 1.1.8.1 yamt * of its contributors may be used to endorse or promote products
23 1.1.8.1 yamt * derived from this software without specific prior written
24 1.1.8.1 yamt * permission.
25 1.1.8.1 yamt *
26 1.1.8.1 yamt * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
27 1.1.8.1 yamt * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
28 1.1.8.1 yamt * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29 1.1.8.1 yamt * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 1.1.8.1 yamt * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
31 1.1.8.1 yamt * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
32 1.1.8.1 yamt * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 1.1.8.1 yamt * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 1.1.8.1 yamt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35 1.1.8.1 yamt * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 1.1.8.1 yamt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
37 1.1.8.1 yamt * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
38 1.1.8.1 yamt * THE POSSIBILITY OF SUCH DAMAGE.
39 1.1.8.1 yamt */
40 1.1.8.1 yamt /*
41 1.1.8.1 yamt * JoBS - altq prototype implementation
42 1.1.8.1 yamt *
43 1.1.8.1 yamt * Author: Nicolas Christin <nicolas (at) cs.virginia.edu>
44 1.1.8.1 yamt *
45 1.1.8.1 yamt * JoBS algorithms originally devised and proposed by
46 1.1.8.1 yamt * Nicolas Christin and Jorg Liebeherr.
47 1.1.8.1 yamt * Grateful acknowledgments to Tarek Abdelzaher for his help and
48 1.1.8.1 yamt * comments, and to Kenjiro Cho for some helpful advice.
49 1.1.8.1 yamt * Contributed by the Multimedia Networks Group at the University
50 1.1.8.1 yamt * of Virginia.
51 1.1.8.1 yamt *
52 1.1.8.1 yamt * Papers and additional info can be found at
53 1.1.8.1 yamt * http://qosbox.cs.virginia.edu
54 1.1.8.1 yamt *
55 1.1.8.1 yamt */
56 1.1.8.1 yamt
57 1.1.8.1 yamt /*
58 1.1.8.1 yamt * JoBS queue
59 1.1.8.1 yamt */
60 1.1.8.1 yamt
61 1.1.8.1 yamt #include <sys/cdefs.h>
62 1.1.8.2 yamt __KERNEL_RCSID(0, "$NetBSD: altq_jobs.c,v 1.1.8.2 2006/12/10 07:15:44 yamt Exp $");
63 1.1.8.1 yamt
64 1.1.8.1 yamt #ifdef _KERNEL_OPT
65 1.1.8.1 yamt #include "opt_altq.h"
66 1.1.8.1 yamt #include "opt_inet.h"
67 1.1.8.1 yamt #endif
68 1.1.8.1 yamt
69 1.1.8.1 yamt #ifdef ALTQ_JOBS /* jobs is enabled by ALTQ_JOBS option in opt_altq.h */
70 1.1.8.1 yamt
71 1.1.8.1 yamt #include <sys/param.h>
72 1.1.8.1 yamt #include <sys/malloc.h>
73 1.1.8.1 yamt #include <sys/mbuf.h>
74 1.1.8.1 yamt #include <sys/socket.h>
75 1.1.8.1 yamt #include <sys/sockio.h>
76 1.1.8.1 yamt #include <sys/systm.h>
77 1.1.8.1 yamt #include <sys/proc.h>
78 1.1.8.1 yamt #include <sys/errno.h>
79 1.1.8.1 yamt #include <sys/kernel.h>
80 1.1.8.1 yamt #include <sys/queue.h>
81 1.1.8.1 yamt #include <sys/kauth.h>
82 1.1.8.1 yamt
83 1.1.8.1 yamt #ifdef __FreeBSD__
84 1.1.8.1 yamt #include <sys/limits.h>
85 1.1.8.1 yamt #endif
86 1.1.8.1 yamt
87 1.1.8.1 yamt #include <net/if.h>
88 1.1.8.1 yamt #include <net/if_types.h>
89 1.1.8.1 yamt
90 1.1.8.1 yamt #include <altq/altq.h>
91 1.1.8.1 yamt #include <altq/altq_conf.h>
92 1.1.8.1 yamt #include <altq/altq_jobs.h>
93 1.1.8.1 yamt
94 1.1.8.1 yamt #ifdef ALTQ3_COMPAT
95 1.1.8.1 yamt /*
96 1.1.8.1 yamt * function prototypes
97 1.1.8.1 yamt */
98 1.1.8.1 yamt static struct jobs_if *jobs_attach(struct ifaltq *, u_int, u_int, u_int);
99 1.1.8.1 yamt static int jobs_detach(struct jobs_if *);
100 1.1.8.1 yamt static int jobs_clear_interface(struct jobs_if *);
101 1.1.8.1 yamt static int jobs_request(struct ifaltq *, int, void *);
102 1.1.8.1 yamt static void jobs_purge(struct jobs_if *);
103 1.1.8.1 yamt static struct jobs_class *jobs_class_create(struct jobs_if *,
104 1.1.8.1 yamt int, int64_t, int64_t, int64_t, int64_t, int64_t, int);
105 1.1.8.1 yamt static int jobs_class_destroy(struct jobs_class *);
106 1.1.8.1 yamt static int jobs_enqueue(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
107 1.1.8.1 yamt static struct mbuf *jobs_dequeue(struct ifaltq *, int);
108 1.1.8.1 yamt
109 1.1.8.1 yamt static int jobs_addq(struct jobs_class *, struct mbuf *, struct jobs_if*);
110 1.1.8.1 yamt static struct mbuf *jobs_getq(struct jobs_class *);
111 1.1.8.1 yamt static struct mbuf *jobs_pollq(struct jobs_class *);
112 1.1.8.1 yamt static void jobs_purgeq(struct jobs_class *);
113 1.1.8.1 yamt
114 1.1.8.1 yamt static int jobscmd_if_attach(struct jobs_attach *);
115 1.1.8.1 yamt static int jobscmd_if_detach(struct jobs_interface *);
116 1.1.8.1 yamt static int jobscmd_add_class(struct jobs_add_class *);
117 1.1.8.1 yamt static int jobscmd_delete_class(struct jobs_delete_class *);
118 1.1.8.1 yamt static int jobscmd_modify_class(struct jobs_modify_class *);
119 1.1.8.1 yamt static int jobscmd_add_filter(struct jobs_add_filter *);
120 1.1.8.1 yamt static int jobscmd_delete_filter(struct jobs_delete_filter *);
121 1.1.8.1 yamt static int jobscmd_class_stats(struct jobs_class_stats *);
122 1.1.8.1 yamt static void get_class_stats(struct class_stats *, struct jobs_class *);
123 1.1.8.1 yamt static struct jobs_class *clh_to_clp(struct jobs_if *, u_long);
124 1.1.8.1 yamt static u_long clp_to_clh(struct jobs_class *);
125 1.1.8.1 yamt
126 1.1.8.1 yamt static TSLIST *tslist_alloc(void);
127 1.1.8.1 yamt static void tslist_destroy(struct jobs_class *);
128 1.1.8.1 yamt static int tslist_enqueue(struct jobs_class *, u_int64_t);
129 1.1.8.1 yamt static void tslist_dequeue(struct jobs_class *);
130 1.1.8.1 yamt static void tslist_drop(struct jobs_class *);
131 1.1.8.1 yamt
132 1.1.8.1 yamt static int enforce_wc(struct jobs_if *);
133 1.1.8.1 yamt static int64_t* adjust_rates_rdc(struct jobs_if *);
134 1.1.8.1 yamt static int64_t* assign_rate_drops_adc(struct jobs_if *);
135 1.1.8.1 yamt static int64_t* update_error(struct jobs_if *);
136 1.1.8.1 yamt static int min_rates_adc(struct jobs_if *);
137 1.1.8.1 yamt static int64_t proj_delay(struct jobs_if *, int);
138 1.1.8.1 yamt static int pick_dropped_rlc(struct jobs_if *);
139 1.1.8.1 yamt
140 1.1.8.1 yamt altqdev_decl(jobs);
141 1.1.8.1 yamt
142 1.1.8.1 yamt /* jif_list keeps all jobs_if's allocated. */
143 1.1.8.1 yamt static struct jobs_if *jif_list = NULL;
144 1.1.8.1 yamt
145 1.1.8.1 yamt typedef unsigned long long ull;
146 1.1.8.1 yamt
147 1.1.8.1 yamt /* setup functions */
148 1.1.8.1 yamt
149 1.1.8.1 yamt static struct jobs_if *
150 1.1.8.1 yamt jobs_attach(struct ifaltq *ifq, u_int bandwidth, u_int qlimit, u_int separate)
151 1.1.8.1 yamt {
152 1.1.8.1 yamt struct jobs_if *jif;
153 1.1.8.1 yamt
154 1.1.8.1 yamt jif = malloc(sizeof(struct jobs_if), M_DEVBUF, M_WAITOK|M_ZERO);
155 1.1.8.1 yamt if (jif == NULL)
156 1.1.8.1 yamt return (NULL);
157 1.1.8.1 yamt
158 1.1.8.1 yamt jif->jif_bandwidth = bandwidth;
159 1.1.8.1 yamt jif->jif_qlimit = qlimit;
160 1.1.8.1 yamt jif->jif_separate = separate;
161 1.1.8.1 yamt #ifdef ALTQ_DEBUG
162 1.1.8.1 yamt printf("JoBS bandwidth = %d bps\n", (int)bandwidth);
163 1.1.8.1 yamt printf("JoBS buffer size = %d pkts [%s]\n",
164 1.1.8.1 yamt (int)qlimit, separate?"separate buffers":"shared buffer");
165 1.1.8.1 yamt #endif
166 1.1.8.1 yamt jif->jif_maxpri = -1;
167 1.1.8.1 yamt jif->jif_ifq = ifq;
168 1.1.8.1 yamt
169 1.1.8.1 yamt jif->wc_cycles_enqueue = 0;
170 1.1.8.1 yamt jif->avg_cycles_enqueue = 0;
171 1.1.8.1 yamt jif->avg_cycles2_enqueue = 0;
172 1.1.8.1 yamt jif->bc_cycles_enqueue = INFINITY;
173 1.1.8.1 yamt jif->wc_cycles_dequeue = 0;
174 1.1.8.1 yamt jif->avg_cycles_dequeue = 0;
175 1.1.8.1 yamt jif->avg_cycles2_dequeue = 0;
176 1.1.8.1 yamt jif->bc_cycles_dequeue = INFINITY;
177 1.1.8.1 yamt jif->total_enqueued = 0;
178 1.1.8.1 yamt jif->total_dequeued = 0;
179 1.1.8.1 yamt
180 1.1.8.1 yamt /* add this state to the jobs list */
181 1.1.8.1 yamt jif->jif_next = jif_list;
182 1.1.8.1 yamt jif_list = jif;
183 1.1.8.1 yamt
184 1.1.8.1 yamt return (jif);
185 1.1.8.1 yamt }
186 1.1.8.1 yamt
187 1.1.8.1 yamt static int
188 1.1.8.1 yamt jobs_detach(struct jobs_if *jif)
189 1.1.8.1 yamt {
190 1.1.8.1 yamt (void)jobs_clear_interface(jif);
191 1.1.8.1 yamt
192 1.1.8.1 yamt /* remove this interface from the jif list */
193 1.1.8.1 yamt if (jif_list == jif)
194 1.1.8.1 yamt jif_list = jif->jif_next;
195 1.1.8.1 yamt else {
196 1.1.8.1 yamt struct jobs_if *p;
197 1.1.8.1 yamt
198 1.1.8.1 yamt for (p = jif_list; p != NULL; p = p->jif_next)
199 1.1.8.1 yamt if (p->jif_next == jif) {
200 1.1.8.1 yamt p->jif_next = jif->jif_next;
201 1.1.8.1 yamt break;
202 1.1.8.1 yamt }
203 1.1.8.1 yamt ASSERT(p != NULL);
204 1.1.8.1 yamt }
205 1.1.8.1 yamt free(jif, M_DEVBUF);
206 1.1.8.1 yamt return (0);
207 1.1.8.1 yamt }
208 1.1.8.1 yamt
209 1.1.8.1 yamt /*
210 1.1.8.1 yamt * bring the interface back to the initial state by discarding
211 1.1.8.1 yamt * all the filters and classes.
212 1.1.8.1 yamt */
213 1.1.8.1 yamt static int
214 1.1.8.1 yamt jobs_clear_interface(struct jobs_if *jif)
215 1.1.8.1 yamt {
216 1.1.8.1 yamt struct jobs_class *cl;
217 1.1.8.1 yamt int pri;
218 1.1.8.1 yamt
219 1.1.8.1 yamt /* free the filters for this interface */
220 1.1.8.1 yamt acc_discard_filters(&jif->jif_classifier, NULL, 1);
221 1.1.8.1 yamt
222 1.1.8.1 yamt /* clear out the classes */
223 1.1.8.1 yamt for (pri = 0; pri <= jif->jif_maxpri; pri++)
224 1.1.8.1 yamt if ((cl = jif->jif_classes[pri]) != NULL)
225 1.1.8.1 yamt jobs_class_destroy(cl);
226 1.1.8.1 yamt
227 1.1.8.1 yamt return (0);
228 1.1.8.1 yamt }
229 1.1.8.1 yamt
230 1.1.8.1 yamt static int
231 1.1.8.2 yamt jobs_request(struct ifaltq *ifq, int req, void *arg)
232 1.1.8.1 yamt {
233 1.1.8.1 yamt struct jobs_if *jif = (struct jobs_if *)ifq->altq_disc;
234 1.1.8.1 yamt
235 1.1.8.1 yamt switch (req) {
236 1.1.8.1 yamt case ALTRQ_PURGE:
237 1.1.8.1 yamt jobs_purge(jif);
238 1.1.8.1 yamt break;
239 1.1.8.1 yamt }
240 1.1.8.1 yamt return (0);
241 1.1.8.1 yamt }
242 1.1.8.1 yamt
243 1.1.8.1 yamt /* discard all the queued packets on the interface */
244 1.1.8.1 yamt static void
245 1.1.8.1 yamt jobs_purge(struct jobs_if *jif)
246 1.1.8.1 yamt {
247 1.1.8.1 yamt struct jobs_class *cl;
248 1.1.8.1 yamt int pri;
249 1.1.8.1 yamt
250 1.1.8.1 yamt for (pri = 0; pri <= jif->jif_maxpri; pri++) {
251 1.1.8.1 yamt if ((cl = jif->jif_classes[pri]) != NULL && !qempty(cl->cl_q))
252 1.1.8.1 yamt jobs_purgeq(cl);
253 1.1.8.1 yamt }
254 1.1.8.1 yamt if (ALTQ_IS_ENABLED(jif->jif_ifq))
255 1.1.8.1 yamt jif->jif_ifq->ifq_len = 0;
256 1.1.8.1 yamt }
257 1.1.8.1 yamt
258 1.1.8.1 yamt static struct jobs_class *
259 1.1.8.1 yamt jobs_class_create(struct jobs_if *jif, int pri, int64_t adc, int64_t rdc,
260 1.1.8.1 yamt int64_t alc, int64_t rlc, int64_t arc, int flags)
261 1.1.8.1 yamt {
262 1.1.8.1 yamt struct jobs_class *cl, *scan1, *scan2;
263 1.1.8.1 yamt int s;
264 1.1.8.1 yamt int class_exists1, class_exists2;
265 1.1.8.1 yamt int i, j;
266 1.1.8.1 yamt int64_t tmp[JOBS_MAXPRI];
267 1.1.8.1 yamt u_int64_t now;
268 1.1.8.1 yamt
269 1.1.8.1 yamt if ((cl = jif->jif_classes[pri]) != NULL) {
270 1.1.8.1 yamt /* modify the class instead of creating a new one */
271 1.1.8.1 yamt s = splnet();
272 1.1.8.1 yamt if (!qempty(cl->cl_q))
273 1.1.8.1 yamt jobs_purgeq(cl);
274 1.1.8.1 yamt splx(s);
275 1.1.8.1 yamt } else {
276 1.1.8.1 yamt cl = malloc(sizeof(struct jobs_class), M_DEVBUF,
277 1.1.8.1 yamt M_WAITOK|M_ZERO);
278 1.1.8.1 yamt if (cl == NULL)
279 1.1.8.1 yamt return (NULL);
280 1.1.8.1 yamt
281 1.1.8.1 yamt cl->cl_q = malloc(sizeof(class_queue_t), M_DEVBUF,
282 1.1.8.1 yamt M_WAITOK|M_ZERO);
283 1.1.8.1 yamt if (cl->cl_q == NULL)
284 1.1.8.1 yamt goto err_ret;
285 1.1.8.1 yamt
286 1.1.8.1 yamt cl->arv_tm = tslist_alloc();
287 1.1.8.1 yamt if (cl->arv_tm == NULL)
288 1.1.8.1 yamt goto err_ret;
289 1.1.8.1 yamt }
290 1.1.8.1 yamt
291 1.1.8.1 yamt jif->jif_classes[pri] = cl;
292 1.1.8.1 yamt
293 1.1.8.1 yamt if (flags & JOCF_DEFAULTCLASS)
294 1.1.8.1 yamt jif->jif_default = cl;
295 1.1.8.1 yamt
296 1.1.8.1 yamt qtype(cl->cl_q) = Q_DROPTAIL;
297 1.1.8.1 yamt qlen(cl->cl_q) = 0;
298 1.1.8.1 yamt cl->service_rate = 0;
299 1.1.8.1 yamt cl->min_rate_adc = 0;
300 1.1.8.1 yamt cl->current_loss = 0;
301 1.1.8.1 yamt cl->cl_period = 0;
302 1.1.8.1 yamt PKTCNTR_RESET(&cl->cl_arrival);
303 1.1.8.1 yamt PKTCNTR_RESET(&cl->cl_rin);
304 1.1.8.1 yamt PKTCNTR_RESET(&cl->cl_rout);
305 1.1.8.1 yamt PKTCNTR_RESET(&cl->cl_rout_th);
306 1.1.8.1 yamt PKTCNTR_RESET(&cl->cl_dropcnt);
307 1.1.8.1 yamt PKTCNTR_RESET(&cl->st_arrival);
308 1.1.8.1 yamt PKTCNTR_RESET(&cl->st_rin);
309 1.1.8.1 yamt PKTCNTR_RESET(&cl->st_rout);
310 1.1.8.1 yamt PKTCNTR_RESET(&cl->st_dropcnt);
311 1.1.8.1 yamt cl->st_service_rate = 0;
312 1.1.8.1 yamt cl->cl_lastdel = 0;
313 1.1.8.1 yamt cl->cl_avgdel = 0;
314 1.1.8.1 yamt cl->adc_violations = 0;
315 1.1.8.1 yamt
316 1.1.8.1 yamt if (adc == -1) {
317 1.1.8.1 yamt cl->concerned_adc = 0;
318 1.1.8.1 yamt adc = INFINITY;
319 1.1.8.1 yamt } else
320 1.1.8.1 yamt cl->concerned_adc = 1;
321 1.1.8.1 yamt
322 1.1.8.1 yamt if (alc == -1) {
323 1.1.8.1 yamt cl->concerned_alc = 0;
324 1.1.8.1 yamt alc = INFINITY;
325 1.1.8.1 yamt } else
326 1.1.8.1 yamt cl->concerned_alc = 1;
327 1.1.8.1 yamt
328 1.1.8.1 yamt if (rdc == -1) {
329 1.1.8.1 yamt rdc = 0;
330 1.1.8.1 yamt cl->concerned_rdc = 0;
331 1.1.8.1 yamt } else
332 1.1.8.1 yamt cl->concerned_rdc = 1;
333 1.1.8.1 yamt
334 1.1.8.1 yamt if (rlc == -1) {
335 1.1.8.1 yamt rlc = 0;
336 1.1.8.1 yamt cl->concerned_rlc = 0;
337 1.1.8.1 yamt } else
338 1.1.8.1 yamt cl->concerned_rlc = 1;
339 1.1.8.1 yamt
340 1.1.8.1 yamt if (arc == -1) {
341 1.1.8.1 yamt arc = 0;
342 1.1.8.1 yamt cl->concerned_arc = 0;
343 1.1.8.1 yamt } else
344 1.1.8.1 yamt cl->concerned_arc = 1;
345 1.1.8.1 yamt
346 1.1.8.1 yamt cl->cl_rdc=rdc;
347 1.1.8.1 yamt
348 1.1.8.1 yamt if (cl->concerned_adc) {
349 1.1.8.1 yamt /* adc is given in us, convert it to clock ticks */
350 1.1.8.1 yamt cl->cl_adc = (u_int64_t)(adc*machclk_freq/GRANULARITY);
351 1.1.8.1 yamt } else
352 1.1.8.1 yamt cl->cl_adc = adc;
353 1.1.8.1 yamt
354 1.1.8.1 yamt if (cl->concerned_arc) {
355 1.1.8.1 yamt /* arc is given in bps, convert it to internal unit */
356 1.1.8.1 yamt cl->cl_arc = (u_int64_t)(bps_to_internal(arc));
357 1.1.8.1 yamt } else
358 1.1.8.1 yamt cl->cl_arc = arc;
359 1.1.8.1 yamt
360 1.1.8.1 yamt cl->cl_rlc=rlc;
361 1.1.8.1 yamt cl->cl_alc=alc;
362 1.1.8.1 yamt cl->delay_prod_others = 0;
363 1.1.8.1 yamt cl->loss_prod_others = 0;
364 1.1.8.1 yamt cl->cl_flags = flags;
365 1.1.8.1 yamt cl->cl_pri = pri;
366 1.1.8.1 yamt if (pri > jif->jif_maxpri)
367 1.1.8.1 yamt jif->jif_maxpri = pri;
368 1.1.8.1 yamt cl->cl_jif = jif;
369 1.1.8.1 yamt cl->cl_handle = (u_long)cl; /* just a pointer to this class */
370 1.1.8.1 yamt
371 1.1.8.1 yamt /*
372 1.1.8.1 yamt * update delay_prod_others and loss_prod_others
373 1.1.8.1 yamt * in all classes if needed
374 1.1.8.1 yamt */
375 1.1.8.1 yamt
376 1.1.8.1 yamt if (cl->concerned_rdc) {
377 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
378 1.1.8.1 yamt scan1 = jif->jif_classes[i];
379 1.1.8.1 yamt class_exists1 = (scan1 != NULL);
380 1.1.8.1 yamt if (class_exists1) {
381 1.1.8.1 yamt tmp[i] = 1;
382 1.1.8.1 yamt for (j = 0; j <= i-1; j++) {
383 1.1.8.1 yamt scan2 = jif->jif_classes[j];
384 1.1.8.1 yamt class_exists2 = (scan2 != NULL);
385 1.1.8.1 yamt if (class_exists2
386 1.1.8.1 yamt && scan2->concerned_rdc)
387 1.1.8.1 yamt tmp[i] *= scan2->cl_rdc;
388 1.1.8.1 yamt }
389 1.1.8.1 yamt } else
390 1.1.8.1 yamt tmp[i] = 0;
391 1.1.8.1 yamt }
392 1.1.8.1 yamt
393 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
394 1.1.8.1 yamt scan1 = jif->jif_classes[i];
395 1.1.8.1 yamt class_exists1 = (scan1 != NULL);
396 1.1.8.1 yamt if (class_exists1) {
397 1.1.8.1 yamt scan1->delay_prod_others = 1;
398 1.1.8.1 yamt for (j = 0; j <= jif->jif_maxpri; j++) {
399 1.1.8.1 yamt scan2 = jif->jif_classes[j];
400 1.1.8.1 yamt class_exists2 = (scan2 != NULL);
401 1.1.8.1 yamt if (class_exists2 && j != i
402 1.1.8.1 yamt && scan2->concerned_rdc)
403 1.1.8.1 yamt scan1->delay_prod_others *= tmp[j];
404 1.1.8.1 yamt }
405 1.1.8.1 yamt }
406 1.1.8.1 yamt }
407 1.1.8.1 yamt }
408 1.1.8.1 yamt
409 1.1.8.1 yamt if (cl->concerned_rlc) {
410 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
411 1.1.8.1 yamt scan1 = jif->jif_classes[i];
412 1.1.8.1 yamt class_exists1 = (scan1 != NULL);
413 1.1.8.1 yamt if (class_exists1) {
414 1.1.8.1 yamt tmp[i] = 1;
415 1.1.8.1 yamt for (j = 0; j <= i-1; j++) {
416 1.1.8.1 yamt scan2 = jif->jif_classes[j];
417 1.1.8.1 yamt class_exists2 = (scan2 != NULL);
418 1.1.8.1 yamt if (class_exists2
419 1.1.8.1 yamt && scan2->concerned_rlc)
420 1.1.8.1 yamt tmp[i] *= scan2->cl_rlc;
421 1.1.8.1 yamt }
422 1.1.8.1 yamt } else
423 1.1.8.1 yamt tmp[i] = 0;
424 1.1.8.1 yamt }
425 1.1.8.1 yamt
426 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
427 1.1.8.1 yamt scan1 = jif->jif_classes[i];
428 1.1.8.1 yamt class_exists1 = (scan1 != NULL);
429 1.1.8.1 yamt if (class_exists1) {
430 1.1.8.1 yamt scan1->loss_prod_others = 1;
431 1.1.8.1 yamt for (j = 0; j <= jif->jif_maxpri; j++) {
432 1.1.8.1 yamt scan2 = jif->jif_classes[j];
433 1.1.8.1 yamt class_exists2 = (scan2 != NULL);
434 1.1.8.1 yamt if (class_exists2 && j != i
435 1.1.8.1 yamt && scan2->concerned_rlc)
436 1.1.8.1 yamt scan1->loss_prod_others *= tmp[j];
437 1.1.8.1 yamt }
438 1.1.8.1 yamt }
439 1.1.8.1 yamt }
440 1.1.8.1 yamt }
441 1.1.8.1 yamt
442 1.1.8.1 yamt now = read_machclk();
443 1.1.8.1 yamt cl->idletime = now;
444 1.1.8.1 yamt return (cl);
445 1.1.8.1 yamt
446 1.1.8.1 yamt err_ret:
447 1.1.8.1 yamt if (cl->cl_q != NULL)
448 1.1.8.1 yamt free(cl->cl_q, M_DEVBUF);
449 1.1.8.1 yamt if (cl->arv_tm != NULL)
450 1.1.8.1 yamt free(cl->arv_tm, M_DEVBUF);
451 1.1.8.1 yamt
452 1.1.8.1 yamt free(cl, M_DEVBUF);
453 1.1.8.1 yamt return (NULL);
454 1.1.8.1 yamt }
455 1.1.8.1 yamt
456 1.1.8.1 yamt static int
457 1.1.8.1 yamt jobs_class_destroy(struct jobs_class *cl)
458 1.1.8.1 yamt {
459 1.1.8.1 yamt struct jobs_if *jif;
460 1.1.8.1 yamt int s, pri;
461 1.1.8.1 yamt
462 1.1.8.1 yamt s = splnet();
463 1.1.8.1 yamt
464 1.1.8.1 yamt /* delete filters referencing to this class */
465 1.1.8.1 yamt acc_discard_filters(&cl->cl_jif->jif_classifier, cl, 0);
466 1.1.8.1 yamt
467 1.1.8.1 yamt if (!qempty(cl->cl_q))
468 1.1.8.1 yamt jobs_purgeq(cl);
469 1.1.8.1 yamt
470 1.1.8.1 yamt jif = cl->cl_jif;
471 1.1.8.1 yamt jif->jif_classes[cl->cl_pri] = NULL;
472 1.1.8.1 yamt if (jif->jif_maxpri == cl->cl_pri) {
473 1.1.8.1 yamt for (pri = cl->cl_pri; pri >= 0; pri--)
474 1.1.8.1 yamt if (jif->jif_classes[pri] != NULL) {
475 1.1.8.1 yamt jif->jif_maxpri = pri;
476 1.1.8.1 yamt break;
477 1.1.8.1 yamt }
478 1.1.8.1 yamt if (pri < 0)
479 1.1.8.1 yamt jif->jif_maxpri = -1;
480 1.1.8.1 yamt }
481 1.1.8.1 yamt splx(s);
482 1.1.8.1 yamt
483 1.1.8.1 yamt tslist_destroy(cl);
484 1.1.8.1 yamt free(cl->cl_q, M_DEVBUF);
485 1.1.8.1 yamt free(cl, M_DEVBUF);
486 1.1.8.1 yamt return (0);
487 1.1.8.1 yamt }
488 1.1.8.1 yamt
489 1.1.8.1 yamt /*
490 1.1.8.1 yamt * jobs_enqueue is an enqueue function to be registered to
491 1.1.8.1 yamt * (*altq_enqueue) in struct ifaltq.
492 1.1.8.1 yamt */
493 1.1.8.1 yamt static int
494 1.1.8.1 yamt jobs_enqueue(struct ifaltq *ifq, struct mbuf *m, struct altq_pktattr *pktattr)
495 1.1.8.1 yamt {
496 1.1.8.1 yamt struct jobs_if *jif = (struct jobs_if *)ifq->altq_disc;
497 1.1.8.1 yamt struct jobs_class *cl, *scan;
498 1.1.8.1 yamt int len;
499 1.1.8.1 yamt int return_flag;
500 1.1.8.1 yamt int pri;
501 1.1.8.1 yamt u_int64_t now;
502 1.1.8.1 yamt u_int64_t old_arv;
503 1.1.8.1 yamt int64_t* delta_rate;
504 1.1.8.1 yamt u_int64_t tstamp1, tstamp2, cycles; /* used for benchmarking only */
505 1.1.8.1 yamt
506 1.1.8.1 yamt jif->total_enqueued++;
507 1.1.8.1 yamt now = read_machclk();
508 1.1.8.1 yamt tstamp1 = now;
509 1.1.8.1 yamt
510 1.1.8.1 yamt return_flag = 0;
511 1.1.8.1 yamt
512 1.1.8.1 yamt /* proceed with packet enqueuing */
513 1.1.8.1 yamt
514 1.1.8.1 yamt if (IFQ_IS_EMPTY(ifq)) {
515 1.1.8.1 yamt for (pri=0; pri <= jif->jif_maxpri; pri++) {
516 1.1.8.1 yamt scan = jif->jif_classes[pri];
517 1.1.8.1 yamt if (scan != NULL) {
518 1.1.8.1 yamt /*
519 1.1.8.1 yamt * reset all quantities, except:
520 1.1.8.1 yamt * average delay, number of violations
521 1.1.8.1 yamt */
522 1.1.8.1 yamt PKTCNTR_RESET(&scan->cl_rin);
523 1.1.8.1 yamt PKTCNTR_RESET(&scan->cl_rout);
524 1.1.8.1 yamt PKTCNTR_RESET(&scan->cl_rout_th);
525 1.1.8.1 yamt PKTCNTR_RESET(&scan->cl_arrival);
526 1.1.8.1 yamt PKTCNTR_RESET(&scan->cl_dropcnt);
527 1.1.8.1 yamt scan->cl_lastdel = 0;
528 1.1.8.1 yamt scan->current_loss = 0;
529 1.1.8.1 yamt scan->service_rate = 0;
530 1.1.8.1 yamt scan->idletime = now;
531 1.1.8.1 yamt scan->cl_last_rate_update = now;
532 1.1.8.1 yamt }
533 1.1.8.1 yamt }
534 1.1.8.1 yamt }
535 1.1.8.1 yamt
536 1.1.8.1 yamt /* grab class set by classifier */
537 1.1.8.1 yamt if (pktattr == NULL || (cl = pktattr->pattr_class) == NULL)
538 1.1.8.1 yamt cl = jif->jif_default;
539 1.1.8.1 yamt
540 1.1.8.1 yamt len = m_pktlen(m);
541 1.1.8.1 yamt old_arv = cl->cl_arrival.bytes;
542 1.1.8.1 yamt PKTCNTR_ADD(&cl->cl_arrival, (int)len);
543 1.1.8.1 yamt PKTCNTR_ADD(&cl->cl_rin, (int)len);
544 1.1.8.1 yamt PKTCNTR_ADD(&cl->st_arrival, (int)len);
545 1.1.8.1 yamt PKTCNTR_ADD(&cl->st_rin, (int)len);
546 1.1.8.1 yamt
547 1.1.8.1 yamt if (cl->cl_arrival.bytes < old_arv) {
548 1.1.8.1 yamt /* deals w/ overflow */
549 1.1.8.1 yamt for (pri=0; pri <= jif->jif_maxpri; pri++) {
550 1.1.8.1 yamt scan = jif->jif_classes[pri];
551 1.1.8.1 yamt if (scan != NULL) {
552 1.1.8.1 yamt /*
553 1.1.8.1 yamt * reset all quantities, except:
554 1.1.8.1 yamt * average delay, number of violations
555 1.1.8.1 yamt */
556 1.1.8.1 yamt PKTCNTR_RESET(&scan->cl_rin);
557 1.1.8.1 yamt PKTCNTR_RESET(&scan->cl_rout);
558 1.1.8.1 yamt PKTCNTR_RESET(&scan->cl_rout_th);
559 1.1.8.1 yamt PKTCNTR_RESET(&scan->cl_arrival);
560 1.1.8.1 yamt PKTCNTR_RESET(&scan->cl_dropcnt);
561 1.1.8.1 yamt scan->current_loss = 0;
562 1.1.8.1 yamt scan->service_rate = 0;
563 1.1.8.1 yamt scan->idletime = now;
564 1.1.8.1 yamt scan->cl_last_rate_update = now;
565 1.1.8.1 yamt }
566 1.1.8.1 yamt }
567 1.1.8.1 yamt PKTCNTR_ADD(&cl->cl_arrival, (int)len);
568 1.1.8.1 yamt PKTCNTR_ADD(&cl->cl_rin, (int)len);
569 1.1.8.1 yamt }
570 1.1.8.1 yamt
571 1.1.8.1 yamt if (cl->cl_arrival.bytes > cl->cl_rin.bytes)
572 1.1.8.1 yamt cl->current_loss =
573 1.1.8.1 yamt ((cl->cl_arrival.bytes - cl->cl_rin.bytes) << SCALE_LOSS)
574 1.1.8.1 yamt / cl->cl_arrival.bytes;
575 1.1.8.1 yamt else
576 1.1.8.1 yamt cl->current_loss = 0;
577 1.1.8.1 yamt
578 1.1.8.1 yamt /* for MDRR: update theoretical value of the output curve */
579 1.1.8.1 yamt
580 1.1.8.1 yamt for (pri=0; pri <= jif->jif_maxpri; pri++) {
581 1.1.8.1 yamt scan = jif->jif_classes[pri];
582 1.1.8.1 yamt if (scan != NULL) {
583 1.1.8.1 yamt if (scan->cl_last_rate_update == scan->idletime
584 1.1.8.1 yamt || scan->cl_last_rate_update == 0)
585 1.1.8.1 yamt scan->cl_last_rate_update = now; /* initial case */
586 1.1.8.1 yamt else
587 1.1.8.1 yamt scan->cl_rout_th.bytes +=
588 1.1.8.1 yamt delay_diff(now, scan->cl_last_rate_update)
589 1.1.8.1 yamt * scan->service_rate;
590 1.1.8.1 yamt
591 1.1.8.1 yamt /*
592 1.1.8.1 yamt * we don't really care about packets here
593 1.1.8.1 yamt * WARNING: rout_th is SCALED
594 1.1.8.1 yamt * (b/c of the service rate)
595 1.1.8.1 yamt * for precision, as opposed to rout.
596 1.1.8.1 yamt */
597 1.1.8.1 yamt
598 1.1.8.1 yamt scan->cl_last_rate_update = now;
599 1.1.8.1 yamt }
600 1.1.8.1 yamt }
601 1.1.8.1 yamt
602 1.1.8.1 yamt if (jobs_addq(cl, m, jif) != 0)
603 1.1.8.1 yamt return_flag = ENOBUFS; /* signals there's a buffer overflow */
604 1.1.8.1 yamt else
605 1.1.8.1 yamt IFQ_INC_LEN(ifq);
606 1.1.8.1 yamt
607 1.1.8.1 yamt /* successfully queued. */
608 1.1.8.1 yamt
609 1.1.8.1 yamt enforce_wc(jif);
610 1.1.8.1 yamt
611 1.1.8.1 yamt if (!min_rates_adc(jif)) {
612 1.1.8.1 yamt delta_rate = assign_rate_drops_adc(jif);
613 1.1.8.1 yamt if (delta_rate != NULL) {
614 1.1.8.1 yamt for (pri = 0; pri <= jif->jif_maxpri; pri++)
615 1.1.8.1 yamt if ((cl = jif->jif_classes[pri]) != NULL &&
616 1.1.8.1 yamt !qempty(cl->cl_q))
617 1.1.8.1 yamt cl->service_rate += delta_rate[pri];
618 1.1.8.1 yamt free(delta_rate, M_DEVBUF);
619 1.1.8.1 yamt }
620 1.1.8.1 yamt }
621 1.1.8.1 yamt
622 1.1.8.1 yamt delta_rate = adjust_rates_rdc(jif);
623 1.1.8.1 yamt
624 1.1.8.1 yamt if (delta_rate != NULL) {
625 1.1.8.1 yamt for (pri = 0; pri <= jif->jif_maxpri; pri++)
626 1.1.8.1 yamt if ((cl = jif->jif_classes[pri]) != NULL &&
627 1.1.8.1 yamt !qempty(cl->cl_q))
628 1.1.8.1 yamt cl->service_rate += delta_rate[pri];
629 1.1.8.1 yamt free(delta_rate, M_DEVBUF);
630 1.1.8.1 yamt }
631 1.1.8.1 yamt
632 1.1.8.1 yamt tstamp2 = read_machclk();
633 1.1.8.1 yamt cycles = delay_diff(tstamp2, tstamp1);
634 1.1.8.1 yamt if (cycles > jif->wc_cycles_enqueue)
635 1.1.8.1 yamt jif->wc_cycles_enqueue=cycles;
636 1.1.8.1 yamt if (cycles < jif->bc_cycles_enqueue)
637 1.1.8.1 yamt jif->bc_cycles_enqueue=cycles;
638 1.1.8.1 yamt
639 1.1.8.1 yamt jif->avg_cycles_enqueue += cycles;
640 1.1.8.1 yamt jif->avg_cycles2_enqueue += cycles * cycles;
641 1.1.8.1 yamt
642 1.1.8.1 yamt return (return_flag);
643 1.1.8.1 yamt }
644 1.1.8.1 yamt
645 1.1.8.1 yamt /*
646 1.1.8.1 yamt * jobs_dequeue is a dequeue function to be registered to
647 1.1.8.1 yamt * (*altq_dequeue) in struct ifaltq.
648 1.1.8.1 yamt *
649 1.1.8.1 yamt * note: ALTDQ_POLL returns the next packet without removing the packet
650 1.1.8.1 yamt * from the queue. ALTDQ_REMOVE is a normal dequeue operation.
651 1.1.8.1 yamt * ALTDQ_REMOVE must return the same packet if called immediately
652 1.1.8.1 yamt * after ALTDQ_POLL.
653 1.1.8.1 yamt */
654 1.1.8.1 yamt
655 1.1.8.1 yamt static struct mbuf *
656 1.1.8.1 yamt jobs_dequeue(struct ifaltq *ifq, int op)
657 1.1.8.1 yamt {
658 1.1.8.1 yamt struct jobs_if *jif = (struct jobs_if *)ifq->altq_disc;
659 1.1.8.1 yamt struct jobs_class *cl;
660 1.1.8.1 yamt struct mbuf *m;
661 1.1.8.1 yamt int pri;
662 1.1.8.1 yamt int svc_class;
663 1.1.8.1 yamt int64_t max_error;
664 1.1.8.1 yamt int64_t error;
665 1.1.8.1 yamt u_int64_t now;
666 1.1.8.1 yamt u_int64_t tstamp1, tstamp2, cycles;
667 1.1.8.1 yamt
668 1.1.8.1 yamt jif->total_dequeued++;
669 1.1.8.1 yamt
670 1.1.8.1 yamt now = read_machclk();
671 1.1.8.1 yamt tstamp1 = now;
672 1.1.8.1 yamt
673 1.1.8.1 yamt if (IFQ_IS_EMPTY(ifq)) {
674 1.1.8.1 yamt /* no packet in the queue */
675 1.1.8.1 yamt for (pri=0; pri <= jif->jif_maxpri; pri++) {
676 1.1.8.1 yamt cl = jif->jif_classes[pri];
677 1.1.8.1 yamt if (cl != NULL)
678 1.1.8.1 yamt cl->idletime = now;
679 1.1.8.1 yamt }
680 1.1.8.1 yamt
681 1.1.8.1 yamt tstamp2 = read_machclk();
682 1.1.8.1 yamt cycles = delay_diff(tstamp2, tstamp1);
683 1.1.8.1 yamt if (cycles > jif->wc_cycles_dequeue)
684 1.1.8.1 yamt jif->wc_cycles_dequeue = cycles;
685 1.1.8.1 yamt if (cycles < jif->bc_cycles_dequeue)
686 1.1.8.1 yamt jif->bc_cycles_dequeue = cycles;
687 1.1.8.1 yamt
688 1.1.8.1 yamt jif->avg_cycles_dequeue += cycles;
689 1.1.8.1 yamt jif->avg_cycles2_dequeue += cycles * cycles;
690 1.1.8.1 yamt
691 1.1.8.1 yamt return (NULL);
692 1.1.8.1 yamt }
693 1.1.8.1 yamt
694 1.1.8.1 yamt /*
695 1.1.8.1 yamt * select the class whose actual tranmissions are the furthest
696 1.1.8.1 yamt * from the promised transmissions
697 1.1.8.1 yamt */
698 1.1.8.1 yamt
699 1.1.8.1 yamt max_error = -1;
700 1.1.8.1 yamt svc_class = -1;
701 1.1.8.1 yamt
702 1.1.8.1 yamt for (pri=0; pri <= jif->jif_maxpri; pri++) {
703 1.1.8.1 yamt if (((cl = jif->jif_classes[pri]) != NULL)
704 1.1.8.1 yamt && !qempty(cl->cl_q)) {
705 1.1.8.1 yamt error = (int64_t)cl->cl_rout_th.bytes
706 1.1.8.1 yamt -(int64_t)scale_rate(cl->cl_rout.bytes);
707 1.1.8.1 yamt if (max_error == -1) {
708 1.1.8.1 yamt max_error = error;
709 1.1.8.1 yamt svc_class = pri;
710 1.1.8.1 yamt } else if (error > max_error) {
711 1.1.8.1 yamt max_error = error;
712 1.1.8.1 yamt svc_class = pri;
713 1.1.8.1 yamt }
714 1.1.8.1 yamt }
715 1.1.8.1 yamt }
716 1.1.8.1 yamt
717 1.1.8.1 yamt if (svc_class != -1)
718 1.1.8.1 yamt cl = jif->jif_classes[svc_class];
719 1.1.8.1 yamt else
720 1.1.8.1 yamt cl = NULL;
721 1.1.8.1 yamt
722 1.1.8.1 yamt if (op == ALTDQ_POLL) {
723 1.1.8.1 yamt tstamp2 = read_machclk();
724 1.1.8.1 yamt cycles = delay_diff(tstamp2, tstamp1);
725 1.1.8.1 yamt if (cycles > jif->wc_cycles_dequeue)
726 1.1.8.1 yamt jif->wc_cycles_dequeue = cycles;
727 1.1.8.1 yamt if (cycles < jif->bc_cycles_dequeue)
728 1.1.8.1 yamt jif->bc_cycles_dequeue = cycles;
729 1.1.8.1 yamt
730 1.1.8.1 yamt jif->avg_cycles_dequeue += cycles;
731 1.1.8.1 yamt jif->avg_cycles2_dequeue += cycles * cycles;
732 1.1.8.1 yamt
733 1.1.8.1 yamt return (jobs_pollq(cl));
734 1.1.8.1 yamt }
735 1.1.8.1 yamt
736 1.1.8.1 yamt if (cl != NULL)
737 1.1.8.1 yamt m = jobs_getq(cl);
738 1.1.8.1 yamt else
739 1.1.8.1 yamt m = NULL;
740 1.1.8.1 yamt
741 1.1.8.1 yamt if (m != NULL) {
742 1.1.8.1 yamt IFQ_DEC_LEN(ifq);
743 1.1.8.1 yamt if (qempty(cl->cl_q))
744 1.1.8.1 yamt cl->cl_period++;
745 1.1.8.1 yamt
746 1.1.8.1 yamt cl->cl_lastdel = (u_int64_t)delay_diff(now,
747 1.1.8.1 yamt tslist_first(cl->arv_tm)->timestamp);
748 1.1.8.1 yamt if (cl->concerned_adc
749 1.1.8.1 yamt && (int64_t)cl->cl_lastdel > cl->cl_adc)
750 1.1.8.1 yamt cl->adc_violations++;
751 1.1.8.1 yamt cl->cl_avgdel += ticks_to_secs(GRANULARITY*cl->cl_lastdel);
752 1.1.8.1 yamt
753 1.1.8.1 yamt PKTCNTR_ADD(&cl->cl_rout, m_pktlen(m));
754 1.1.8.1 yamt PKTCNTR_ADD(&cl->st_rout, m_pktlen(m));
755 1.1.8.1 yamt }
756 1.1.8.1 yamt if (cl != NULL)
757 1.1.8.1 yamt tslist_dequeue(cl); /* dequeue the timestamp */
758 1.1.8.1 yamt
759 1.1.8.1 yamt tstamp2 = read_machclk();
760 1.1.8.1 yamt cycles = delay_diff(tstamp2, tstamp1);
761 1.1.8.1 yamt if (cycles > jif->wc_cycles_dequeue)
762 1.1.8.1 yamt jif->wc_cycles_dequeue = cycles;
763 1.1.8.1 yamt if (cycles < jif->bc_cycles_dequeue)
764 1.1.8.1 yamt jif->bc_cycles_dequeue = cycles;
765 1.1.8.1 yamt
766 1.1.8.1 yamt jif->avg_cycles_dequeue += cycles;
767 1.1.8.1 yamt jif->avg_cycles2_dequeue += cycles * cycles;
768 1.1.8.1 yamt
769 1.1.8.1 yamt return (m);
770 1.1.8.1 yamt }
771 1.1.8.1 yamt
772 1.1.8.1 yamt static int
773 1.1.8.1 yamt jobs_addq(struct jobs_class *cl, struct mbuf *m, struct jobs_if *jif)
774 1.1.8.1 yamt {
775 1.1.8.1 yamt int victim;
776 1.1.8.1 yamt u_int64_t len;
777 1.1.8.1 yamt u_int64_t now;
778 1.1.8.1 yamt struct jobs_class* victim_class;
779 1.1.8.1 yamt
780 1.1.8.1 yamt victim = -1;
781 1.1.8.1 yamt victim_class = NULL;
782 1.1.8.1 yamt len = 0;
783 1.1.8.1 yamt
784 1.1.8.1 yamt now = read_machclk();
785 1.1.8.1 yamt
786 1.1.8.1 yamt if (jif->jif_separate && qlen(cl->cl_q) >= jif->jif_qlimit) {
787 1.1.8.1 yamt /*
788 1.1.8.1 yamt * separate buffers: no guarantees on packet drops
789 1.1.8.1 yamt * can be offered
790 1.1.8.1 yamt * thus we drop the incoming packet
791 1.1.8.1 yamt */
792 1.1.8.1 yamt len = (u_int64_t)m_pktlen(m);
793 1.1.8.1 yamt PKTCNTR_ADD(&cl->cl_dropcnt, (int)len);
794 1.1.8.1 yamt PKTCNTR_SUB(&cl->cl_rin, (int)len);
795 1.1.8.1 yamt PKTCNTR_ADD(&cl->st_dropcnt, (int)len);
796 1.1.8.1 yamt PKTCNTR_SUB(&cl->st_rin, (int)len);
797 1.1.8.1 yamt cl->current_loss += (len << SCALE_LOSS)
798 1.1.8.1 yamt /cl->cl_arrival.bytes;
799 1.1.8.1 yamt m_freem(m);
800 1.1.8.1 yamt return (-1);
801 1.1.8.1 yamt
802 1.1.8.1 yamt } else if (!jif->jif_separate
803 1.1.8.1 yamt && jif->jif_ifq->ifq_len >= jif->jif_qlimit) {
804 1.1.8.1 yamt /* shared buffer: supports guarantees on losses */
805 1.1.8.1 yamt if (!cl->concerned_rlc) {
806 1.1.8.1 yamt if (!cl->concerned_alc) {
807 1.1.8.1 yamt /*
808 1.1.8.1 yamt * no ALC, no RLC on this class:
809 1.1.8.1 yamt * drop the incoming packet
810 1.1.8.1 yamt */
811 1.1.8.1 yamt len = (u_int64_t)m_pktlen(m);
812 1.1.8.1 yamt PKTCNTR_ADD(&cl->cl_dropcnt, (int)len);
813 1.1.8.1 yamt PKTCNTR_SUB(&cl->cl_rin, (int)len);
814 1.1.8.1 yamt PKTCNTR_ADD(&cl->st_dropcnt, (int)len);
815 1.1.8.1 yamt PKTCNTR_SUB(&cl->st_rin, (int)len);
816 1.1.8.1 yamt cl->current_loss += (len << SCALE_LOSS)/cl->cl_arrival.bytes;
817 1.1.8.1 yamt m_freem(m);
818 1.1.8.1 yamt return (-1);
819 1.1.8.1 yamt } else {
820 1.1.8.1 yamt /*
821 1.1.8.1 yamt * no RLC, but an ALC:
822 1.1.8.1 yamt * drop the incoming packet if possible
823 1.1.8.1 yamt */
824 1.1.8.1 yamt len = (u_int64_t)m_pktlen(m);
825 1.1.8.1 yamt if (cl->current_loss + (len << SCALE_LOSS)
826 1.1.8.1 yamt / cl->cl_arrival.bytes <= cl->cl_alc) {
827 1.1.8.1 yamt PKTCNTR_ADD(&cl->cl_dropcnt, (int)len);
828 1.1.8.1 yamt PKTCNTR_SUB(&cl->cl_rin, (int)len);
829 1.1.8.1 yamt PKTCNTR_ADD(&cl->st_dropcnt, (int)len);
830 1.1.8.1 yamt PKTCNTR_SUB(&cl->st_rin, (int)len);
831 1.1.8.1 yamt cl->current_loss += (len << SCALE_LOSS)/cl->cl_arrival.bytes;
832 1.1.8.1 yamt m_freem(m);
833 1.1.8.1 yamt return (-1);
834 1.1.8.1 yamt } else {
835 1.1.8.1 yamt /*
836 1.1.8.1 yamt * the ALC would be violated:
837 1.1.8.1 yamt * pick another class
838 1.1.8.1 yamt */
839 1.1.8.1 yamt _addq(cl->cl_q, m);
840 1.1.8.1 yamt tslist_enqueue(cl, now);
841 1.1.8.1 yamt
842 1.1.8.1 yamt victim = pick_dropped_rlc(jif);
843 1.1.8.1 yamt
844 1.1.8.1 yamt if (victim == -1) {
845 1.1.8.1 yamt /*
846 1.1.8.1 yamt * something went wrong
847 1.1.8.1 yamt * let us discard
848 1.1.8.1 yamt * the incoming packet,
849 1.1.8.1 yamt * regardless of what
850 1.1.8.1 yamt * may happen...
851 1.1.8.1 yamt */
852 1.1.8.1 yamt victim_class = cl;
853 1.1.8.1 yamt } else
854 1.1.8.1 yamt victim_class = jif->jif_classes[victim];
855 1.1.8.1 yamt
856 1.1.8.1 yamt if (victim_class != NULL) {
857 1.1.8.1 yamt /*
858 1.1.8.1 yamt * test for safety
859 1.1.8.1 yamt * purposes...
860 1.1.8.1 yamt * it must be true
861 1.1.8.1 yamt */
862 1.1.8.1 yamt m = _getq_tail(victim_class->cl_q);
863 1.1.8.1 yamt len = (u_int64_t)m_pktlen(m);
864 1.1.8.1 yamt PKTCNTR_ADD(&victim_class->cl_dropcnt, (int)len);
865 1.1.8.1 yamt PKTCNTR_SUB(&victim_class->cl_rin, (int)len);
866 1.1.8.1 yamt PKTCNTR_ADD(&victim_class->st_dropcnt, (int)len);
867 1.1.8.1 yamt PKTCNTR_SUB(&victim_class->st_rin, (int)len);
868 1.1.8.1 yamt victim_class->current_loss += (len << SCALE_LOSS)/victim_class->cl_arrival.bytes;
869 1.1.8.1 yamt m_freem(m); /* the packet is trashed here */
870 1.1.8.1 yamt tslist_drop(victim_class); /* and its timestamp as well */
871 1.1.8.1 yamt }
872 1.1.8.1 yamt return (-1);
873 1.1.8.1 yamt }
874 1.1.8.1 yamt }
875 1.1.8.1 yamt } else {
876 1.1.8.1 yamt /*
877 1.1.8.1 yamt * RLC on that class:
878 1.1.8.1 yamt * pick class according to RLCs
879 1.1.8.1 yamt */
880 1.1.8.1 yamt _addq(cl->cl_q, m);
881 1.1.8.1 yamt tslist_enqueue(cl, now);
882 1.1.8.1 yamt
883 1.1.8.1 yamt victim = pick_dropped_rlc(jif);
884 1.1.8.1 yamt if (victim == -1) {
885 1.1.8.1 yamt /*
886 1.1.8.1 yamt * something went wrong
887 1.1.8.1 yamt * let us discard the incoming packet,
888 1.1.8.1 yamt * regardless of what may happen...
889 1.1.8.1 yamt */
890 1.1.8.1 yamt victim_class = cl;
891 1.1.8.1 yamt } else
892 1.1.8.1 yamt victim_class = jif->jif_classes[victim];
893 1.1.8.1 yamt
894 1.1.8.1 yamt if (victim_class != NULL) {
895 1.1.8.1 yamt /*
896 1.1.8.1 yamt * test for safety purposes...
897 1.1.8.1 yamt * it must be true
898 1.1.8.1 yamt */
899 1.1.8.1 yamt m = _getq_tail(victim_class->cl_q);
900 1.1.8.1 yamt len = (u_int64_t)m_pktlen(m);
901 1.1.8.1 yamt PKTCNTR_ADD(&victim_class->cl_dropcnt, (int)len);
902 1.1.8.1 yamt PKTCNTR_SUB(&victim_class->cl_rin, (int)len);
903 1.1.8.1 yamt PKTCNTR_ADD(&victim_class->st_dropcnt, (int)len);
904 1.1.8.1 yamt PKTCNTR_SUB(&victim_class->st_rin, (int)len);
905 1.1.8.1 yamt victim_class->current_loss += (len << SCALE_LOSS)/victim_class->cl_arrival.bytes;
906 1.1.8.1 yamt m_freem(m); /* the packet is trashed here */
907 1.1.8.1 yamt tslist_drop(victim_class); /* and its timestamp as well */
908 1.1.8.1 yamt }
909 1.1.8.1 yamt return (-1);
910 1.1.8.1 yamt }
911 1.1.8.1 yamt }
912 1.1.8.1 yamt /* else: no drop */
913 1.1.8.1 yamt
914 1.1.8.1 yamt _addq(cl->cl_q, m);
915 1.1.8.1 yamt tslist_enqueue(cl, now);
916 1.1.8.1 yamt
917 1.1.8.1 yamt return (0);
918 1.1.8.1 yamt }
919 1.1.8.1 yamt
920 1.1.8.1 yamt static struct mbuf *
921 1.1.8.1 yamt jobs_getq(struct jobs_class *cl)
922 1.1.8.1 yamt {
923 1.1.8.1 yamt return _getq(cl->cl_q);
924 1.1.8.1 yamt }
925 1.1.8.1 yamt
926 1.1.8.1 yamt static struct mbuf *
927 1.1.8.1 yamt jobs_pollq(struct jobs_class *cl)
928 1.1.8.1 yamt {
929 1.1.8.1 yamt return qhead(cl->cl_q);
930 1.1.8.1 yamt }
931 1.1.8.1 yamt
932 1.1.8.1 yamt static void
933 1.1.8.1 yamt jobs_purgeq(struct jobs_class *cl)
934 1.1.8.1 yamt {
935 1.1.8.1 yamt struct mbuf *m;
936 1.1.8.1 yamt
937 1.1.8.1 yamt if (qempty(cl->cl_q))
938 1.1.8.1 yamt return;
939 1.1.8.1 yamt
940 1.1.8.1 yamt while ((m = _getq(cl->cl_q)) != NULL) {
941 1.1.8.1 yamt PKTCNTR_ADD(&cl->cl_dropcnt, m_pktlen(m));
942 1.1.8.1 yamt PKTCNTR_ADD(&cl->st_dropcnt, m_pktlen(m));
943 1.1.8.1 yamt m_freem(m);
944 1.1.8.1 yamt tslist_drop(cl);
945 1.1.8.1 yamt }
946 1.1.8.1 yamt ASSERT(qlen(cl->cl_q) == 0);
947 1.1.8.1 yamt }
948 1.1.8.1 yamt
949 1.1.8.1 yamt /*
950 1.1.8.1 yamt * timestamp list support routines
951 1.1.8.1 yamt *
952 1.1.8.1 yamt * this implementation has been revamped and
953 1.1.8.1 yamt * now uses a TAILQ structure.
954 1.1.8.1 yamt * timestamp list holds class timestamps
955 1.1.8.1 yamt * there is one timestamp list per class.
956 1.1.8.1 yamt */
957 1.1.8.1 yamt static TSLIST *
958 1.1.8.1 yamt tslist_alloc(void)
959 1.1.8.1 yamt {
960 1.1.8.1 yamt TSLIST *list_init;
961 1.1.8.1 yamt
962 1.1.8.1 yamt list_init = malloc(sizeof(TSLIST), M_DEVBUF, M_WAITOK);
963 1.1.8.1 yamt TAILQ_INIT(list_init);
964 1.1.8.1 yamt return (list_init);
965 1.1.8.1 yamt }
966 1.1.8.1 yamt
967 1.1.8.1 yamt static void
968 1.1.8.1 yamt tslist_destroy(struct jobs_class *cl)
969 1.1.8.1 yamt {
970 1.1.8.1 yamt while (tslist_first(cl->arv_tm) != NULL)
971 1.1.8.1 yamt tslist_dequeue(cl);
972 1.1.8.1 yamt
973 1.1.8.1 yamt free(cl->arv_tm, M_DEVBUF);
974 1.1.8.1 yamt }
975 1.1.8.1 yamt
976 1.1.8.1 yamt static int
977 1.1.8.1 yamt tslist_enqueue(struct jobs_class *cl, u_int64_t arv)
978 1.1.8.1 yamt {
979 1.1.8.1 yamt TSENTRY *pushed;
980 1.1.8.1 yamt pushed = malloc(sizeof(TSENTRY), M_DEVBUF, M_WAITOK);
981 1.1.8.1 yamt if (pushed == NULL)
982 1.1.8.1 yamt return (0);
983 1.1.8.1 yamt
984 1.1.8.1 yamt pushed->timestamp = arv;
985 1.1.8.1 yamt TAILQ_INSERT_TAIL(cl->arv_tm, pushed, ts_list);
986 1.1.8.1 yamt return (1);
987 1.1.8.1 yamt }
988 1.1.8.1 yamt
989 1.1.8.1 yamt static void
990 1.1.8.1 yamt tslist_dequeue(struct jobs_class *cl)
991 1.1.8.1 yamt {
992 1.1.8.1 yamt TSENTRY *popped;
993 1.1.8.1 yamt popped = tslist_first(cl->arv_tm);
994 1.1.8.1 yamt if (popped != NULL) {
995 1.1.8.1 yamt TAILQ_REMOVE(cl->arv_tm, popped, ts_list);
996 1.1.8.1 yamt free(popped, M_DEVBUF);
997 1.1.8.1 yamt }
998 1.1.8.1 yamt return;
999 1.1.8.1 yamt }
1000 1.1.8.1 yamt
1001 1.1.8.1 yamt static void
1002 1.1.8.1 yamt tslist_drop(struct jobs_class *cl)
1003 1.1.8.1 yamt {
1004 1.1.8.1 yamt TSENTRY *popped;
1005 1.1.8.1 yamt popped = tslist_last(cl->arv_tm);
1006 1.1.8.1 yamt if (popped != NULL) {
1007 1.1.8.1 yamt TAILQ_REMOVE(cl->arv_tm, popped, ts_list);
1008 1.1.8.1 yamt free(popped, M_DEVBUF);
1009 1.1.8.1 yamt }
1010 1.1.8.1 yamt return;
1011 1.1.8.1 yamt }
1012 1.1.8.1 yamt
1013 1.1.8.1 yamt /*
1014 1.1.8.1 yamt * rate allocation support routines
1015 1.1.8.1 yamt */
1016 1.1.8.1 yamt /*
1017 1.1.8.1 yamt * enforce_wc: enforce that backlogged classes have non-zero
1018 1.1.8.1 yamt * service rate, and that non-backlogged classes have zero
1019 1.1.8.1 yamt * service rate.
1020 1.1.8.1 yamt */
1021 1.1.8.1 yamt
1022 1.1.8.1 yamt static int
1023 1.1.8.1 yamt enforce_wc(struct jobs_if *jif)
1024 1.1.8.1 yamt {
1025 1.1.8.1 yamt struct jobs_class *cl;
1026 1.1.8.1 yamt
1027 1.1.8.1 yamt int64_t active_classes;
1028 1.1.8.1 yamt int pri;
1029 1.1.8.1 yamt int is_backlogged, class_exists, updated;
1030 1.1.8.1 yamt
1031 1.1.8.1 yamt updated = 0;
1032 1.1.8.1 yamt active_classes = 0;
1033 1.1.8.1 yamt
1034 1.1.8.1 yamt for (pri = 0; pri <= jif->jif_maxpri; pri++) {
1035 1.1.8.1 yamt cl = jif->jif_classes[pri];
1036 1.1.8.1 yamt class_exists = (cl != NULL);
1037 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1038 1.1.8.1 yamt
1039 1.1.8.1 yamt if (is_backlogged)
1040 1.1.8.1 yamt active_classes++;
1041 1.1.8.1 yamt if ((is_backlogged && cl->service_rate <= 0)
1042 1.1.8.1 yamt ||(class_exists
1043 1.1.8.1 yamt && !is_backlogged && cl->service_rate > 0))
1044 1.1.8.1 yamt updated = 1;
1045 1.1.8.1 yamt }
1046 1.1.8.1 yamt
1047 1.1.8.1 yamt if (updated) {
1048 1.1.8.1 yamt for (pri = 0; pri <= jif->jif_maxpri; pri++) {
1049 1.1.8.1 yamt cl = jif->jif_classes[pri];
1050 1.1.8.1 yamt class_exists = (cl != NULL);
1051 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1052 1.1.8.1 yamt
1053 1.1.8.1 yamt if (class_exists && !is_backlogged)
1054 1.1.8.1 yamt cl->service_rate = 0;
1055 1.1.8.1 yamt else if (is_backlogged)
1056 1.1.8.1 yamt cl->service_rate = (int64_t)(bps_to_internal((u_int64_t)jif->jif_bandwidth)/active_classes);
1057 1.1.8.1 yamt }
1058 1.1.8.1 yamt }
1059 1.1.8.1 yamt
1060 1.1.8.1 yamt return (updated);
1061 1.1.8.1 yamt }
1062 1.1.8.1 yamt
1063 1.1.8.1 yamt /*
1064 1.1.8.1 yamt * adjust_rates_rdc: compute the service rates adjustments
1065 1.1.8.1 yamt * needed to realize the desired proportional delay differentiation.
1066 1.1.8.1 yamt * essentially, the rate adjustement delta_rate = prop_control*error,
1067 1.1.8.1 yamt * where error is the difference between the measured "weighted"
1068 1.1.8.1 yamt * delay and the mean of the weighted delays. see paper for more
1069 1.1.8.1 yamt * information.
1070 1.1.8.1 yamt * prop_control has slightly changed since the INFOCOM paper,
1071 1.1.8.1 yamt * this condition seems to provide better results.
1072 1.1.8.1 yamt */
1073 1.1.8.1 yamt
1074 1.1.8.1 yamt static int64_t *
1075 1.1.8.1 yamt adjust_rates_rdc(struct jobs_if *jif)
1076 1.1.8.1 yamt {
1077 1.1.8.1 yamt int64_t *result;
1078 1.1.8.1 yamt int64_t credit, available, lower_bound, upper_bound;
1079 1.1.8.1 yamt int64_t bk;
1080 1.1.8.1 yamt int i, j;
1081 1.1.8.1 yamt int rdc_classes, active_classes;
1082 1.1.8.1 yamt int class_exists, is_backlogged;
1083 1.1.8.1 yamt struct jobs_class *cl;
1084 1.1.8.1 yamt int64_t *error;
1085 1.1.8.1 yamt int64_t prop_control;
1086 1.1.8.1 yamt u_int64_t max_prod;
1087 1.1.8.1 yamt u_int64_t min_share;
1088 1.1.8.1 yamt u_int64_t max_avg_pkt_size;
1089 1.1.8.1 yamt
1090 1.1.8.1 yamt /*
1091 1.1.8.1 yamt * min_share is scaled
1092 1.1.8.1 yamt * to avoid dealing with doubles
1093 1.1.8.1 yamt */
1094 1.1.8.1 yamt active_classes = 0;
1095 1.1.8.1 yamt rdc_classes = 0;
1096 1.1.8.1 yamt max_prod = 0;
1097 1.1.8.1 yamt max_avg_pkt_size = 0;
1098 1.1.8.1 yamt
1099 1.1.8.1 yamt upper_bound = (int64_t)jif->jif_bandwidth;
1100 1.1.8.1 yamt
1101 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1102 1.1.8.1 yamt cl = jif->jif_classes[i];
1103 1.1.8.1 yamt class_exists = (cl != NULL);
1104 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1105 1.1.8.1 yamt if (is_backlogged) {
1106 1.1.8.1 yamt active_classes++;
1107 1.1.8.1 yamt if (cl->concerned_rdc)
1108 1.1.8.1 yamt rdc_classes++;
1109 1.1.8.1 yamt else
1110 1.1.8.1 yamt upper_bound -=
1111 1.1.8.1 yamt internal_to_bps(cl->service_rate);
1112 1.1.8.1 yamt }
1113 1.1.8.1 yamt }
1114 1.1.8.1 yamt
1115 1.1.8.1 yamt result = malloc((jif->jif_maxpri+1)*sizeof(int64_t),
1116 1.1.8.1 yamt M_DEVBUF, M_WAITOK);
1117 1.1.8.1 yamt
1118 1.1.8.1 yamt if (result == NULL)
1119 1.1.8.1 yamt return NULL;
1120 1.1.8.1 yamt
1121 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++)
1122 1.1.8.1 yamt result[i] = 0;
1123 1.1.8.1 yamt
1124 1.1.8.1 yamt if (upper_bound <= 0 || rdc_classes == 0)
1125 1.1.8.1 yamt return result;
1126 1.1.8.1 yamt
1127 1.1.8.1 yamt credit = 0;
1128 1.1.8.1 yamt lower_bound = 0;
1129 1.1.8.1 yamt min_share = ((u_int64_t)1 << SCALE_SHARE);
1130 1.1.8.1 yamt bk = 0;
1131 1.1.8.1 yamt
1132 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1133 1.1.8.1 yamt cl = jif->jif_classes[i];
1134 1.1.8.1 yamt class_exists = (cl != NULL);
1135 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1136 1.1.8.1 yamt if (is_backlogged && cl->concerned_rdc)
1137 1.1.8.1 yamt bk += cl->cl_rin.bytes;
1138 1.1.8.1 yamt }
1139 1.1.8.1 yamt
1140 1.1.8.1 yamt if (bk == 0)
1141 1.1.8.1 yamt return (result);
1142 1.1.8.1 yamt
1143 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1144 1.1.8.1 yamt cl = jif->jif_classes[i];
1145 1.1.8.1 yamt class_exists = (cl != NULL);
1146 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1147 1.1.8.1 yamt if (is_backlogged
1148 1.1.8.1 yamt && (cl->cl_rin.bytes << SCALE_SHARE)/bk < min_share)
1149 1.1.8.1 yamt min_share = (cl->cl_rin.bytes << SCALE_SHARE)/bk;
1150 1.1.8.1 yamt if (is_backlogged && cl->concerned_rdc
1151 1.1.8.1 yamt && cl->delay_prod_others > max_prod)
1152 1.1.8.1 yamt max_prod = cl->delay_prod_others;
1153 1.1.8.1 yamt
1154 1.1.8.1 yamt if (is_backlogged && cl->concerned_rdc
1155 1.1.8.1 yamt && cl->cl_rin.bytes > max_avg_pkt_size*cl->cl_rin.packets)
1156 1.1.8.1 yamt max_avg_pkt_size = (u_int64_t)((u_int)cl->cl_rin.bytes/(u_int)cl->cl_rin.packets);
1157 1.1.8.1 yamt }
1158 1.1.8.1 yamt
1159 1.1.8.1 yamt error = update_error(jif);
1160 1.1.8.1 yamt if (!error)
1161 1.1.8.1 yamt return (NULL);
1162 1.1.8.1 yamt
1163 1.1.8.1 yamt prop_control = (upper_bound*upper_bound*min_share)
1164 1.1.8.1 yamt /(max_prod*(max_avg_pkt_size << 2));
1165 1.1.8.1 yamt
1166 1.1.8.1 yamt prop_control = bps_to_internal(ticks_to_secs(prop_control)); /* in BT-1 */
1167 1.1.8.1 yamt
1168 1.1.8.1 yamt credit = 0;
1169 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1170 1.1.8.1 yamt cl = jif->jif_classes[i];
1171 1.1.8.1 yamt class_exists = (cl != NULL);
1172 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1173 1.1.8.1 yamt if (is_backlogged && cl->concerned_rdc) {
1174 1.1.8.1 yamt result[i] = -prop_control*error[i]; /* in BT-1 */
1175 1.1.8.1 yamt result[i] >>= (SCALE_SHARE);
1176 1.1.8.1 yamt }
1177 1.1.8.1 yamt }
1178 1.1.8.1 yamt
1179 1.1.8.1 yamt free(error, M_DEVBUF); /* we don't need these anymore */
1180 1.1.8.1 yamt
1181 1.1.8.1 yamt /* saturation */
1182 1.1.8.1 yamt
1183 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1184 1.1.8.1 yamt cl = jif->jif_classes[i];
1185 1.1.8.1 yamt class_exists = (cl != NULL);
1186 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1187 1.1.8.1 yamt
1188 1.1.8.1 yamt if (is_backlogged && cl->concerned_rdc)
1189 1.1.8.1 yamt lower_bound += cl->min_rate_adc;
1190 1.1.8.1 yamt /*
1191 1.1.8.1 yamt * note: if there's no ADC or ARC on cl,
1192 1.1.8.1 yamt * this is equal to zero, which is fine
1193 1.1.8.1 yamt */
1194 1.1.8.1 yamt }
1195 1.1.8.1 yamt
1196 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1197 1.1.8.1 yamt cl = jif->jif_classes[i];
1198 1.1.8.1 yamt class_exists = (cl != NULL);
1199 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1200 1.1.8.1 yamt
1201 1.1.8.1 yamt if (is_backlogged && cl->concerned_rdc
1202 1.1.8.1 yamt && result[i] + cl->service_rate > upper_bound) {
1203 1.1.8.1 yamt for (j = 0; j <= jif->jif_maxpri; j++) {
1204 1.1.8.1 yamt cl = jif->jif_classes[j];
1205 1.1.8.1 yamt class_exists = (cl != NULL);
1206 1.1.8.1 yamt is_backlogged = (class_exists
1207 1.1.8.1 yamt && !qempty(cl->cl_q));
1208 1.1.8.1 yamt if (is_backlogged && cl->concerned_rdc) {
1209 1.1.8.1 yamt if (j == i)
1210 1.1.8.1 yamt result[j] = upper_bound
1211 1.1.8.1 yamt -cl->service_rate
1212 1.1.8.1 yamt + cl->min_rate_adc
1213 1.1.8.1 yamt - lower_bound;
1214 1.1.8.1 yamt else
1215 1.1.8.1 yamt result[j] =
1216 1.1.8.1 yamt -cl->service_rate
1217 1.1.8.1 yamt +cl->min_rate_adc;
1218 1.1.8.1 yamt }
1219 1.1.8.1 yamt }
1220 1.1.8.1 yamt return result;
1221 1.1.8.1 yamt }
1222 1.1.8.1 yamt
1223 1.1.8.1 yamt cl = jif->jif_classes[i];
1224 1.1.8.1 yamt /* do this again since it may have been modified */
1225 1.1.8.1 yamt class_exists = (cl != NULL);
1226 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1227 1.1.8.1 yamt
1228 1.1.8.1 yamt if (is_backlogged && cl->concerned_rdc
1229 1.1.8.1 yamt && result[i] + cl->service_rate < cl->min_rate_adc) {
1230 1.1.8.1 yamt credit += cl->service_rate+result[i]
1231 1.1.8.1 yamt -cl->min_rate_adc;
1232 1.1.8.1 yamt /* "credit" is in fact a negative number */
1233 1.1.8.1 yamt result[i] = -cl->service_rate+cl->min_rate_adc;
1234 1.1.8.1 yamt }
1235 1.1.8.1 yamt }
1236 1.1.8.1 yamt
1237 1.1.8.1 yamt for (i = jif->jif_maxpri; (i >= 0 && credit < 0); i--) {
1238 1.1.8.1 yamt cl = jif->jif_classes[i];
1239 1.1.8.1 yamt class_exists = (cl != NULL);
1240 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1241 1.1.8.1 yamt
1242 1.1.8.1 yamt if (is_backlogged && cl->concerned_rdc) {
1243 1.1.8.1 yamt available = result[i]
1244 1.1.8.1 yamt + cl->service_rate-cl->min_rate_adc;
1245 1.1.8.1 yamt if (available >= -credit) {
1246 1.1.8.1 yamt result[i] += credit;
1247 1.1.8.1 yamt credit = 0;
1248 1.1.8.1 yamt } else {
1249 1.1.8.1 yamt result[i] -= available;
1250 1.1.8.1 yamt credit += available;
1251 1.1.8.1 yamt }
1252 1.1.8.1 yamt }
1253 1.1.8.1 yamt }
1254 1.1.8.1 yamt return result;
1255 1.1.8.1 yamt }
1256 1.1.8.1 yamt
1257 1.1.8.1 yamt /*
1258 1.1.8.1 yamt * assign_rate_drops_adc: returns the adjustment needed to
1259 1.1.8.1 yamt * the service rates to meet the absolute delay/rate constraints
1260 1.1.8.1 yamt * (delay/throughput bounds) and drops traffic if need be.
1261 1.1.8.1 yamt * see tech. report UVA/T.R. CS-2000-24/CS-2001-21 for more info.
1262 1.1.8.1 yamt */
1263 1.1.8.1 yamt
1264 1.1.8.1 yamt static int64_t *
1265 1.1.8.1 yamt assign_rate_drops_adc(struct jobs_if *jif)
1266 1.1.8.1 yamt {
1267 1.1.8.1 yamt int64_t *result;
1268 1.1.8.1 yamt int class_exists, is_backlogged;
1269 1.1.8.1 yamt struct jobs_class *cl;
1270 1.1.8.1 yamt
1271 1.1.8.1 yamt int64_t *c, *n, *k;
1272 1.1.8.1 yamt int64_t *available;
1273 1.1.8.1 yamt
1274 1.1.8.1 yamt int lowest, highest;
1275 1.1.8.1 yamt int keep_going;
1276 1.1.8.1 yamt int i;
1277 1.1.8.1 yamt u_int64_t now, oldest_arv;
1278 1.1.8.1 yamt int64_t remaining_time;
1279 1.1.8.1 yamt struct mbuf* pkt;
1280 1.1.8.1 yamt u_int64_t len;
1281 1.1.8.1 yamt
1282 1.1.8.1 yamt now = read_machclk();
1283 1.1.8.1 yamt oldest_arv = now;
1284 1.1.8.1 yamt
1285 1.1.8.1 yamt result = malloc((jif->jif_maxpri+1)*sizeof(int64_t), M_DEVBUF, M_WAITOK);
1286 1.1.8.1 yamt if (result == NULL)
1287 1.1.8.1 yamt return NULL;
1288 1.1.8.1 yamt c = malloc((jif->jif_maxpri+1)*sizeof(u_int64_t), M_DEVBUF, M_WAITOK);
1289 1.1.8.1 yamt if (c == NULL)
1290 1.1.8.1 yamt return NULL;
1291 1.1.8.1 yamt n = malloc((jif->jif_maxpri+1)*sizeof(u_int64_t), M_DEVBUF, M_WAITOK);
1292 1.1.8.1 yamt if (n == NULL)
1293 1.1.8.1 yamt return NULL;
1294 1.1.8.1 yamt k = malloc((jif->jif_maxpri+1)*sizeof(u_int64_t), M_DEVBUF, M_WAITOK);
1295 1.1.8.1 yamt if (k == NULL)
1296 1.1.8.1 yamt return NULL;
1297 1.1.8.1 yamt available = malloc((jif->jif_maxpri+1)*sizeof(int64_t), M_DEVBUF, M_WAITOK);
1298 1.1.8.1 yamt if (available == NULL)
1299 1.1.8.1 yamt return NULL;
1300 1.1.8.1 yamt
1301 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++)
1302 1.1.8.1 yamt result[i] = 0;
1303 1.1.8.1 yamt
1304 1.1.8.1 yamt keep_going = 1;
1305 1.1.8.1 yamt
1306 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1307 1.1.8.1 yamt cl = jif->jif_classes[i];
1308 1.1.8.1 yamt class_exists = (cl != NULL);
1309 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1310 1.1.8.1 yamt
1311 1.1.8.1 yamt if (is_backlogged) {
1312 1.1.8.1 yamt if (cl->concerned_adc) {
1313 1.1.8.1 yamt /*
1314 1.1.8.1 yamt * get the arrival time of the oldest
1315 1.1.8.1 yamt * class-i packet
1316 1.1.8.1 yamt */
1317 1.1.8.1 yamt if (tslist_first(cl->arv_tm) == NULL)
1318 1.1.8.1 yamt oldest_arv = now; /* NOTREACHED */
1319 1.1.8.1 yamt else
1320 1.1.8.1 yamt oldest_arv = (tslist_first(cl->arv_tm))->timestamp;
1321 1.1.8.1 yamt
1322 1.1.8.1 yamt n[i] = cl->service_rate;
1323 1.1.8.1 yamt k[i] = scale_rate((int64_t)(cl->cl_rin.bytes - cl->cl_rout.bytes));
1324 1.1.8.1 yamt
1325 1.1.8.1 yamt remaining_time = cl->cl_adc
1326 1.1.8.1 yamt - (int64_t)delay_diff(now, oldest_arv);
1327 1.1.8.1 yamt if (remaining_time > 0) {
1328 1.1.8.1 yamt c[i] = remaining_time;
1329 1.1.8.1 yamt /*
1330 1.1.8.1 yamt * c is the remaining time before
1331 1.1.8.1 yamt * the deadline is violated
1332 1.1.8.1 yamt * (in ticks)
1333 1.1.8.1 yamt */
1334 1.1.8.1 yamt available[i] = n[i]-k[i]/c[i];
1335 1.1.8.1 yamt } else {
1336 1.1.8.1 yamt /*
1337 1.1.8.1 yamt * deadline has passed...
1338 1.1.8.1 yamt * we allocate the whole link
1339 1.1.8.1 yamt * capacity to hopefully
1340 1.1.8.1 yamt * solve the problem
1341 1.1.8.1 yamt */
1342 1.1.8.1 yamt c[i] = 0;
1343 1.1.8.1 yamt available[i] = -((int64_t)bps_to_internal((u_int64_t)jif->jif_bandwidth));
1344 1.1.8.1 yamt }
1345 1.1.8.1 yamt if (cl->concerned_arc) {
1346 1.1.8.1 yamt /*
1347 1.1.8.1 yamt * there's an ARC in addition
1348 1.1.8.1 yamt * to the ADC
1349 1.1.8.1 yamt */
1350 1.1.8.1 yamt if (n[i] - cl->cl_arc < available[i])
1351 1.1.8.1 yamt available[i] = n[i]
1352 1.1.8.1 yamt - cl->cl_arc;
1353 1.1.8.1 yamt }
1354 1.1.8.1 yamt } else if (cl->concerned_arc) {
1355 1.1.8.1 yamt /*
1356 1.1.8.1 yamt * backlogged, concerned by ARC
1357 1.1.8.1 yamt * but not by ADC
1358 1.1.8.1 yamt */
1359 1.1.8.1 yamt n[i] = cl->service_rate;
1360 1.1.8.1 yamt available[i] = n[i] - cl->cl_arc;
1361 1.1.8.1 yamt } else {
1362 1.1.8.1 yamt /*
1363 1.1.8.1 yamt * backlogged but not concerned by ADC
1364 1.1.8.1 yamt * or ARC -> can give everything
1365 1.1.8.1 yamt */
1366 1.1.8.1 yamt n[i] = cl->service_rate;
1367 1.1.8.1 yamt available[i] = n[i];
1368 1.1.8.1 yamt }
1369 1.1.8.1 yamt } else {
1370 1.1.8.1 yamt /* not backlogged */
1371 1.1.8.1 yamt n[i] = 0;
1372 1.1.8.1 yamt k[i] = 0;
1373 1.1.8.1 yamt c[i] = 0;
1374 1.1.8.1 yamt if (class_exists)
1375 1.1.8.1 yamt available[i] = cl->service_rate;
1376 1.1.8.1 yamt else
1377 1.1.8.1 yamt available[i] = 0;
1378 1.1.8.1 yamt }
1379 1.1.8.1 yamt }
1380 1.1.8.1 yamt
1381 1.1.8.1 yamt /* step 1: adjust rates (greedy algorithm) */
1382 1.1.8.1 yamt
1383 1.1.8.1 yamt highest = 0;
1384 1.1.8.1 yamt lowest = jif->jif_maxpri;
1385 1.1.8.1 yamt
1386 1.1.8.1 yamt while (highest < jif->jif_maxpri+1 && available[highest] >= 0)
1387 1.1.8.1 yamt highest++; /* which is the highest class that needs more service? */
1388 1.1.8.1 yamt while (lowest > 0 && available[lowest] <= 0)
1389 1.1.8.1 yamt lowest--; /* which is the lowest class that needs less service? */
1390 1.1.8.1 yamt
1391 1.1.8.1 yamt while (highest != jif->jif_maxpri+1 && lowest != -1) {
1392 1.1.8.1 yamt /* give the excess service from lowest to highest */
1393 1.1.8.1 yamt if (available[lowest]+available[highest] > 0) {
1394 1.1.8.1 yamt /*
1395 1.1.8.1 yamt * still some "credit" left
1396 1.1.8.1 yamt * give all that is needed by "highest"
1397 1.1.8.1 yamt */
1398 1.1.8.1 yamt n[lowest] += available[highest];
1399 1.1.8.1 yamt n[highest] -= available[highest];
1400 1.1.8.1 yamt available[lowest] += available[highest];
1401 1.1.8.1 yamt available[highest] = 0;
1402 1.1.8.1 yamt
1403 1.1.8.1 yamt while (highest < jif->jif_maxpri+1
1404 1.1.8.1 yamt && available[highest] >= 0)
1405 1.1.8.1 yamt highest++; /* which is the highest class that needs more service now? */
1406 1.1.8.1 yamt
1407 1.1.8.1 yamt } else if (available[lowest]+available[highest] == 0) {
1408 1.1.8.1 yamt /* no more credit left but it's fine */
1409 1.1.8.1 yamt n[lowest] += available[highest];
1410 1.1.8.1 yamt n[highest] -= available[highest];
1411 1.1.8.1 yamt available[highest] = 0;
1412 1.1.8.1 yamt available[lowest] = 0;
1413 1.1.8.1 yamt
1414 1.1.8.1 yamt while (highest < jif->jif_maxpri+1
1415 1.1.8.1 yamt && available[highest] >= 0)
1416 1.1.8.1 yamt highest++; /* which is the highest class that needs more service? */
1417 1.1.8.1 yamt while (lowest >= 0 && available[lowest] <= 0)
1418 1.1.8.1 yamt lowest--; /* which is the lowest class that needs less service? */
1419 1.1.8.1 yamt
1420 1.1.8.1 yamt } else if (available[lowest]+available[highest] < 0) {
1421 1.1.8.1 yamt /*
1422 1.1.8.1 yamt * no more credit left and we need to switch
1423 1.1.8.1 yamt * to another class
1424 1.1.8.1 yamt */
1425 1.1.8.1 yamt n[lowest] -= available[lowest];
1426 1.1.8.1 yamt n[highest] += available[lowest];
1427 1.1.8.1 yamt available[highest] += available[lowest];
1428 1.1.8.1 yamt available[lowest] = 0;
1429 1.1.8.1 yamt
1430 1.1.8.1 yamt while ((lowest >= 0)&&(available[lowest] <= 0))
1431 1.1.8.1 yamt lowest--; /* which is the lowest class that needs less service? */
1432 1.1.8.1 yamt }
1433 1.1.8.1 yamt }
1434 1.1.8.1 yamt
1435 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1436 1.1.8.1 yamt cl = jif->jif_classes[i];
1437 1.1.8.1 yamt class_exists = (cl != NULL);
1438 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1439 1.1.8.1 yamt if (is_backlogged) {
1440 1.1.8.1 yamt result[i] = n[i] - cl->service_rate;
1441 1.1.8.1 yamt } else {
1442 1.1.8.1 yamt if (class_exists)
1443 1.1.8.1 yamt result[i] = - cl->service_rate;
1444 1.1.8.1 yamt else
1445 1.1.8.1 yamt result[i] = 0;
1446 1.1.8.1 yamt }
1447 1.1.8.1 yamt }
1448 1.1.8.1 yamt
1449 1.1.8.1 yamt /* step 2: adjust drops (for ADC) */
1450 1.1.8.1 yamt
1451 1.1.8.1 yamt if (highest != jif->jif_maxpri+1) {
1452 1.1.8.1 yamt /* some class(es) still need(s) additional service */
1453 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1454 1.1.8.1 yamt cl = jif->jif_classes[i];
1455 1.1.8.1 yamt class_exists = (cl != NULL);
1456 1.1.8.1 yamt is_backlogged = (class_exists
1457 1.1.8.1 yamt && !qempty(cl->cl_q));
1458 1.1.8.1 yamt if (is_backlogged && available[i] < 0) {
1459 1.1.8.1 yamt if (cl->concerned_adc) {
1460 1.1.8.1 yamt k[i] = c[i]*n[i];
1461 1.1.8.1 yamt while (keep_going && scale_rate((int64_t)(cl->cl_rin.bytes-cl->cl_rout.bytes)) > k[i]) {
1462 1.1.8.1 yamt pkt = qtail(cl->cl_q);
1463 1.1.8.1 yamt if (pkt != NULL) {
1464 1.1.8.1 yamt /* "safeguard" test (a packet SHOULD be in there) */
1465 1.1.8.1 yamt len = (u_int64_t)m_pktlen(pkt);
1466 1.1.8.1 yamt /* access packet at the tail */
1467 1.1.8.1 yamt if (cl->concerned_alc
1468 1.1.8.1 yamt && cl->current_loss+(len << SCALE_LOSS)/cl->cl_arrival.bytes > cl->cl_alc) {
1469 1.1.8.1 yamt keep_going = 0; /* relax ADC in favor of ALC */
1470 1.1.8.1 yamt } else {
1471 1.1.8.1 yamt /* drop packet at the tail of the class-i queue, update values */
1472 1.1.8.1 yamt pkt = _getq_tail(cl->cl_q);
1473 1.1.8.1 yamt len = (u_int64_t)m_pktlen(pkt);
1474 1.1.8.1 yamt PKTCNTR_ADD(&cl->cl_dropcnt, (int)len);
1475 1.1.8.1 yamt PKTCNTR_SUB(&cl->cl_rin, (int)len);
1476 1.1.8.1 yamt PKTCNTR_ADD(&cl->st_dropcnt, (int)len);
1477 1.1.8.1 yamt PKTCNTR_SUB(&cl->st_rin, (int)len);
1478 1.1.8.1 yamt cl->current_loss += (len << SCALE_LOSS)/cl->cl_arrival.bytes;
1479 1.1.8.1 yamt m_freem(pkt); /* the packet is trashed here */
1480 1.1.8.1 yamt tslist_drop(cl);
1481 1.1.8.1 yamt IFQ_DEC_LEN(cl->cl_jif->jif_ifq);
1482 1.1.8.1 yamt }
1483 1.1.8.1 yamt } else
1484 1.1.8.1 yamt keep_going = 0; /* NOTREACHED */
1485 1.1.8.1 yamt }
1486 1.1.8.1 yamt k[i] = scale_rate((int64_t)(cl->cl_rin.bytes-cl->cl_rout.bytes));
1487 1.1.8.1 yamt }
1488 1.1.8.1 yamt /*
1489 1.1.8.1 yamt * n[i] is the max rate we can give.
1490 1.1.8.1 yamt * the above drops as much as possible
1491 1.1.8.1 yamt * to respect a delay bound.
1492 1.1.8.1 yamt * for throughput bounds,
1493 1.1.8.1 yamt * there's nothing that can be done
1494 1.1.8.1 yamt * after the greedy reallocation.
1495 1.1.8.1 yamt */
1496 1.1.8.1 yamt }
1497 1.1.8.1 yamt }
1498 1.1.8.1 yamt }
1499 1.1.8.1 yamt
1500 1.1.8.1 yamt /* update the values of min_rate_adc */
1501 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1502 1.1.8.1 yamt cl = jif->jif_classes[i];
1503 1.1.8.1 yamt class_exists = (cl != NULL);
1504 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1505 1.1.8.1 yamt if (is_backlogged && cl->concerned_adc) {
1506 1.1.8.1 yamt if (c[i] != 0) {
1507 1.1.8.1 yamt if (cl->concerned_adc
1508 1.1.8.1 yamt && !cl->concerned_arc)
1509 1.1.8.1 yamt cl->min_rate_adc = k[i]/c[i];
1510 1.1.8.1 yamt else
1511 1.1.8.1 yamt cl->min_rate_adc = n[i];
1512 1.1.8.1 yamt } else
1513 1.1.8.1 yamt cl->min_rate_adc = (int64_t)bps_to_internal((u_int64_t)jif->jif_bandwidth);
1514 1.1.8.1 yamt } else if (is_backlogged && cl->concerned_arc)
1515 1.1.8.1 yamt cl->min_rate_adc = n[i]; /* the best we can give */
1516 1.1.8.1 yamt else {
1517 1.1.8.1 yamt if (class_exists)
1518 1.1.8.1 yamt cl->min_rate_adc = 0;
1519 1.1.8.1 yamt }
1520 1.1.8.1 yamt }
1521 1.1.8.1 yamt
1522 1.1.8.1 yamt free(c, M_DEVBUF);
1523 1.1.8.1 yamt free(n, M_DEVBUF);
1524 1.1.8.1 yamt free(k, M_DEVBUF);
1525 1.1.8.1 yamt free(available, M_DEVBUF);
1526 1.1.8.1 yamt
1527 1.1.8.1 yamt return (result);
1528 1.1.8.1 yamt }
1529 1.1.8.1 yamt
1530 1.1.8.1 yamt /*
1531 1.1.8.1 yamt * update_error: returns the difference between the mean weighted
1532 1.1.8.1 yamt * delay and the weighted delay for each class. if proportional
1533 1.1.8.1 yamt * delay differentiation is perfectly achieved, it should return
1534 1.1.8.1 yamt * zero for each class.
1535 1.1.8.1 yamt */
1536 1.1.8.1 yamt static int64_t *
1537 1.1.8.1 yamt update_error(struct jobs_if *jif)
1538 1.1.8.1 yamt {
1539 1.1.8.1 yamt int i;
1540 1.1.8.1 yamt int active_classes, backlogged_classes;
1541 1.1.8.1 yamt u_int64_t mean_weighted_delay;
1542 1.1.8.1 yamt u_int64_t delays[JOBS_MAXPRI];
1543 1.1.8.1 yamt int64_t* error;
1544 1.1.8.1 yamt int class_exists, is_backlogged;
1545 1.1.8.1 yamt struct jobs_class *cl;
1546 1.1.8.1 yamt
1547 1.1.8.1 yamt error = malloc(sizeof(int64_t)*(jif->jif_maxpri+1), M_DEVBUF,
1548 1.1.8.1 yamt M_WAITOK|M_ZERO);
1549 1.1.8.1 yamt
1550 1.1.8.1 yamt if (error == NULL)
1551 1.1.8.1 yamt return NULL;
1552 1.1.8.1 yamt
1553 1.1.8.1 yamt mean_weighted_delay = 0;
1554 1.1.8.1 yamt active_classes = 0;
1555 1.1.8.1 yamt backlogged_classes = 0;
1556 1.1.8.1 yamt
1557 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1558 1.1.8.1 yamt cl = jif->jif_classes[i];
1559 1.1.8.1 yamt class_exists = (cl != NULL);
1560 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1561 1.1.8.1 yamt
1562 1.1.8.1 yamt if (is_backlogged) {
1563 1.1.8.1 yamt backlogged_classes++;
1564 1.1.8.1 yamt if (cl->concerned_rdc) {
1565 1.1.8.1 yamt delays[i] = proj_delay(jif, i);
1566 1.1.8.1 yamt mean_weighted_delay += cl->delay_prod_others*delays[i];
1567 1.1.8.1 yamt active_classes ++;
1568 1.1.8.1 yamt }
1569 1.1.8.1 yamt }
1570 1.1.8.1 yamt }
1571 1.1.8.1 yamt
1572 1.1.8.1 yamt if (active_classes == 0)
1573 1.1.8.1 yamt return error;
1574 1.1.8.1 yamt else
1575 1.1.8.1 yamt mean_weighted_delay /= active_classes;
1576 1.1.8.1 yamt
1577 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1578 1.1.8.1 yamt cl = jif->jif_classes[i];
1579 1.1.8.1 yamt class_exists = (cl != NULL);
1580 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1581 1.1.8.1 yamt
1582 1.1.8.1 yamt if (is_backlogged && cl->concerned_rdc)
1583 1.1.8.1 yamt error[i] = ((int64_t)mean_weighted_delay)-((int64_t)cl->delay_prod_others*delays[i]);
1584 1.1.8.1 yamt else
1585 1.1.8.1 yamt error[i] = 0; /*
1586 1.1.8.1 yamt * either the class isn't concerned,
1587 1.1.8.1 yamt * or it's not backlogged.
1588 1.1.8.1 yamt * in any case, the rate shouldn't
1589 1.1.8.1 yamt * be adjusted.
1590 1.1.8.1 yamt */
1591 1.1.8.1 yamt }
1592 1.1.8.1 yamt return error;
1593 1.1.8.1 yamt }
1594 1.1.8.1 yamt
1595 1.1.8.1 yamt /*
1596 1.1.8.1 yamt * min_rates_adc: computes the minimum service rates needed in
1597 1.1.8.1 yamt * each class to meet the absolute delay bounds. if, for any
1598 1.1.8.1 yamt * class i, the current service rate of class i is less than
1599 1.1.8.1 yamt * the computed minimum service rate, this function returns
1600 1.1.8.1 yamt * false, true otherwise.
1601 1.1.8.1 yamt */
1602 1.1.8.1 yamt static int
1603 1.1.8.1 yamt min_rates_adc(struct jobs_if *jif)
1604 1.1.8.1 yamt {
1605 1.1.8.1 yamt int result;
1606 1.1.8.1 yamt int i;
1607 1.1.8.1 yamt int class_exists, is_backlogged;
1608 1.1.8.1 yamt int64_t remaining_time;
1609 1.1.8.1 yamt struct jobs_class *cl;
1610 1.1.8.1 yamt result = 1;
1611 1.1.8.1 yamt
1612 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1613 1.1.8.1 yamt cl = jif->jif_classes[i];
1614 1.1.8.1 yamt class_exists = (cl != NULL);
1615 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1616 1.1.8.1 yamt if (is_backlogged && cl->concerned_adc) {
1617 1.1.8.1 yamt remaining_time = cl->cl_adc - proj_delay(jif, i);
1618 1.1.8.1 yamt if (remaining_time > 0 ) {
1619 1.1.8.1 yamt /* min rate needed for ADC */
1620 1.1.8.1 yamt cl->min_rate_adc = scale_rate((int64_t)(cl->cl_rin.bytes-cl->cl_rout.bytes))/remaining_time;
1621 1.1.8.1 yamt if (cl->concerned_arc
1622 1.1.8.1 yamt && cl->cl_arc > cl->min_rate_adc) {
1623 1.1.8.1 yamt /* min rate needed for ADC + ARC */
1624 1.1.8.1 yamt cl->min_rate_adc = cl->cl_arc;
1625 1.1.8.1 yamt }
1626 1.1.8.1 yamt } else {
1627 1.1.8.1 yamt /* the deadline has been exceeded: give the whole link capacity to hopefully fix the situation */
1628 1.1.8.1 yamt cl->min_rate_adc = (int64_t)bps_to_internal((u_int64_t)jif->jif_bandwidth);
1629 1.1.8.1 yamt }
1630 1.1.8.1 yamt } else if (is_backlogged && cl->concerned_arc)
1631 1.1.8.1 yamt cl->min_rate_adc = cl->cl_arc; /* no ADC, an ARC */
1632 1.1.8.1 yamt else if (class_exists)
1633 1.1.8.1 yamt cl->min_rate_adc = 0; /*
1634 1.1.8.1 yamt * either the class is not
1635 1.1.8.1 yamt * backlogged
1636 1.1.8.1 yamt * or there is no ADC and
1637 1.1.8.1 yamt * no ARC
1638 1.1.8.1 yamt */
1639 1.1.8.1 yamt if (is_backlogged && cl->min_rate_adc > cl->service_rate)
1640 1.1.8.1 yamt result = 0;
1641 1.1.8.1 yamt }
1642 1.1.8.1 yamt
1643 1.1.8.1 yamt return result;
1644 1.1.8.1 yamt }
1645 1.1.8.1 yamt
1646 1.1.8.1 yamt /*
1647 1.1.8.1 yamt * proj_delay: computes the difference between the current time
1648 1.1.8.1 yamt * and the time the oldest class-i packet still in the class-i
1649 1.1.8.1 yamt * queue i arrived in the system.
1650 1.1.8.1 yamt */
1651 1.1.8.1 yamt static int64_t
1652 1.1.8.1 yamt proj_delay(struct jobs_if *jif, int i)
1653 1.1.8.1 yamt {
1654 1.1.8.1 yamt u_int64_t now;
1655 1.1.8.1 yamt int class_exists, is_backlogged;
1656 1.1.8.1 yamt struct jobs_class *cl;
1657 1.1.8.1 yamt
1658 1.1.8.1 yamt now = read_machclk();
1659 1.1.8.1 yamt cl = jif->jif_classes[i];
1660 1.1.8.1 yamt class_exists = (cl != NULL);
1661 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1662 1.1.8.1 yamt
1663 1.1.8.1 yamt if (is_backlogged)
1664 1.1.8.1 yamt return ((int64_t)delay_diff(now, tslist_first(cl->arv_tm)->timestamp));
1665 1.1.8.1 yamt
1666 1.1.8.1 yamt return (0); /* NOTREACHED */
1667 1.1.8.1 yamt }
1668 1.1.8.1 yamt
1669 1.1.8.1 yamt /*
1670 1.1.8.1 yamt * pick_dropped_rlc: returns the class index of the class to be
1671 1.1.8.1 yamt * dropped for meeting the relative loss constraints.
1672 1.1.8.1 yamt */
1673 1.1.8.1 yamt static int
1674 1.1.8.1 yamt pick_dropped_rlc(struct jobs_if *jif)
1675 1.1.8.1 yamt {
1676 1.1.8.1 yamt int64_t mean;
1677 1.1.8.1 yamt int64_t* loss_error;
1678 1.1.8.1 yamt int i, active_classes, backlogged_classes;
1679 1.1.8.1 yamt int class_exists, is_backlogged;
1680 1.1.8.1 yamt int class_dropped;
1681 1.1.8.1 yamt int64_t max_error;
1682 1.1.8.1 yamt int64_t max_alc;
1683 1.1.8.1 yamt struct mbuf* pkt;
1684 1.1.8.1 yamt struct jobs_class *cl;
1685 1.1.8.1 yamt u_int64_t len;
1686 1.1.8.1 yamt
1687 1.1.8.1 yamt loss_error = malloc(sizeof(int64_t)*(jif->jif_maxpri+1),
1688 1.1.8.1 yamt M_DEVBUF, M_WAITOK);
1689 1.1.8.1 yamt
1690 1.1.8.1 yamt if (loss_error == NULL)
1691 1.1.8.1 yamt return -1;
1692 1.1.8.1 yamt
1693 1.1.8.1 yamt class_dropped = -1;
1694 1.1.8.1 yamt max_error = 0;
1695 1.1.8.1 yamt mean = 0;
1696 1.1.8.1 yamt active_classes = 0;
1697 1.1.8.1 yamt backlogged_classes = 0;
1698 1.1.8.1 yamt
1699 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1700 1.1.8.1 yamt cl = jif->jif_classes[i];
1701 1.1.8.1 yamt class_exists = (cl != NULL);
1702 1.1.8.1 yamt is_backlogged = (class_exists && !qempty(cl->cl_q));
1703 1.1.8.1 yamt if (is_backlogged) {
1704 1.1.8.1 yamt backlogged_classes ++;
1705 1.1.8.1 yamt if (cl->concerned_rlc) {
1706 1.1.8.1 yamt mean += cl->loss_prod_others
1707 1.1.8.1 yamt * cl->current_loss;
1708 1.1.8.1 yamt active_classes++;
1709 1.1.8.1 yamt }
1710 1.1.8.1 yamt }
1711 1.1.8.1 yamt }
1712 1.1.8.1 yamt
1713 1.1.8.1 yamt if (active_classes > 0)
1714 1.1.8.1 yamt mean /= active_classes;
1715 1.1.8.1 yamt
1716 1.1.8.1 yamt if (active_classes == 0)
1717 1.1.8.1 yamt class_dropped = JOBS_MAXPRI+1; /*
1718 1.1.8.1 yamt * no classes are concerned
1719 1.1.8.1 yamt * by RLCs (JOBS_MAXPRI+1
1720 1.1.8.1 yamt * means "ignore RLC" here)
1721 1.1.8.1 yamt */
1722 1.1.8.1 yamt else {
1723 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1724 1.1.8.1 yamt cl = jif->jif_classes[i];
1725 1.1.8.1 yamt class_exists = (cl != NULL);
1726 1.1.8.1 yamt is_backlogged = (class_exists
1727 1.1.8.1 yamt && !qempty(cl->cl_q));
1728 1.1.8.1 yamt
1729 1.1.8.1 yamt if ((is_backlogged)&&(cl->cl_rlc))
1730 1.1.8.1 yamt loss_error[i]=cl->loss_prod_others
1731 1.1.8.1 yamt *cl->current_loss-mean;
1732 1.1.8.1 yamt else
1733 1.1.8.1 yamt loss_error[i] = INFINITY;
1734 1.1.8.1 yamt }
1735 1.1.8.1 yamt
1736 1.1.8.1 yamt for (i = 0; i <= jif->jif_maxpri; i++) {
1737 1.1.8.1 yamt cl = jif->jif_classes[i];
1738 1.1.8.1 yamt class_exists = (cl != NULL);
1739 1.1.8.1 yamt is_backlogged = (class_exists
1740 1.1.8.1 yamt && !qempty(cl->cl_q));
1741 1.1.8.1 yamt if (is_backlogged && loss_error[i] <= max_error) {
1742 1.1.8.1 yamt /*
1743 1.1.8.1 yamt * find out which class is the most
1744 1.1.8.1 yamt * below the mean.
1745 1.1.8.1 yamt * it's the one that needs to be dropped
1746 1.1.8.1 yamt * ties are broken in favor of the higher
1747 1.1.8.1 yamt * priority classes (i.e., if two classes
1748 1.1.8.1 yamt * present the same deviation, the lower
1749 1.1.8.1 yamt * priority class will get dropped).
1750 1.1.8.1 yamt */
1751 1.1.8.1 yamt max_error = loss_error[i];
1752 1.1.8.1 yamt class_dropped = i;
1753 1.1.8.1 yamt }
1754 1.1.8.1 yamt }
1755 1.1.8.1 yamt
1756 1.1.8.1 yamt if (class_dropped != -1) {
1757 1.1.8.1 yamt cl = jif->jif_classes[class_dropped];
1758 1.1.8.1 yamt pkt = qtail(cl->cl_q);
1759 1.1.8.1 yamt if (pkt != NULL) {
1760 1.1.8.1 yamt /*
1761 1.1.8.1 yamt * "safeguard" test (a packet SHOULD be
1762 1.1.8.1 yamt * in there)
1763 1.1.8.1 yamt */
1764 1.1.8.1 yamt len = (u_int64_t)m_pktlen(pkt);
1765 1.1.8.1 yamt /* access packet at the tail */
1766 1.1.8.1 yamt if (cl->current_loss+(len << SCALE_LOSS)/cl->cl_arrival.bytes > cl->cl_alc) {
1767 1.1.8.1 yamt /*
1768 1.1.8.1 yamt * the class to drop for meeting
1769 1.1.8.1 yamt * the RLC will defeat the ALC:
1770 1.1.8.1 yamt * ignore RLC.
1771 1.1.8.1 yamt */
1772 1.1.8.1 yamt class_dropped = JOBS_MAXPRI+1;
1773 1.1.8.1 yamt }
1774 1.1.8.1 yamt } else
1775 1.1.8.1 yamt class_dropped = JOBS_MAXPRI+1; /* NOTREACHED */
1776 1.1.8.1 yamt } else
1777 1.1.8.1 yamt class_dropped = JOBS_MAXPRI+1;
1778 1.1.8.1 yamt }
1779 1.1.8.1 yamt
1780 1.1.8.1 yamt if (class_dropped == JOBS_MAXPRI+1) {
1781 1.1.8.1 yamt max_alc = -((int64_t)1 << SCALE_LOSS);
1782 1.1.8.1 yamt for (i = jif->jif_maxpri; i >= 0; i--) {
1783 1.1.8.1 yamt cl = jif->jif_classes[i];
1784 1.1.8.1 yamt class_exists = (cl != NULL);
1785 1.1.8.1 yamt is_backlogged = (class_exists
1786 1.1.8.1 yamt && !qempty(cl->cl_q));
1787 1.1.8.1 yamt if (is_backlogged) {
1788 1.1.8.1 yamt if (cl->concerned_alc && cl->cl_alc - cl->current_loss > max_alc) {
1789 1.1.8.1 yamt max_alc = cl->cl_alc-cl->current_loss; /* pick the class which is the furthest from its ALC */
1790 1.1.8.1 yamt class_dropped = i;
1791 1.1.8.1 yamt } else if (!cl->concerned_alc && ((int64_t) 1 << SCALE_LOSS)-cl->current_loss > max_alc) {
1792 1.1.8.1 yamt max_alc = ((int64_t) 1 << SCALE_LOSS)-cl->current_loss;
1793 1.1.8.1 yamt class_dropped = i;
1794 1.1.8.1 yamt }
1795 1.1.8.1 yamt }
1796 1.1.8.1 yamt }
1797 1.1.8.1 yamt }
1798 1.1.8.1 yamt
1799 1.1.8.1 yamt free(loss_error, M_DEVBUF);
1800 1.1.8.1 yamt return (class_dropped);
1801 1.1.8.1 yamt }
1802 1.1.8.1 yamt
1803 1.1.8.1 yamt /*
1804 1.1.8.1 yamt * ALTQ binding/setup functions
1805 1.1.8.1 yamt */
1806 1.1.8.1 yamt /*
1807 1.1.8.1 yamt * jobs device interface
1808 1.1.8.1 yamt */
1809 1.1.8.1 yamt int
1810 1.1.8.2 yamt jobsopen(dev_t dev, int flag, int fmt,
1811 1.1.8.2 yamt struct lwp *l)
1812 1.1.8.1 yamt {
1813 1.1.8.1 yamt if (machclk_freq == 0)
1814 1.1.8.1 yamt init_machclk();
1815 1.1.8.1 yamt
1816 1.1.8.1 yamt if (machclk_freq == 0) {
1817 1.1.8.1 yamt printf("jobs: no CPU clock available!\n");
1818 1.1.8.1 yamt return (ENXIO);
1819 1.1.8.1 yamt }
1820 1.1.8.1 yamt /* everything will be done when the queueing scheme is attached. */
1821 1.1.8.1 yamt return 0;
1822 1.1.8.1 yamt }
1823 1.1.8.1 yamt
1824 1.1.8.1 yamt int
1825 1.1.8.2 yamt jobsclose(dev_t dev, int flag, int fmt,
1826 1.1.8.2 yamt struct lwp *l)
1827 1.1.8.1 yamt {
1828 1.1.8.1 yamt struct jobs_if *jif;
1829 1.1.8.1 yamt int err, error = 0;
1830 1.1.8.1 yamt
1831 1.1.8.1 yamt while ((jif = jif_list) != NULL) {
1832 1.1.8.1 yamt /* destroy all */
1833 1.1.8.1 yamt if (ALTQ_IS_ENABLED(jif->jif_ifq))
1834 1.1.8.1 yamt altq_disable(jif->jif_ifq);
1835 1.1.8.1 yamt
1836 1.1.8.1 yamt err = altq_detach(jif->jif_ifq);
1837 1.1.8.1 yamt if (err == 0)
1838 1.1.8.1 yamt err = jobs_detach(jif);
1839 1.1.8.1 yamt if (err != 0 && error == 0)
1840 1.1.8.1 yamt error = err;
1841 1.1.8.1 yamt }
1842 1.1.8.1 yamt
1843 1.1.8.1 yamt return error;
1844 1.1.8.1 yamt }
1845 1.1.8.1 yamt
1846 1.1.8.1 yamt int
1847 1.1.8.2 yamt jobsioctl(dev_t dev, ioctlcmd_t cmd, caddr_t addr, int flag,
1848 1.1.8.1 yamt struct lwp *l)
1849 1.1.8.1 yamt {
1850 1.1.8.1 yamt struct jobs_if *jif;
1851 1.1.8.1 yamt struct jobs_interface *ifacep;
1852 1.1.8.1 yamt struct proc *p = l->l_proc;
1853 1.1.8.1 yamt int error = 0;
1854 1.1.8.1 yamt
1855 1.1.8.1 yamt /* check super-user privilege */
1856 1.1.8.1 yamt switch (cmd) {
1857 1.1.8.1 yamt case JOBS_GETSTATS:
1858 1.1.8.1 yamt break;
1859 1.1.8.1 yamt default:
1860 1.1.8.1 yamt #if (__FreeBSD_version > 400000)
1861 1.1.8.1 yamt if ((error = suser(p)) != 0)
1862 1.1.8.1 yamt return (error);
1863 1.1.8.1 yamt #else
1864 1.1.8.1 yamt if ((error = kauth_authorize_network(p->p_cred,
1865 1.1.8.1 yamt KAUTH_NETWORK_ALTQ, KAUTH_REQ_NETWORK_ALTQ_JOBS, NULL,
1866 1.1.8.1 yamt NULL, NULL)) != 0)
1867 1.1.8.1 yamt return (error);
1868 1.1.8.1 yamt #endif
1869 1.1.8.1 yamt break;
1870 1.1.8.1 yamt }
1871 1.1.8.1 yamt
1872 1.1.8.1 yamt switch (cmd) {
1873 1.1.8.1 yamt
1874 1.1.8.1 yamt case JOBS_IF_ATTACH:
1875 1.1.8.1 yamt error = jobscmd_if_attach((struct jobs_attach *)addr);
1876 1.1.8.1 yamt break;
1877 1.1.8.1 yamt
1878 1.1.8.1 yamt case JOBS_IF_DETACH:
1879 1.1.8.1 yamt error = jobscmd_if_detach((struct jobs_interface *)addr);
1880 1.1.8.1 yamt break;
1881 1.1.8.1 yamt
1882 1.1.8.1 yamt case JOBS_ENABLE:
1883 1.1.8.1 yamt case JOBS_DISABLE:
1884 1.1.8.1 yamt case JOBS_CLEAR:
1885 1.1.8.1 yamt ifacep = (struct jobs_interface *)addr;
1886 1.1.8.1 yamt if ((jif = altq_lookup(ifacep->jobs_ifname,
1887 1.1.8.1 yamt ALTQT_JOBS)) == NULL) {
1888 1.1.8.1 yamt error = EBADF;
1889 1.1.8.1 yamt break;
1890 1.1.8.1 yamt }
1891 1.1.8.1 yamt
1892 1.1.8.1 yamt switch (cmd) {
1893 1.1.8.1 yamt case JOBS_ENABLE:
1894 1.1.8.1 yamt if (jif->jif_default == NULL) {
1895 1.1.8.1 yamt #if 1
1896 1.1.8.1 yamt printf("jobs: no default class\n");
1897 1.1.8.1 yamt #endif
1898 1.1.8.1 yamt error = EINVAL;
1899 1.1.8.1 yamt break;
1900 1.1.8.1 yamt }
1901 1.1.8.1 yamt error = altq_enable(jif->jif_ifq);
1902 1.1.8.1 yamt break;
1903 1.1.8.1 yamt
1904 1.1.8.1 yamt case JOBS_DISABLE:
1905 1.1.8.1 yamt error = altq_disable(jif->jif_ifq);
1906 1.1.8.1 yamt break;
1907 1.1.8.1 yamt
1908 1.1.8.1 yamt case JOBS_CLEAR:
1909 1.1.8.1 yamt jobs_clear_interface(jif);
1910 1.1.8.1 yamt break;
1911 1.1.8.1 yamt }
1912 1.1.8.1 yamt break;
1913 1.1.8.1 yamt
1914 1.1.8.1 yamt case JOBS_ADD_CLASS:
1915 1.1.8.1 yamt error = jobscmd_add_class((struct jobs_add_class *)addr);
1916 1.1.8.1 yamt break;
1917 1.1.8.1 yamt
1918 1.1.8.1 yamt case JOBS_DEL_CLASS:
1919 1.1.8.1 yamt error = jobscmd_delete_class((struct jobs_delete_class *)addr);
1920 1.1.8.1 yamt break;
1921 1.1.8.1 yamt
1922 1.1.8.1 yamt case JOBS_MOD_CLASS:
1923 1.1.8.1 yamt error = jobscmd_modify_class((struct jobs_modify_class *)addr);
1924 1.1.8.1 yamt break;
1925 1.1.8.1 yamt
1926 1.1.8.1 yamt case JOBS_ADD_FILTER:
1927 1.1.8.1 yamt error = jobscmd_add_filter((struct jobs_add_filter *)addr);
1928 1.1.8.1 yamt break;
1929 1.1.8.1 yamt
1930 1.1.8.1 yamt case JOBS_DEL_FILTER:
1931 1.1.8.1 yamt error = jobscmd_delete_filter((struct jobs_delete_filter *)addr);
1932 1.1.8.1 yamt break;
1933 1.1.8.1 yamt
1934 1.1.8.1 yamt case JOBS_GETSTATS:
1935 1.1.8.1 yamt error = jobscmd_class_stats((struct jobs_class_stats *)addr);
1936 1.1.8.1 yamt break;
1937 1.1.8.1 yamt
1938 1.1.8.1 yamt default:
1939 1.1.8.1 yamt error = EINVAL;
1940 1.1.8.1 yamt break;
1941 1.1.8.1 yamt }
1942 1.1.8.1 yamt return error;
1943 1.1.8.1 yamt }
1944 1.1.8.1 yamt
1945 1.1.8.1 yamt static int
1946 1.1.8.1 yamt jobscmd_if_attach(struct jobs_attach *ap)
1947 1.1.8.1 yamt {
1948 1.1.8.1 yamt struct jobs_if *jif;
1949 1.1.8.1 yamt struct ifnet *ifp;
1950 1.1.8.1 yamt int error;
1951 1.1.8.1 yamt
1952 1.1.8.1 yamt if ((ifp = ifunit(ap->iface.jobs_ifname)) == NULL)
1953 1.1.8.1 yamt return (ENXIO);
1954 1.1.8.1 yamt if ((jif = jobs_attach(&ifp->if_snd, ap->bandwidth, ap->qlimit, ap->separate)) == NULL)
1955 1.1.8.1 yamt return (ENOMEM);
1956 1.1.8.1 yamt
1957 1.1.8.1 yamt /*
1958 1.1.8.1 yamt * set JOBS to this ifnet structure.
1959 1.1.8.1 yamt */
1960 1.1.8.1 yamt if ((error = altq_attach(&ifp->if_snd, ALTQT_JOBS, jif,
1961 1.1.8.1 yamt jobs_enqueue, jobs_dequeue, jobs_request,
1962 1.1.8.1 yamt &jif->jif_classifier, acc_classify)) != 0)
1963 1.1.8.1 yamt (void)jobs_detach(jif);
1964 1.1.8.1 yamt
1965 1.1.8.1 yamt return (error);
1966 1.1.8.1 yamt }
1967 1.1.8.1 yamt
1968 1.1.8.1 yamt static int
1969 1.1.8.1 yamt jobscmd_if_detach(struct jobs_interface *ap)
1970 1.1.8.1 yamt {
1971 1.1.8.1 yamt struct jobs_if *jif;
1972 1.1.8.1 yamt int error;
1973 1.1.8.1 yamt
1974 1.1.8.1 yamt if ((jif = altq_lookup(ap->jobs_ifname, ALTQT_JOBS)) == NULL)
1975 1.1.8.1 yamt return (EBADF);
1976 1.1.8.1 yamt
1977 1.1.8.1 yamt if (ALTQ_IS_ENABLED(jif->jif_ifq))
1978 1.1.8.1 yamt altq_disable(jif->jif_ifq);
1979 1.1.8.1 yamt
1980 1.1.8.1 yamt if ((error = altq_detach(jif->jif_ifq)))
1981 1.1.8.1 yamt return (error);
1982 1.1.8.1 yamt
1983 1.1.8.1 yamt return jobs_detach(jif);
1984 1.1.8.1 yamt }
1985 1.1.8.1 yamt
1986 1.1.8.1 yamt static int
1987 1.1.8.1 yamt jobscmd_add_class(struct jobs_add_class *ap)
1988 1.1.8.1 yamt {
1989 1.1.8.1 yamt struct jobs_if *jif;
1990 1.1.8.1 yamt struct jobs_class *cl;
1991 1.1.8.1 yamt
1992 1.1.8.1 yamt if ((jif = altq_lookup(ap->iface.jobs_ifname, ALTQT_JOBS)) == NULL)
1993 1.1.8.1 yamt return (EBADF);
1994 1.1.8.1 yamt
1995 1.1.8.1 yamt if (ap->pri < 0 || ap->pri >= JOBS_MAXPRI)
1996 1.1.8.1 yamt return (EINVAL);
1997 1.1.8.1 yamt
1998 1.1.8.1 yamt if ((cl = jobs_class_create(jif, ap->pri,
1999 1.1.8.1 yamt ap->cl_adc, ap->cl_rdc,
2000 1.1.8.1 yamt ap->cl_alc, ap->cl_rlc, ap-> cl_arc,
2001 1.1.8.1 yamt ap->flags)) == NULL)
2002 1.1.8.1 yamt return (ENOMEM);
2003 1.1.8.1 yamt
2004 1.1.8.1 yamt /* return a class handle to the user */
2005 1.1.8.1 yamt ap->class_handle = clp_to_clh(cl);
2006 1.1.8.1 yamt return (0);
2007 1.1.8.1 yamt }
2008 1.1.8.1 yamt
2009 1.1.8.1 yamt static int
2010 1.1.8.1 yamt jobscmd_delete_class(struct jobs_delete_class *ap)
2011 1.1.8.1 yamt {
2012 1.1.8.1 yamt struct jobs_if *jif;
2013 1.1.8.1 yamt struct jobs_class *cl;
2014 1.1.8.1 yamt
2015 1.1.8.1 yamt if ((jif = altq_lookup(ap->iface.jobs_ifname, ALTQT_JOBS)) == NULL)
2016 1.1.8.1 yamt return (EBADF);
2017 1.1.8.1 yamt
2018 1.1.8.1 yamt if ((cl = clh_to_clp(jif, ap->class_handle)) == NULL)
2019 1.1.8.1 yamt return (EINVAL);
2020 1.1.8.1 yamt
2021 1.1.8.1 yamt return jobs_class_destroy(cl);
2022 1.1.8.1 yamt }
2023 1.1.8.1 yamt
2024 1.1.8.1 yamt static int
2025 1.1.8.1 yamt jobscmd_modify_class(struct jobs_modify_class *ap)
2026 1.1.8.1 yamt {
2027 1.1.8.1 yamt struct jobs_if *jif;
2028 1.1.8.1 yamt struct jobs_class *cl;
2029 1.1.8.1 yamt
2030 1.1.8.1 yamt if ((jif = altq_lookup(ap->iface.jobs_ifname, ALTQT_JOBS)) == NULL)
2031 1.1.8.1 yamt return (EBADF);
2032 1.1.8.1 yamt
2033 1.1.8.1 yamt if (ap->pri < 0 || ap->pri >= JOBS_MAXPRI)
2034 1.1.8.1 yamt return (EINVAL);
2035 1.1.8.1 yamt
2036 1.1.8.1 yamt if ((cl = clh_to_clp(jif, ap->class_handle)) == NULL)
2037 1.1.8.1 yamt return (EINVAL);
2038 1.1.8.1 yamt
2039 1.1.8.1 yamt /*
2040 1.1.8.1 yamt * if priority is changed, move the class to the new priority
2041 1.1.8.1 yamt */
2042 1.1.8.1 yamt if (jif->jif_classes[ap->pri] != cl) {
2043 1.1.8.1 yamt if (jif->jif_classes[ap->pri] != NULL)
2044 1.1.8.1 yamt return (EEXIST);
2045 1.1.8.1 yamt jif->jif_classes[cl->cl_pri] = NULL;
2046 1.1.8.1 yamt jif->jif_classes[ap->pri] = cl;
2047 1.1.8.1 yamt cl->cl_pri = ap->pri;
2048 1.1.8.1 yamt }
2049 1.1.8.1 yamt
2050 1.1.8.1 yamt /* call jobs_class_create to change class parameters */
2051 1.1.8.1 yamt if ((cl = jobs_class_create(jif, ap->pri,
2052 1.1.8.1 yamt ap->cl_adc, ap->cl_rdc,
2053 1.1.8.1 yamt ap->cl_alc, ap->cl_rlc, ap->cl_arc,
2054 1.1.8.1 yamt ap->flags)) == NULL)
2055 1.1.8.1 yamt return (ENOMEM);
2056 1.1.8.1 yamt return 0;
2057 1.1.8.1 yamt }
2058 1.1.8.1 yamt
2059 1.1.8.1 yamt static int
2060 1.1.8.1 yamt jobscmd_add_filter(struct jobs_add_filter *ap)
2061 1.1.8.1 yamt {
2062 1.1.8.1 yamt struct jobs_if *jif;
2063 1.1.8.1 yamt struct jobs_class *cl;
2064 1.1.8.1 yamt
2065 1.1.8.1 yamt if ((jif = altq_lookup(ap->iface.jobs_ifname, ALTQT_JOBS)) == NULL)
2066 1.1.8.1 yamt return (EBADF);
2067 1.1.8.1 yamt
2068 1.1.8.1 yamt if ((cl = clh_to_clp(jif, ap->class_handle)) == NULL)
2069 1.1.8.1 yamt return (EINVAL);
2070 1.1.8.1 yamt
2071 1.1.8.1 yamt return acc_add_filter(&jif->jif_classifier, &ap->filter,
2072 1.1.8.1 yamt cl, &ap->filter_handle);
2073 1.1.8.1 yamt }
2074 1.1.8.1 yamt
2075 1.1.8.1 yamt static int
2076 1.1.8.1 yamt jobscmd_delete_filter(struct jobs_delete_filter *ap)
2077 1.1.8.1 yamt {
2078 1.1.8.1 yamt struct jobs_if *jif;
2079 1.1.8.1 yamt
2080 1.1.8.1 yamt if ((jif = altq_lookup(ap->iface.jobs_ifname, ALTQT_JOBS)) == NULL)
2081 1.1.8.1 yamt return (EBADF);
2082 1.1.8.1 yamt
2083 1.1.8.1 yamt return acc_delete_filter(&jif->jif_classifier, ap->filter_handle);
2084 1.1.8.1 yamt }
2085 1.1.8.1 yamt
2086 1.1.8.1 yamt static int
2087 1.1.8.1 yamt jobscmd_class_stats(struct jobs_class_stats *ap)
2088 1.1.8.1 yamt {
2089 1.1.8.1 yamt struct jobs_if *jif;
2090 1.1.8.1 yamt struct jobs_class *cl;
2091 1.1.8.1 yamt struct class_stats stats, *usp;
2092 1.1.8.1 yamt int pri, error;
2093 1.1.8.1 yamt
2094 1.1.8.1 yamt if ((jif = altq_lookup(ap->iface.jobs_ifname, ALTQT_JOBS)) == NULL)
2095 1.1.8.1 yamt return (EBADF);
2096 1.1.8.1 yamt
2097 1.1.8.1 yamt ap->maxpri = jif->jif_maxpri;
2098 1.1.8.1 yamt
2099 1.1.8.1 yamt /* then, read the next N classes */
2100 1.1.8.1 yamt usp = ap->stats;
2101 1.1.8.1 yamt for (pri = 0; pri <= jif->jif_maxpri; pri++) {
2102 1.1.8.1 yamt cl = jif->jif_classes[pri];
2103 1.1.8.1 yamt if (cl != NULL)
2104 1.1.8.1 yamt get_class_stats(&stats, cl);
2105 1.1.8.1 yamt else
2106 1.1.8.1 yamt (void)memset(&stats, 0, sizeof(stats));
2107 1.1.8.1 yamt if ((error = copyout((caddr_t)&stats, (caddr_t)usp++,
2108 1.1.8.1 yamt sizeof(stats))) != 0)
2109 1.1.8.1 yamt return (error);
2110 1.1.8.1 yamt }
2111 1.1.8.1 yamt return (0);
2112 1.1.8.1 yamt }
2113 1.1.8.1 yamt
2114 1.1.8.1 yamt static void
2115 1.1.8.1 yamt get_class_stats(struct class_stats *sp, struct jobs_class *cl)
2116 1.1.8.1 yamt {
2117 1.1.8.1 yamt u_int64_t now;
2118 1.1.8.1 yamt now = read_machclk();
2119 1.1.8.1 yamt
2120 1.1.8.1 yamt sp->class_handle = clp_to_clh(cl);
2121 1.1.8.1 yamt sp->qlength = qlen(cl->cl_q);
2122 1.1.8.1 yamt
2123 1.1.8.1 yamt sp->period = cl->cl_period;
2124 1.1.8.1 yamt sp->rin = cl->st_rin;
2125 1.1.8.1 yamt sp->arrival = cl->st_arrival;
2126 1.1.8.1 yamt sp->arrivalbusy = cl->cl_arrival;
2127 1.1.8.1 yamt sp->rout = cl->st_rout;
2128 1.1.8.1 yamt sp->dropcnt = cl->cl_dropcnt;
2129 1.1.8.1 yamt
2130 1.1.8.1 yamt /* PKTCNTR_RESET(&cl->st_arrival);*/
2131 1.1.8.1 yamt PKTCNTR_RESET(&cl->st_rin);
2132 1.1.8.1 yamt PKTCNTR_RESET(&cl->st_rout);
2133 1.1.8.1 yamt
2134 1.1.8.1 yamt sp->totallength = cl->cl_jif->jif_ifq->ifq_len;
2135 1.1.8.1 yamt sp->lastdel = ticks_to_secs(GRANULARITY*cl->cl_lastdel);
2136 1.1.8.1 yamt sp->avgdel = cl->cl_avgdel;
2137 1.1.8.1 yamt
2138 1.1.8.1 yamt cl->cl_avgdel = 0;
2139 1.1.8.1 yamt
2140 1.1.8.1 yamt sp->busylength = ticks_to_secs(1000*delay_diff(now, cl->idletime));
2141 1.1.8.1 yamt sp->adc_violations = cl->adc_violations;
2142 1.1.8.1 yamt
2143 1.1.8.1 yamt sp->wc_cycles_enqueue = cl->cl_jif->wc_cycles_enqueue;
2144 1.1.8.1 yamt sp->wc_cycles_dequeue = cl->cl_jif->wc_cycles_dequeue;
2145 1.1.8.1 yamt sp->bc_cycles_enqueue = cl->cl_jif->bc_cycles_enqueue;
2146 1.1.8.1 yamt sp->bc_cycles_dequeue = cl->cl_jif->bc_cycles_dequeue;
2147 1.1.8.1 yamt sp->avg_cycles_enqueue = cl->cl_jif->avg_cycles_enqueue;
2148 1.1.8.1 yamt sp->avg_cycles_dequeue = cl->cl_jif->avg_cycles_dequeue;
2149 1.1.8.1 yamt sp->avg_cycles2_enqueue = cl->cl_jif->avg_cycles2_enqueue;
2150 1.1.8.1 yamt sp->avg_cycles2_dequeue = cl->cl_jif->avg_cycles2_dequeue;
2151 1.1.8.1 yamt sp->total_enqueued = cl->cl_jif->total_enqueued;
2152 1.1.8.1 yamt sp->total_dequeued = cl->cl_jif->total_dequeued;
2153 1.1.8.1 yamt }
2154 1.1.8.1 yamt
2155 1.1.8.1 yamt /* convert a class handle to the corresponding class pointer */
2156 1.1.8.1 yamt static struct jobs_class *
2157 1.1.8.1 yamt clh_to_clp(struct jobs_if *jif, u_long chandle)
2158 1.1.8.1 yamt {
2159 1.1.8.1 yamt struct jobs_class *cl;
2160 1.1.8.1 yamt
2161 1.1.8.1 yamt cl = (struct jobs_class *)chandle;
2162 1.1.8.1 yamt if (chandle != ALIGN(cl)) {
2163 1.1.8.1 yamt #if 1
2164 1.1.8.1 yamt printf("clh_to_cl: unaligned pointer %p\n", cl);
2165 1.1.8.1 yamt #endif
2166 1.1.8.1 yamt return (NULL);
2167 1.1.8.1 yamt }
2168 1.1.8.1 yamt
2169 1.1.8.1 yamt if (cl == NULL || cl->cl_handle != chandle || cl->cl_jif != jif)
2170 1.1.8.1 yamt return (NULL);
2171 1.1.8.1 yamt return (cl);
2172 1.1.8.1 yamt }
2173 1.1.8.1 yamt
2174 1.1.8.1 yamt /* convert a class pointer to the corresponding class handle */
2175 1.1.8.1 yamt static u_long
2176 1.1.8.1 yamt clp_to_clh(struct jobs_class *cl)
2177 1.1.8.1 yamt {
2178 1.1.8.1 yamt return (cl->cl_handle);
2179 1.1.8.1 yamt }
2180 1.1.8.1 yamt
2181 1.1.8.1 yamt #ifdef KLD_MODULE
2182 1.1.8.1 yamt
2183 1.1.8.1 yamt static struct altqsw jobs_sw =
2184 1.1.8.1 yamt {"jobs", jobsopen, jobsclose, jobsioctl};
2185 1.1.8.1 yamt
2186 1.1.8.1 yamt ALTQ_MODULE(altq_jobs, ALTQT_JOBS, &jobs_sw);
2187 1.1.8.1 yamt
2188 1.1.8.1 yamt #endif /* KLD_MODULE */
2189 1.1.8.1 yamt
2190 1.1.8.1 yamt #endif /* ALTQ3_COMPAT */
2191 1.1.8.1 yamt #endif /* ALTQ_JOBS */
2192