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