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