1 /* $KAME: qop_jobs.c,v 1.2 2002/10/26 07:09:22 kjc Exp $ */
2 /*
3 * Copyright (c) 2001-2002, by the Rector and Board of Visitors of
4 * the University of Virginia.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms,
8 * with or without modification, are permitted provided
9 * that the following conditions are met:
10 *
11 * Redistributions of source code must retain the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 *
20 * Neither the name of the University of Virginia nor the names
21 * of its contributors may be used to endorse or promote products
22 * derived from this software without specific prior written
23 * permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
26 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
27 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37 * THE POSSIBILITY OF SUCH DAMAGE.
38 */
39 /*
40 * Copyright (C) 1999-2000
41 * Sony Computer Science Laboratories, Inc. All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 *
52 * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 */
64 /*
65 * JoBS - altq prototype implementation
66 *
67 * Author: Nicolas Christin <nicolas@cs.virginia.edu>
68 *
69 * JoBS algorithms originally devised and proposed by
70 * Nicolas Christin and Jorg Liebeherr.
71 * Grateful Acknowledgments to Tarek Abdelzaher for his help and
72 * comments, and to Kenjiro Cho for some helpful advice.
73 * Contributed by the Multimedia Networks Group at the University
74 * of Virginia.
75 *
76 * http://qosbox.cs.virginia.edu
77 *
78 */
79
80 #include <sys/param.h>
81 #include <sys/socket.h>
82 #include <sys/sockio.h>
83 #include <sys/ioctl.h>
84 #include <sys/fcntl.h>
85 #include <net/if.h>
86 #include <netinet/in.h>
87 #include <arpa/inet.h>
88
89 #include <stdio.h>
90 #include <stdlib.h>
91 #include <unistd.h>
92 #include <stddef.h>
93 #include <string.h>
94 #include <ctype.h>
95 #include <errno.h>
96 #include <syslog.h>
97 #include <netdb.h>
98
99 #include <altq/altq.h>
100 #include <altq/altq_var.h>
101 #include <altq/altq_jobs.h>
102 #include "altq_qop.h"
103 #include "qop_jobs.h"
104 #define SCALE_LOSS 32
105
106 #if 0
107 static int qop_jobs_enable_hook(struct ifinfo *);
108 #endif
109 static int qop_jobs_delete_class_hook(struct classinfo *);
110
111 static int jobs_attach(struct ifinfo *);
112 static int jobs_detach(struct ifinfo *);
113 static int jobs_clear(struct ifinfo *);
114 static int jobs_enable(struct ifinfo *);
115 static int jobs_disable(struct ifinfo *);
116 static int jobs_add_class(struct classinfo *);
117 static int jobs_modify_class(struct classinfo *, void *);
118 static int jobs_delete_class(struct classinfo *);
119 static int jobs_add_filter(struct fltrinfo *);
120 static int jobs_delete_filter(struct fltrinfo *);
121
122 #define JOBS_DEVICE "/dev/altq/jobs"
123
124 static int jobs_fd = -1;
125 static int jobs_refcount = 0;
126
127 static struct qdisc_ops jobs_qdisc = {
128 ALTQT_JOBS,
129 "jobs",
130 jobs_attach,
131 jobs_detach,
132 jobs_clear,
133 jobs_enable,
134 jobs_disable,
135 jobs_add_class,
136 jobs_modify_class,
137 jobs_delete_class,
138 jobs_add_filter,
139 jobs_delete_filter
140 };
141
142 /*
143 * parser interface
144 */
145 #define EQUAL(s1, s2) (strcmp((s1), (s2)) == 0)
146
147 int
jobs_interface_parser(const char * ifname,int argc,char ** argv)148 jobs_interface_parser(const char *ifname, int argc, char **argv)
149 {
150 u_int bandwidth = 100000000; /* 100 Mbps */
151 u_int tbrsize = 0;
152 int qlimit = 200; /* 200 packets */
153 int separate = 0; /* by default: shared buffer */
154
155 /*
156 * process options
157 */
158 while (argc > 0) {
159 if (EQUAL(*argv, "bandwidth")) {
160 argc--; argv++;
161 if (argc > 0)
162 bandwidth = atobps(*argv);
163 } else if (EQUAL(*argv, "tbrsize")) {
164 argc--; argv++;
165 if (argc > 0)
166 tbrsize = atobytes(*argv);
167 } else if (EQUAL(*argv, "qlimit")) {
168 argc--; argv++;
169 if (argc > 0)
170 qlimit = (int)strtol(*argv, NULL, 0);
171 } else if (EQUAL(*argv, "separate")) {
172 argc--; argv++;
173 separate = 1;
174 } else if (EQUAL(*argv, "jobs")) {
175 /* just skip */
176 } else {
177 LOG(LOG_ERR, 0, "Unknown keyword '%s'", *argv);
178 return (0);
179 }
180 argc--; argv++;
181 }
182
183 if (qcmd_tbr_register(ifname, bandwidth, tbrsize) != 0)
184 return (0);
185
186 if (qcmd_jobs_add_if(ifname, bandwidth, qlimit, separate) != 0)
187 return (0);
188 return (1);
189 }
190
191 int
jobs_class_parser(const char * ifname,const char * class_name,const char * parent_name,int argc,char ** argv)192 jobs_class_parser(const char *ifname, const char *class_name,
193 const char *parent_name, int argc, char **argv)
194 {
195 int64_t adc, rdc, alc, rlc, arc;
196 int pri = 0;
197 int flags = 0;
198 int error;
199
200 /* disable everything by default */
201 adc = -1;
202 rdc = -1;
203 arc = -1;
204 alc = -1;
205 rlc = -1;
206
207 while (argc > 0) {
208 if (EQUAL(*argv, "priority")) {
209 argc--; argv++;
210 if (argc > 0) {
211 if (strtol(*argv, NULL, 0) < 0)
212 pri = 0;
213 else
214 pri = strtol(*argv, NULL, 0);
215 }
216 } else if (EQUAL(*argv, "adc")) {
217 argc--; argv++;
218 if (argc > 0) {
219 if (strtol(*argv, NULL, 0) < 0)
220 adc = -1;
221 else
222 adc = strtol(*argv, NULL, 0);
223 }
224 } else if (EQUAL(*argv, "rdc")) {
225 argc--; argv++;
226 if (argc > 0) {
227 if (strtol(*argv, NULL, 0) < 0)
228 rdc = -1;
229 else
230 rdc = strtol(*argv, NULL, 0);
231 }
232 } else if (EQUAL(*argv, "alc")) {
233 argc--; argv++;
234 if (argc > 0) {
235 if (strtol(*argv, NULL, 0) < 0)
236 alc = -1;
237 else
238 alc = (int64_t)(strtod(*argv, NULL)
239 * ((int64_t)1 << SCALE_LOSS));
240 /*
241 * alc is given in fraction of 1, convert it
242 * to a fraction of 2^(SCALE_LOSS)
243 */
244 }
245 } else if (EQUAL(*argv, "rlc")) {
246 argc--; argv++;
247 if (argc > 0) {
248 if (strtol(*argv, NULL, 0) < 0)
249 rlc = -1;
250 else
251 rlc = strtol(*argv, NULL, 0);
252 }
253 } else if (EQUAL(*argv, "arc")) {
254 argc--; argv++;
255 if (argc > 0) {
256 if (EQUAL(*argv,"-1"))
257 arc = -1;
258 else
259 arc = atobps(*argv);
260 }
261 } else if (EQUAL(*argv, "default")) {
262 flags |= JOCF_DEFAULTCLASS;
263 } else {
264 LOG(LOG_ERR, 0,
265 "Unknown keyword '%s' in %s, line %d",
266 *argv, altqconfigfile, line_no);
267 return (0);
268 }
269 argc--; argv++;
270 }
271
272 error = qcmd_jobs_add_class(ifname, class_name, pri,
273 adc, rdc, alc, rlc, arc, flags);
274
275 if (error) {
276 LOG(LOG_ERR, errno, "jobs_class_parser: %s",
277 qoperror(error));
278 return (0);
279 }
280 return (1);
281 }
282
283 /*
284 * qcmd api
285 */
286 int
qcmd_jobs_add_if(const char * ifname,u_int bandwidth,int qlimit,int separate)287 qcmd_jobs_add_if(const char *ifname, u_int bandwidth, int qlimit, int separate)
288 {
289 int error;
290
291 error = qop_jobs_add_if(NULL, ifname, bandwidth, qlimit, separate);
292 if (error != 0)
293 LOG(LOG_ERR, errno, "%s: can't add jobs on interface '%s'",
294 qoperror(error), ifname);
295 return (error);
296 }
297
298 int
qcmd_jobs_add_class(const char * ifname,const char * class_name,int pri,int64_t adc,int64_t rdc,int64_t alc,int64_t rlc,int64_t arc,int flags)299 qcmd_jobs_add_class(const char *ifname, const char *class_name, int pri,
300 int64_t adc, int64_t rdc, int64_t alc, int64_t rlc, int64_t arc,
301 int flags)
302 {
303 struct ifinfo *ifinfo;
304 int error = 0;
305 char name_adc[20],name_alc[20],name_rdc[20],name_rlc[20],name_arc[20];
306
307 if ((ifinfo = ifname2ifinfo(ifname)) == NULL)
308 error = QOPERR_BADIF;
309 if (error == 0)
310 error = qop_jobs_add_class(NULL, class_name, ifinfo,
311 pri, adc, rdc, alc, rlc, arc, flags);
312 if (error != 0)
313 LOG(LOG_ERR, errno,
314 "jobs: %s: can't add class '%s' on interface '%s'",
315 qoperror(error), class_name, ifname);
316 else {
317 if (adc > 0)
318 sprintf(name_adc,"%.3f ms",(double)adc/1000.);
319 else
320 sprintf(name_adc,"N/A");
321 if (alc > 0)
322 sprintf(name_alc,"%.2f%%",
323 (double)100*alc/((u_int64_t)1 << SCALE_LOSS));
324 else
325 sprintf(name_alc,"N/A");
326 if (rdc > 0)
327 sprintf(name_rdc,"%d",(int)rdc);
328 else
329 sprintf(name_rdc,"N/A");
330 if (rlc > 0)
331 sprintf(name_rlc,"%d",(int)rlc);
332 else
333 sprintf(name_rlc,"N/A");
334 if (arc > 0)
335 sprintf(name_arc,"%.2f Mbps",(double)arc/1000000.);
336 else
337 sprintf(name_arc,"N/A");
338
339 LOG(LOG_INFO, 0,
340 "added '%s' (pri=%d,adc=%s,rdc=%s,alc=%s,rlc=%s,arc=%s) on interface '%s'\n",
341 class_name,pri,name_adc,name_rdc,name_alc,name_rlc,name_arc,ifname);
342 }
343 return (error);
344 }
345
346 int
qcmd_jobs_modify_class(const char * ifname,const char * class_name,int pri,int64_t adc,int64_t rdc,int64_t alc,int64_t rlc,int64_t arc)347 qcmd_jobs_modify_class(const char *ifname, const char *class_name, int pri,
348 int64_t adc, int64_t rdc, int64_t alc, int64_t rlc, int64_t arc)
349 {
350 struct ifinfo *ifinfo;
351 struct classinfo *clinfo;
352
353 if ((ifinfo = ifname2ifinfo(ifname)) == NULL)
354 return (QOPERR_BADIF);
355
356 if ((clinfo = clname2clinfo(ifinfo, class_name)) == NULL)
357 return (QOPERR_BADCLASS);
358
359 return qop_jobs_modify_class(clinfo, pri, adc, rdc, alc, rlc, arc);
360 }
361
362 /*
363 * qop api
364 */
365 int
qop_jobs_add_if(struct ifinfo ** rp,const char * ifname,u_int bandwidth,int qlimit,int separate)366 qop_jobs_add_if(struct ifinfo **rp, const char *ifname,
367 u_int bandwidth, int qlimit, int separate)
368 {
369 struct ifinfo *ifinfo = NULL;
370 struct jobs_ifinfo *jobs_ifinfo;
371 int error;
372
373 if ((jobs_ifinfo = calloc(1, sizeof(*jobs_ifinfo))) == NULL)
374 return (QOPERR_NOMEM);
375 jobs_ifinfo->qlimit = qlimit;
376 jobs_ifinfo->separate = separate;
377
378 error = qop_add_if(&ifinfo, ifname, bandwidth,
379 &jobs_qdisc, jobs_ifinfo);
380 if (error != 0) {
381 free(jobs_ifinfo);
382 return (error);
383 }
384
385 if (rp != NULL)
386 *rp = ifinfo;
387 return (0);
388 }
389
390 int
qop_jobs_add_class(struct classinfo ** rp,const char * class_name,struct ifinfo * ifinfo,int pri,int64_t adc,int64_t rdc,int64_t alc,int64_t rlc,int64_t arc,int flags)391 qop_jobs_add_class(struct classinfo **rp, const char *class_name,
392 struct ifinfo *ifinfo, int pri,
393 int64_t adc, int64_t rdc, int64_t alc, int64_t rlc, int64_t arc,
394 int flags)
395 {
396 struct classinfo *clinfo;
397 struct jobs_ifinfo *jobs_ifinfo;
398 struct jobs_classinfo *jobs_clinfo = NULL;
399 int error;
400
401 jobs_ifinfo = ifinfo->private;
402 if ((flags & JOCF_DEFAULTCLASS) && jobs_ifinfo->default_class != NULL)
403 return (QOPERR_CLASS_INVAL);
404
405 if ((jobs_clinfo = calloc(1, sizeof(*jobs_clinfo))) == NULL) {
406 error = QOPERR_NOMEM;
407 goto err_ret;
408 }
409
410 jobs_clinfo->pri = pri;
411 jobs_clinfo->adc = adc;
412 jobs_clinfo->rdc = rdc;
413 jobs_clinfo->alc = alc;
414 jobs_clinfo->rlc = rlc;
415 jobs_clinfo->arc = arc;
416 jobs_clinfo->flags = flags;
417
418 if ((error = qop_add_class(&clinfo, class_name, ifinfo, NULL,
419 jobs_clinfo)) != 0)
420 goto err_ret;
421
422 /* set delete hook */
423 clinfo->delete_hook = qop_jobs_delete_class_hook;
424
425 if (flags & JOCF_DEFAULTCLASS)
426 jobs_ifinfo->default_class = clinfo;
427
428 if (rp != NULL)
429 *rp = clinfo;
430 return (0);
431
432 err_ret:
433 if (jobs_clinfo != NULL) {
434 free(jobs_clinfo);
435 clinfo->private = NULL;
436 }
437
438 return (error);
439 }
440
441 /*
442 * this is called from qop_delete_class() before a class is destroyed
443 * for discipline specific cleanup.
444 */
445 static int
qop_jobs_delete_class_hook(struct classinfo * clinfo)446 qop_jobs_delete_class_hook(struct classinfo *clinfo)
447 {
448 /* in fact this function doesn't do anything
449 * i'm not sure how/when it's used, so I just
450 * leave it here
451 */
452 return (0);
453 }
454
455 int
qop_jobs_modify_class(struct classinfo * clinfo,int pri,int64_t adc,int64_t rdc,int64_t alc,int64_t rlc,int64_t arc)456 qop_jobs_modify_class(struct classinfo *clinfo, int pri,
457 int64_t adc, int64_t rdc, int64_t alc, int64_t rlc, int64_t arc)
458 {
459 struct jobs_classinfo *jobs_clinfo = clinfo->private;
460 int error;
461 int pri_old;
462 int64_t adc_old, rdc_old, alc_old, rlc_old, arc_old;
463
464 pri_old = jobs_clinfo->pri;
465 adc_old = jobs_clinfo->adc;
466 rdc_old = jobs_clinfo->rdc;
467 alc_old = jobs_clinfo->alc;
468 rlc_old = jobs_clinfo->rlc;
469 arc_old = jobs_clinfo->arc;
470
471 jobs_clinfo = clinfo->private;
472 jobs_clinfo->adc = adc;
473 jobs_clinfo->rdc = rdc;
474 jobs_clinfo->alc = alc;
475 jobs_clinfo->rlc = rlc;
476 jobs_clinfo->arc = arc;
477 jobs_clinfo->pri = pri;
478
479 error = qop_modify_class(clinfo, NULL);
480 if (error == 0)
481 return (0);
482
483 /* modify failed!, restore the old service guarantees */
484 jobs_clinfo->adc = adc_old;
485 jobs_clinfo->rdc = rdc_old;
486 jobs_clinfo->alc = alc_old;
487 jobs_clinfo->rlc = rlc_old;
488 jobs_clinfo->arc = arc_old;
489 jobs_clinfo->pri = pri_old;
490 return (error);
491 }
492
493 #if 0
494 /*
495 * sanity check at enabling jobs:
496 * there must one default class for an interface
497 */
498 static int
499 qop_jobs_enable_hook(struct ifinfo *ifinfo)
500 {
501 struct jobs_ifinfo *jobs_ifinfo;
502
503 jobs_ifinfo = ifinfo->private;
504 if (jobs_ifinfo->default_class == NULL) {
505 LOG(LOG_ERR, 0, "jobs: no default class on interface %s!",
506 ifinfo->ifname);
507 return (QOPERR_CLASS);
508 }
509 return (0);
510 }
511 #endif
512
513 /*
514 * system call interfaces for qdisc_ops
515 */
516 static int
jobs_attach(struct ifinfo * ifinfo)517 jobs_attach(struct ifinfo *ifinfo)
518 {
519 struct jobs_attach attach;
520
521 if (jobs_fd < 0 &&
522 (jobs_fd = open(JOBS_DEVICE, O_RDWR)) < 0 &&
523 (jobs_fd = open_module(JOBS_DEVICE, O_RDWR)) < 0) {
524 LOG(LOG_ERR, errno, "JOBS open");
525 return (QOPERR_SYSCALL);
526 }
527
528 jobs_refcount++;
529 memset(&attach, 0, sizeof(attach));
530 strncpy(attach.iface.jobs_ifname, ifinfo->ifname, IFNAMSIZ);
531 attach.bandwidth = ifinfo->bandwidth;
532 attach.qlimit = (u_int)((struct jobs_ifinfo*)ifinfo->private)->qlimit;
533 attach.separate = (u_int)((struct jobs_ifinfo*)ifinfo->private)->separate;
534
535 if (ioctl(jobs_fd, JOBS_IF_ATTACH, (struct jobs_attach*) &attach) < 0)
536 return (QOPERR_SYSCALL);
537
538 #if 1
539 LOG(LOG_INFO, 0,
540 "jobs attached to %s (b/w = %d bps, buff = %d pkts [%s])\n",
541 attach.iface.jobs_ifname,
542 (int) attach.bandwidth, (int) attach.qlimit,
543 attach.separate?"separate buffers":"shared buffer");
544 #endif
545 return (0);
546 }
547
548 static int
jobs_detach(struct ifinfo * ifinfo)549 jobs_detach(struct ifinfo *ifinfo)
550 {
551 struct jobs_interface iface;
552
553 memset(&iface, 0, sizeof(iface));
554 strncpy(iface.jobs_ifname, ifinfo->ifname, IFNAMSIZ);
555
556 if (ioctl(jobs_fd, JOBS_IF_DETACH, &iface) < 0)
557 return (QOPERR_SYSCALL);
558
559 if (--jobs_refcount == 0) {
560 close(jobs_fd);
561 jobs_fd = -1;
562 }
563 return (0);
564 }
565
566 static int
jobs_enable(struct ifinfo * ifinfo)567 jobs_enable(struct ifinfo *ifinfo)
568 {
569 struct jobs_interface iface;
570
571 memset(&iface, 0, sizeof(iface));
572 strncpy(iface.jobs_ifname, ifinfo->ifname, IFNAMSIZ);
573
574 if (ioctl(jobs_fd, JOBS_ENABLE, &iface) < 0)
575 return (QOPERR_SYSCALL);
576 return (0);
577 }
578
579 static int
jobs_disable(struct ifinfo * ifinfo)580 jobs_disable(struct ifinfo *ifinfo)
581 {
582 struct jobs_interface iface;
583
584 memset(&iface, 0, sizeof(iface));
585 strncpy(iface.jobs_ifname, ifinfo->ifname, IFNAMSIZ);
586
587 if (ioctl(jobs_fd, JOBS_DISABLE, &iface) < 0)
588 return (QOPERR_SYSCALL);
589 return (0);
590 }
591
592 static int
jobs_clear(struct ifinfo * ifinfo)593 jobs_clear(struct ifinfo *ifinfo)
594 {
595 struct jobs_interface iface;
596
597 memset(&iface, 0, sizeof(iface));
598 strncpy(iface.jobs_ifname, ifinfo->ifname, IFNAMSIZ);
599
600 if (ioctl(jobs_fd, JOBS_CLEAR, &iface) < 0)
601 return (QOPERR_SYSCALL);
602 return (0);
603 }
604
605 static int
jobs_add_class(struct classinfo * clinfo)606 jobs_add_class(struct classinfo *clinfo)
607 {
608 struct jobs_add_class class_add;
609 struct jobs_classinfo *jobs_clinfo;
610
611 jobs_clinfo = clinfo->private;
612
613 memset(&class_add, 0, sizeof(class_add));
614 strncpy(class_add.iface.jobs_ifname, clinfo->ifinfo->ifname, IFNAMSIZ);
615 class_add.pri = jobs_clinfo->pri;
616 class_add.cl_adc = jobs_clinfo->adc;
617 class_add.cl_rdc = jobs_clinfo->rdc;
618 class_add.cl_alc = jobs_clinfo->alc;
619 class_add.cl_rlc = jobs_clinfo->rlc;
620 class_add.cl_arc = jobs_clinfo->arc;
621 class_add.flags = jobs_clinfo->flags;
622 if (ioctl(jobs_fd, JOBS_ADD_CLASS, &class_add) < 0) {
623 clinfo->handle = JOBS_NULLCLASS_HANDLE;
624 return (QOPERR_SYSCALL);
625 }
626 clinfo->handle = class_add.class_handle;
627 return (0);
628 }
629
630 static int
jobs_modify_class(struct classinfo * clinfo,void * arg)631 jobs_modify_class(struct classinfo *clinfo, void *arg)
632 {
633 struct jobs_modify_class class_mod;
634 struct jobs_classinfo *jobs_clinfo;
635
636 jobs_clinfo = clinfo->private;
637
638 memset(&class_mod, 0, sizeof(class_mod));
639 strncpy(class_mod.iface.jobs_ifname, clinfo->ifinfo->ifname, IFNAMSIZ);
640 class_mod.class_handle = clinfo->handle;
641
642 class_mod.pri = jobs_clinfo->pri;
643 class_mod.cl_adc = jobs_clinfo->adc;
644 class_mod.cl_rdc = jobs_clinfo->rdc;
645 class_mod.cl_alc = jobs_clinfo->alc;
646 class_mod.cl_rlc = jobs_clinfo->rlc;
647 class_mod.cl_arc = jobs_clinfo->arc;
648 class_mod.flags = jobs_clinfo->flags;
649
650 if (ioctl(jobs_fd, JOBS_MOD_CLASS, &class_mod) < 0)
651 return (QOPERR_SYSCALL);
652 return (0);
653 }
654
655 static int
jobs_delete_class(struct classinfo * clinfo)656 jobs_delete_class(struct classinfo *clinfo)
657 {
658 struct jobs_delete_class class_delete;
659
660 if (clinfo->handle == JOBS_NULLCLASS_HANDLE)
661 return (0);
662
663 memset(&class_delete, 0, sizeof(class_delete));
664 strncpy(class_delete.iface.jobs_ifname, clinfo->ifinfo->ifname,
665 IFNAMSIZ);
666 class_delete.class_handle = clinfo->handle;
667
668 if (ioctl(jobs_fd, JOBS_DEL_CLASS, &class_delete) < 0)
669 return (QOPERR_SYSCALL);
670 return (0);
671 }
672
673 static int
jobs_add_filter(struct fltrinfo * fltrinfo)674 jobs_add_filter(struct fltrinfo *fltrinfo)
675 {
676 struct jobs_add_filter fltr_add;
677
678 memset(&fltr_add, 0, sizeof(fltr_add));
679 strncpy(fltr_add.iface.jobs_ifname, fltrinfo->clinfo->ifinfo->ifname,
680 IFNAMSIZ);
681 fltr_add.class_handle = fltrinfo->clinfo->handle;
682 fltr_add.filter = fltrinfo->fltr;
683
684 if (ioctl(jobs_fd, JOBS_ADD_FILTER, &fltr_add) < 0)
685 return (QOPERR_SYSCALL);
686 fltrinfo->handle = fltr_add.filter_handle;
687 return (0);
688 }
689
690 static int
jobs_delete_filter(struct fltrinfo * fltrinfo)691 jobs_delete_filter(struct fltrinfo *fltrinfo)
692 {
693 struct jobs_delete_filter fltr_del;
694
695 memset(&fltr_del, 0, sizeof(fltr_del));
696 strncpy(fltr_del.iface.jobs_ifname, fltrinfo->clinfo->ifinfo->ifname,
697 IFNAMSIZ);
698 fltr_del.filter_handle = fltrinfo->handle;
699
700 if (ioctl(jobs_fd, JOBS_DEL_FILTER, &fltr_del) < 0)
701 return (QOPERR_SYSCALL);
702 return (0);
703 }
704