1223637Sbz/* $OpenBSD: pfctl_altq.c,v 1.93 2007/10/15 02:16:35 deraadt Exp $ */ 2126353Smlaier 3126353Smlaier/* 4126353Smlaier * Copyright (c) 2002 5126353Smlaier * Sony Computer Science Laboratories Inc. 6126353Smlaier * Copyright (c) 2002, 2003 Henning Brauer <henning@openbsd.org> 7126353Smlaier * 8126353Smlaier * Permission to use, copy, modify, and distribute this software for any 9126353Smlaier * purpose with or without fee is hereby granted, provided that the above 10126353Smlaier * copyright notice and this permission notice appear in all copies. 11126353Smlaier * 12126353Smlaier * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13126353Smlaier * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14126353Smlaier * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15126353Smlaier * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16126353Smlaier * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17126353Smlaier * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18126353Smlaier * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19126353Smlaier */ 20126353Smlaier 21127082Sobrien#include <sys/cdefs.h> 22127082Sobrien__FBSDID("$FreeBSD: stable/11/sbin/pfctl/pfctl_altq.c 360674 2020-05-05 20:56:41Z dim $"); 23127082Sobrien 24223637Sbz#include <sys/types.h> 25126353Smlaier#include <sys/ioctl.h> 26126353Smlaier#include <sys/socket.h> 27126353Smlaier 28126353Smlaier#include <net/if.h> 29126353Smlaier#include <netinet/in.h> 30126353Smlaier#include <net/pfvar.h> 31126353Smlaier 32126353Smlaier#include <err.h> 33126353Smlaier#include <errno.h> 34127024Smlaier#include <limits.h> 35126353Smlaier#include <math.h> 36126353Smlaier#include <stdio.h> 37126353Smlaier#include <stdlib.h> 38126353Smlaier#include <string.h> 39126353Smlaier#include <unistd.h> 40126353Smlaier 41281613Sglebius#include <net/altq/altq.h> 42281613Sglebius#include <net/altq/altq_cbq.h> 43287009Sloos#include <net/altq/altq_codel.h> 44281613Sglebius#include <net/altq/altq_priq.h> 45281613Sglebius#include <net/altq/altq_hfsc.h> 46284777Seri#include <net/altq/altq_fairq.h> 47126353Smlaier 48126353Smlaier#include "pfctl_parser.h" 49126353Smlaier#include "pfctl.h" 50126353Smlaier 51126353Smlaier#define is_sc_null(sc) (((sc) == NULL) || ((sc)->m1 == 0 && (sc)->m2 == 0)) 52126353Smlaier 53126353SmlaierTAILQ_HEAD(altqs, pf_altq) altqs = TAILQ_HEAD_INITIALIZER(altqs); 54126353SmlaierLIST_HEAD(gen_sc, segment) rtsc, lssc; 55126353Smlaier 56126353Smlaierstruct pf_altq *qname_to_pfaltq(const char *, const char *); 57126353Smlaieru_int32_t qname_to_qid(const char *); 58126353Smlaier 59126353Smlaierstatic int eval_pfqueue_cbq(struct pfctl *, struct pf_altq *); 60126353Smlaierstatic int cbq_compute_idletime(struct pfctl *, struct pf_altq *); 61126353Smlaierstatic int check_commit_cbq(int, int, struct pf_altq *); 62126353Smlaierstatic int print_cbq_opts(const struct pf_altq *); 63126353Smlaier 64287009Sloosstatic int print_codel_opts(const struct pf_altq *, 65287009Sloos const struct node_queue_opt *); 66287009Sloos 67126353Smlaierstatic int eval_pfqueue_priq(struct pfctl *, struct pf_altq *); 68126353Smlaierstatic int check_commit_priq(int, int, struct pf_altq *); 69126353Smlaierstatic int print_priq_opts(const struct pf_altq *); 70126353Smlaier 71126353Smlaierstatic int eval_pfqueue_hfsc(struct pfctl *, struct pf_altq *); 72126353Smlaierstatic int check_commit_hfsc(int, int, struct pf_altq *); 73126353Smlaierstatic int print_hfsc_opts(const struct pf_altq *, 74126353Smlaier const struct node_queue_opt *); 75126353Smlaier 76284777Seristatic int eval_pfqueue_fairq(struct pfctl *, struct pf_altq *); 77284777Seristatic int print_fairq_opts(const struct pf_altq *, 78284777Seri const struct node_queue_opt *); 79284777Seristatic int check_commit_fairq(int, int, struct pf_altq *); 80284777Seri 81126353Smlaierstatic void gsc_add_sc(struct gen_sc *, struct service_curve *); 82126353Smlaierstatic int is_gsc_under_sc(struct gen_sc *, 83126353Smlaier struct service_curve *); 84126353Smlaierstatic void gsc_destroy(struct gen_sc *); 85126353Smlaierstatic struct segment *gsc_getentry(struct gen_sc *, double); 86126353Smlaierstatic int gsc_add_seg(struct gen_sc *, double, double, double, 87126353Smlaier double); 88126353Smlaierstatic double sc_x2y(struct service_curve *, double); 89126353Smlaier 90127024Smlaier#ifdef __FreeBSD__ 91223637Sbzu_int32_t getifspeed(int, char *); 92126355Smlaier#else 93126353Smlaieru_int32_t getifspeed(char *); 94126355Smlaier#endif 95126353Smlaieru_long getifmtu(char *); 96126353Smlaierint eval_queue_opts(struct pf_altq *, struct node_queue_opt *, 97126353Smlaier u_int32_t); 98126353Smlaieru_int32_t eval_bwspec(struct node_queue_bw *, u_int32_t); 99126353Smlaiervoid print_hfsc_sc(const char *, u_int, u_int, u_int, 100126353Smlaier const struct node_hfsc_sc *); 101284777Serivoid print_fairq_sc(const char *, u_int, u_int, u_int, 102284777Seri const struct node_fairq_sc *); 103126353Smlaier 104126353Smlaiervoid 105126353Smlaierpfaltq_store(struct pf_altq *a) 106126353Smlaier{ 107126353Smlaier struct pf_altq *altq; 108126353Smlaier 109126353Smlaier if ((altq = malloc(sizeof(*altq))) == NULL) 110126353Smlaier err(1, "malloc"); 111126353Smlaier memcpy(altq, a, sizeof(struct pf_altq)); 112126353Smlaier TAILQ_INSERT_TAIL(&altqs, altq, entries); 113126353Smlaier} 114126353Smlaier 115126353Smlaierstruct pf_altq * 116126353Smlaierpfaltq_lookup(const char *ifname) 117126353Smlaier{ 118126353Smlaier struct pf_altq *altq; 119126353Smlaier 120126353Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 121126353Smlaier if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 && 122126353Smlaier altq->qname[0] == 0) 123126353Smlaier return (altq); 124126353Smlaier } 125126353Smlaier return (NULL); 126126353Smlaier} 127126353Smlaier 128126353Smlaierstruct pf_altq * 129126353Smlaierqname_to_pfaltq(const char *qname, const char *ifname) 130126353Smlaier{ 131126353Smlaier struct pf_altq *altq; 132126353Smlaier 133126353Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 134126353Smlaier if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 && 135126353Smlaier strncmp(qname, altq->qname, PF_QNAME_SIZE) == 0) 136126353Smlaier return (altq); 137126353Smlaier } 138126353Smlaier return (NULL); 139126353Smlaier} 140126353Smlaier 141126353Smlaieru_int32_t 142126353Smlaierqname_to_qid(const char *qname) 143126353Smlaier{ 144126353Smlaier struct pf_altq *altq; 145126353Smlaier 146126353Smlaier /* 147126353Smlaier * We guarantee that same named queues on different interfaces 148126353Smlaier * have the same qid, so we do NOT need to limit matching on 149126353Smlaier * one interface! 150126353Smlaier */ 151126353Smlaier 152126353Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 153126353Smlaier if (strncmp(qname, altq->qname, PF_QNAME_SIZE) == 0) 154126353Smlaier return (altq->qid); 155126353Smlaier } 156126353Smlaier return (0); 157126353Smlaier} 158126353Smlaier 159126353Smlaiervoid 160223637Sbzprint_altq(const struct pf_altq *a, unsigned int level, 161223637Sbz struct node_queue_bw *bw, struct node_queue_opt *qopts) 162126353Smlaier{ 163130617Smlaier if (a->qname[0] != 0) { 164171172Smlaier print_queue(a, level, bw, 1, qopts); 165126353Smlaier return; 166126353Smlaier } 167126353Smlaier 168177700Smlaier#ifdef __FreeBSD__ 169177700Smlaier if (a->local_flags & PFALTQ_FLAG_IF_REMOVED) 170177700Smlaier printf("INACTIVE "); 171177700Smlaier#endif 172223637Sbz 173126353Smlaier printf("altq on %s ", a->ifname); 174126353Smlaier 175130617Smlaier switch (a->scheduler) { 176126353Smlaier case ALTQT_CBQ: 177126353Smlaier if (!print_cbq_opts(a)) 178126353Smlaier printf("cbq "); 179126353Smlaier break; 180126353Smlaier case ALTQT_PRIQ: 181126353Smlaier if (!print_priq_opts(a)) 182126353Smlaier printf("priq "); 183126353Smlaier break; 184126353Smlaier case ALTQT_HFSC: 185126353Smlaier if (!print_hfsc_opts(a, qopts)) 186126353Smlaier printf("hfsc "); 187126353Smlaier break; 188284777Seri case ALTQT_FAIRQ: 189284777Seri if (!print_fairq_opts(a, qopts)) 190284777Seri printf("fairq "); 191284777Seri break; 192287009Sloos case ALTQT_CODEL: 193287009Sloos if (!print_codel_opts(a, qopts)) 194287009Sloos printf("codel "); 195287009Sloos break; 196126353Smlaier } 197126353Smlaier 198126353Smlaier if (bw != NULL && bw->bw_percent > 0) { 199126353Smlaier if (bw->bw_percent < 100) 200126353Smlaier printf("bandwidth %u%% ", bw->bw_percent); 201126353Smlaier } else 202126353Smlaier printf("bandwidth %s ", rate2str((double)a->ifbandwidth)); 203126353Smlaier 204126353Smlaier if (a->qlimit != DEFAULT_QLIMIT) 205126353Smlaier printf("qlimit %u ", a->qlimit); 206126353Smlaier printf("tbrsize %u ", a->tbrsize); 207126353Smlaier} 208126353Smlaier 209126353Smlaiervoid 210223637Sbzprint_queue(const struct pf_altq *a, unsigned int level, 211223637Sbz struct node_queue_bw *bw, int print_interface, 212223637Sbz struct node_queue_opt *qopts) 213126353Smlaier{ 214223637Sbz unsigned int i; 215126353Smlaier 216177700Smlaier#ifdef __FreeBSD__ 217177700Smlaier if (a->local_flags & PFALTQ_FLAG_IF_REMOVED) 218177700Smlaier printf("INACTIVE "); 219177700Smlaier#endif 220126353Smlaier printf("queue "); 221126353Smlaier for (i = 0; i < level; ++i) 222126353Smlaier printf(" "); 223126353Smlaier printf("%s ", a->qname); 224126353Smlaier if (print_interface) 225126353Smlaier printf("on %s ", a->ifname); 226284777Seri if (a->scheduler == ALTQT_CBQ || a->scheduler == ALTQT_HFSC || 227284777Seri a->scheduler == ALTQT_FAIRQ) { 228126353Smlaier if (bw != NULL && bw->bw_percent > 0) { 229126353Smlaier if (bw->bw_percent < 100) 230126353Smlaier printf("bandwidth %u%% ", bw->bw_percent); 231126353Smlaier } else 232126353Smlaier printf("bandwidth %s ", rate2str((double)a->bandwidth)); 233126353Smlaier } 234126353Smlaier if (a->priority != DEFAULT_PRIORITY) 235126353Smlaier printf("priority %u ", a->priority); 236126353Smlaier if (a->qlimit != DEFAULT_QLIMIT) 237126353Smlaier printf("qlimit %u ", a->qlimit); 238126353Smlaier switch (a->scheduler) { 239126353Smlaier case ALTQT_CBQ: 240126353Smlaier print_cbq_opts(a); 241126353Smlaier break; 242126353Smlaier case ALTQT_PRIQ: 243126353Smlaier print_priq_opts(a); 244126353Smlaier break; 245126353Smlaier case ALTQT_HFSC: 246126353Smlaier print_hfsc_opts(a, qopts); 247126353Smlaier break; 248284777Seri case ALTQT_FAIRQ: 249284777Seri print_fairq_opts(a, qopts); 250284777Seri break; 251126353Smlaier } 252126353Smlaier} 253126353Smlaier 254126353Smlaier/* 255126353Smlaier * eval_pfaltq computes the discipline parameters. 256126353Smlaier */ 257126353Smlaierint 258126353Smlaiereval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, 259126353Smlaier struct node_queue_opt *opts) 260126353Smlaier{ 261126353Smlaier u_int rate, size, errors = 0; 262126353Smlaier 263126353Smlaier if (bw->bw_absolute > 0) 264126353Smlaier pa->ifbandwidth = bw->bw_absolute; 265126353Smlaier else 266127024Smlaier#ifdef __FreeBSD__ 267126355Smlaier if ((rate = getifspeed(pf->dev, pa->ifname)) == 0) { 268126355Smlaier#else 269126353Smlaier if ((rate = getifspeed(pa->ifname)) == 0) { 270126355Smlaier#endif 271171172Smlaier fprintf(stderr, "interface %s does not know its bandwidth, " 272171172Smlaier "please specify an absolute bandwidth\n", 273126353Smlaier pa->ifname); 274126353Smlaier errors++; 275126353Smlaier } else if ((pa->ifbandwidth = eval_bwspec(bw, rate)) == 0) 276126353Smlaier pa->ifbandwidth = rate; 277126353Smlaier 278126353Smlaier errors += eval_queue_opts(pa, opts, pa->ifbandwidth); 279126353Smlaier 280126353Smlaier /* if tbrsize is not specified, use heuristics */ 281126353Smlaier if (pa->tbrsize == 0) { 282126353Smlaier rate = pa->ifbandwidth; 283126353Smlaier if (rate <= 1 * 1000 * 1000) 284126353Smlaier size = 1; 285126353Smlaier else if (rate <= 10 * 1000 * 1000) 286126353Smlaier size = 4; 287126353Smlaier else if (rate <= 200 * 1000 * 1000) 288126353Smlaier size = 8; 289126353Smlaier else 290126353Smlaier size = 24; 291126353Smlaier size = size * getifmtu(pa->ifname); 292130617Smlaier if (size > 0xffff) 293130617Smlaier size = 0xffff; 294126353Smlaier pa->tbrsize = size; 295126353Smlaier } 296126353Smlaier return (errors); 297126353Smlaier} 298126353Smlaier 299126353Smlaier/* 300126353Smlaier * check_commit_altq does consistency check for each interface 301126353Smlaier */ 302126353Smlaierint 303126353Smlaiercheck_commit_altq(int dev, int opts) 304126353Smlaier{ 305126353Smlaier struct pf_altq *altq; 306126353Smlaier int error = 0; 307126353Smlaier 308126353Smlaier /* call the discipline check for each interface. */ 309126353Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 310126353Smlaier if (altq->qname[0] == 0) { 311126353Smlaier switch (altq->scheduler) { 312126353Smlaier case ALTQT_CBQ: 313126353Smlaier error = check_commit_cbq(dev, opts, altq); 314126353Smlaier break; 315126353Smlaier case ALTQT_PRIQ: 316126353Smlaier error = check_commit_priq(dev, opts, altq); 317126353Smlaier break; 318126353Smlaier case ALTQT_HFSC: 319126353Smlaier error = check_commit_hfsc(dev, opts, altq); 320126353Smlaier break; 321284777Seri case ALTQT_FAIRQ: 322284777Seri error = check_commit_fairq(dev, opts, altq); 323284777Seri break; 324126353Smlaier default: 325126353Smlaier break; 326126353Smlaier } 327126353Smlaier } 328126353Smlaier } 329126353Smlaier return (error); 330126353Smlaier} 331126353Smlaier 332126353Smlaier/* 333126353Smlaier * eval_pfqueue computes the queue parameters. 334126353Smlaier */ 335126353Smlaierint 336126353Smlaiereval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, 337126353Smlaier struct node_queue_opt *opts) 338126353Smlaier{ 339126353Smlaier /* should be merged with expand_queue */ 340145840Smlaier struct pf_altq *if_pa, *parent, *altq; 341145840Smlaier u_int32_t bwsum; 342126353Smlaier int error = 0; 343126353Smlaier 344126353Smlaier /* find the corresponding interface and copy fields used by queues */ 345126353Smlaier if ((if_pa = pfaltq_lookup(pa->ifname)) == NULL) { 346126353Smlaier fprintf(stderr, "altq not defined on %s\n", pa->ifname); 347126353Smlaier return (1); 348126353Smlaier } 349126353Smlaier pa->scheduler = if_pa->scheduler; 350126353Smlaier pa->ifbandwidth = if_pa->ifbandwidth; 351126353Smlaier 352126353Smlaier if (qname_to_pfaltq(pa->qname, pa->ifname) != NULL) { 353126353Smlaier fprintf(stderr, "queue %s already exists on interface %s\n", 354126353Smlaier pa->qname, pa->ifname); 355126353Smlaier return (1); 356126353Smlaier } 357126353Smlaier pa->qid = qname_to_qid(pa->qname); 358126353Smlaier 359126353Smlaier parent = NULL; 360126353Smlaier if (pa->parent[0] != 0) { 361126353Smlaier parent = qname_to_pfaltq(pa->parent, pa->ifname); 362126353Smlaier if (parent == NULL) { 363126353Smlaier fprintf(stderr, "parent %s not found for %s\n", 364126353Smlaier pa->parent, pa->qname); 365126353Smlaier return (1); 366126353Smlaier } 367126353Smlaier pa->parent_qid = parent->qid; 368126353Smlaier } 369126353Smlaier if (pa->qlimit == 0) 370126353Smlaier pa->qlimit = DEFAULT_QLIMIT; 371126353Smlaier 372284777Seri if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC || 373284777Seri pa->scheduler == ALTQT_FAIRQ) { 374145840Smlaier pa->bandwidth = eval_bwspec(bw, 375145840Smlaier parent == NULL ? 0 : parent->bandwidth); 376126353Smlaier 377126353Smlaier if (pa->bandwidth > pa->ifbandwidth) { 378126353Smlaier fprintf(stderr, "bandwidth for %s higher than " 379126353Smlaier "interface\n", pa->qname); 380126353Smlaier return (1); 381126353Smlaier } 382145840Smlaier /* check the sum of the child bandwidth is under parent's */ 383145840Smlaier if (parent != NULL) { 384145840Smlaier if (pa->bandwidth > parent->bandwidth) { 385145840Smlaier warnx("bandwidth for %s higher than parent", 386145840Smlaier pa->qname); 387145840Smlaier return (1); 388145840Smlaier } 389145840Smlaier bwsum = 0; 390145840Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 391145840Smlaier if (strncmp(altq->ifname, pa->ifname, 392145840Smlaier IFNAMSIZ) == 0 && 393145840Smlaier altq->qname[0] != 0 && 394145840Smlaier strncmp(altq->parent, pa->parent, 395145840Smlaier PF_QNAME_SIZE) == 0) 396145840Smlaier bwsum += altq->bandwidth; 397145840Smlaier } 398145840Smlaier bwsum += pa->bandwidth; 399145840Smlaier if (bwsum > parent->bandwidth) { 400145840Smlaier warnx("the sum of the child bandwidth higher" 401145840Smlaier " than parent \"%s\"", parent->qname); 402145840Smlaier } 403126353Smlaier } 404126353Smlaier } 405126353Smlaier 406126353Smlaier if (eval_queue_opts(pa, opts, parent == NULL? 0 : parent->bandwidth)) 407126353Smlaier return (1); 408126353Smlaier 409126353Smlaier switch (pa->scheduler) { 410126353Smlaier case ALTQT_CBQ: 411126353Smlaier error = eval_pfqueue_cbq(pf, pa); 412126353Smlaier break; 413126353Smlaier case ALTQT_PRIQ: 414126353Smlaier error = eval_pfqueue_priq(pf, pa); 415126353Smlaier break; 416126353Smlaier case ALTQT_HFSC: 417126353Smlaier error = eval_pfqueue_hfsc(pf, pa); 418126353Smlaier break; 419284777Seri case ALTQT_FAIRQ: 420284777Seri error = eval_pfqueue_fairq(pf, pa); 421284777Seri break; 422126353Smlaier default: 423126353Smlaier break; 424126353Smlaier } 425126353Smlaier return (error); 426126353Smlaier} 427126353Smlaier 428126353Smlaier/* 429126353Smlaier * CBQ support functions 430126353Smlaier */ 431126353Smlaier#define RM_FILTER_GAIN 5 /* log2 of gain, e.g., 5 => 31/32 */ 432126353Smlaier#define RM_NS_PER_SEC (1000000000) 433126353Smlaier 434126353Smlaierstatic int 435126353Smlaiereval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *pa) 436126353Smlaier{ 437126353Smlaier struct cbq_opts *opts; 438126353Smlaier u_int ifmtu; 439126353Smlaier 440126353Smlaier if (pa->priority >= CBQ_MAXPRI) { 441126353Smlaier warnx("priority out of range: max %d", CBQ_MAXPRI - 1); 442126353Smlaier return (-1); 443126353Smlaier } 444126353Smlaier 445126353Smlaier ifmtu = getifmtu(pa->ifname); 446126353Smlaier opts = &pa->pq_u.cbq_opts; 447126353Smlaier 448126353Smlaier if (opts->pktsize == 0) { /* use default */ 449126353Smlaier opts->pktsize = ifmtu; 450126353Smlaier if (opts->pktsize > MCLBYTES) /* do what TCP does */ 451126353Smlaier opts->pktsize &= ~MCLBYTES; 452126353Smlaier } else if (opts->pktsize > ifmtu) 453126353Smlaier opts->pktsize = ifmtu; 454126353Smlaier if (opts->maxpktsize == 0) /* use default */ 455126353Smlaier opts->maxpktsize = ifmtu; 456126353Smlaier else if (opts->maxpktsize > ifmtu) 457126353Smlaier opts->pktsize = ifmtu; 458126353Smlaier 459126353Smlaier if (opts->pktsize > opts->maxpktsize) 460126353Smlaier opts->pktsize = opts->maxpktsize; 461126353Smlaier 462126353Smlaier if (pa->parent[0] == 0) 463126353Smlaier opts->flags |= (CBQCLF_ROOTCLASS | CBQCLF_WRR); 464126353Smlaier 465126353Smlaier cbq_compute_idletime(pf, pa); 466126353Smlaier return (0); 467126353Smlaier} 468126353Smlaier 469126353Smlaier/* 470126353Smlaier * compute ns_per_byte, maxidle, minidle, and offtime 471126353Smlaier */ 472126353Smlaierstatic int 473126353Smlaiercbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa) 474126353Smlaier{ 475126353Smlaier struct cbq_opts *opts; 476126353Smlaier double maxidle_s, maxidle, minidle; 477126353Smlaier double offtime, nsPerByte, ifnsPerByte, ptime, cptime; 478126353Smlaier double z, g, f, gton, gtom; 479126353Smlaier u_int minburst, maxburst; 480126353Smlaier 481126353Smlaier opts = &pa->pq_u.cbq_opts; 482126353Smlaier ifnsPerByte = (1.0 / (double)pa->ifbandwidth) * RM_NS_PER_SEC * 8; 483126353Smlaier minburst = opts->minburst; 484126353Smlaier maxburst = opts->maxburst; 485126353Smlaier 486126353Smlaier if (pa->bandwidth == 0) 487126353Smlaier f = 0.0001; /* small enough? */ 488126353Smlaier else 489126353Smlaier f = ((double) pa->bandwidth / (double) pa->ifbandwidth); 490126353Smlaier 491126353Smlaier nsPerByte = ifnsPerByte / f; 492126353Smlaier ptime = (double)opts->pktsize * ifnsPerByte; 493126353Smlaier cptime = ptime * (1.0 - f) / f; 494126353Smlaier 495126353Smlaier if (nsPerByte * (double)opts->maxpktsize > (double)INT_MAX) { 496126353Smlaier /* 497126353Smlaier * this causes integer overflow in kernel! 498126353Smlaier * (bandwidth < 6Kbps when max_pkt_size=1500) 499126353Smlaier */ 500360674Sdim if (pa->bandwidth != 0 && (pf->opts & PF_OPT_QUIET) == 0) { 501126353Smlaier warnx("queue bandwidth must be larger than %s", 502126353Smlaier rate2str(ifnsPerByte * (double)opts->maxpktsize / 503126353Smlaier (double)INT_MAX * (double)pa->ifbandwidth)); 504126353Smlaier fprintf(stderr, "cbq: queue %s is too slow!\n", 505126353Smlaier pa->qname); 506360674Sdim } 507126353Smlaier nsPerByte = (double)(INT_MAX / opts->maxpktsize); 508126353Smlaier } 509126353Smlaier 510126353Smlaier if (maxburst == 0) { /* use default */ 511126353Smlaier if (cptime > 10.0 * 1000000) 512126353Smlaier maxburst = 4; 513126353Smlaier else 514126353Smlaier maxburst = 16; 515126353Smlaier } 516126353Smlaier if (minburst == 0) /* use default */ 517126353Smlaier minburst = 2; 518126353Smlaier if (minburst > maxburst) 519126353Smlaier minburst = maxburst; 520126353Smlaier 521126353Smlaier z = (double)(1 << RM_FILTER_GAIN); 522126353Smlaier g = (1.0 - 1.0 / z); 523126353Smlaier gton = pow(g, (double)maxburst); 524126353Smlaier gtom = pow(g, (double)(minburst-1)); 525126353Smlaier maxidle = ((1.0 / f - 1.0) * ((1.0 - gton) / gton)); 526126353Smlaier maxidle_s = (1.0 - g); 527126353Smlaier if (maxidle > maxidle_s) 528126353Smlaier maxidle = ptime * maxidle; 529126353Smlaier else 530126353Smlaier maxidle = ptime * maxidle_s; 531171172Smlaier offtime = cptime * (1.0 + 1.0/(1.0 - g) * (1.0 - gtom) / gtom); 532126353Smlaier minidle = -((double)opts->maxpktsize * (double)nsPerByte); 533126353Smlaier 534126353Smlaier /* scale parameters */ 535130617Smlaier maxidle = ((maxidle * 8.0) / nsPerByte) * 536130617Smlaier pow(2.0, (double)RM_FILTER_GAIN); 537130617Smlaier offtime = (offtime * 8.0) / nsPerByte * 538130617Smlaier pow(2.0, (double)RM_FILTER_GAIN); 539130617Smlaier minidle = ((minidle * 8.0) / nsPerByte) * 540130617Smlaier pow(2.0, (double)RM_FILTER_GAIN); 541126353Smlaier 542126353Smlaier maxidle = maxidle / 1000.0; 543126353Smlaier offtime = offtime / 1000.0; 544126353Smlaier minidle = minidle / 1000.0; 545126353Smlaier 546126353Smlaier opts->minburst = minburst; 547126353Smlaier opts->maxburst = maxburst; 548130617Smlaier opts->ns_per_byte = (u_int)nsPerByte; 549130617Smlaier opts->maxidle = (u_int)fabs(maxidle); 550126353Smlaier opts->minidle = (int)minidle; 551130617Smlaier opts->offtime = (u_int)fabs(offtime); 552126353Smlaier 553126353Smlaier return (0); 554126353Smlaier} 555126353Smlaier 556126353Smlaierstatic int 557126353Smlaiercheck_commit_cbq(int dev, int opts, struct pf_altq *pa) 558126353Smlaier{ 559126353Smlaier struct pf_altq *altq; 560126353Smlaier int root_class, default_class; 561126353Smlaier int error = 0; 562126353Smlaier 563126353Smlaier /* 564126353Smlaier * check if cbq has one root queue and one default queue 565126353Smlaier * for this interface 566126353Smlaier */ 567126353Smlaier root_class = default_class = 0; 568126353Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 569126353Smlaier if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) 570126353Smlaier continue; 571126353Smlaier if (altq->qname[0] == 0) /* this is for interface */ 572126353Smlaier continue; 573126353Smlaier if (altq->pq_u.cbq_opts.flags & CBQCLF_ROOTCLASS) 574126353Smlaier root_class++; 575126353Smlaier if (altq->pq_u.cbq_opts.flags & CBQCLF_DEFCLASS) 576126353Smlaier default_class++; 577126353Smlaier } 578126353Smlaier if (root_class != 1) { 579126353Smlaier warnx("should have one root queue on %s", pa->ifname); 580126353Smlaier error++; 581126353Smlaier } 582126353Smlaier if (default_class != 1) { 583126353Smlaier warnx("should have one default queue on %s", pa->ifname); 584126353Smlaier error++; 585126353Smlaier } 586126353Smlaier return (error); 587126353Smlaier} 588126353Smlaier 589126353Smlaierstatic int 590126353Smlaierprint_cbq_opts(const struct pf_altq *a) 591126353Smlaier{ 592126353Smlaier const struct cbq_opts *opts; 593126353Smlaier 594126353Smlaier opts = &a->pq_u.cbq_opts; 595126353Smlaier if (opts->flags) { 596126353Smlaier printf("cbq("); 597126353Smlaier if (opts->flags & CBQCLF_RED) 598126353Smlaier printf(" red"); 599126353Smlaier if (opts->flags & CBQCLF_ECN) 600126353Smlaier printf(" ecn"); 601126353Smlaier if (opts->flags & CBQCLF_RIO) 602126353Smlaier printf(" rio"); 603287009Sloos if (opts->flags & CBQCLF_CODEL) 604287009Sloos printf(" codel"); 605126353Smlaier if (opts->flags & CBQCLF_CLEARDSCP) 606126353Smlaier printf(" cleardscp"); 607126353Smlaier if (opts->flags & CBQCLF_FLOWVALVE) 608126353Smlaier printf(" flowvalve"); 609126353Smlaier if (opts->flags & CBQCLF_BORROW) 610126353Smlaier printf(" borrow"); 611126353Smlaier if (opts->flags & CBQCLF_WRR) 612126353Smlaier printf(" wrr"); 613126353Smlaier if (opts->flags & CBQCLF_EFFICIENT) 614126353Smlaier printf(" efficient"); 615126353Smlaier if (opts->flags & CBQCLF_ROOTCLASS) 616126353Smlaier printf(" root"); 617126353Smlaier if (opts->flags & CBQCLF_DEFCLASS) 618126353Smlaier printf(" default"); 619126353Smlaier printf(" ) "); 620126353Smlaier 621126353Smlaier return (1); 622126353Smlaier } else 623126353Smlaier return (0); 624126353Smlaier} 625126353Smlaier 626126353Smlaier/* 627126353Smlaier * PRIQ support functions 628126353Smlaier */ 629126353Smlaierstatic int 630126353Smlaiereval_pfqueue_priq(struct pfctl *pf, struct pf_altq *pa) 631126353Smlaier{ 632126353Smlaier struct pf_altq *altq; 633126353Smlaier 634126353Smlaier if (pa->priority >= PRIQ_MAXPRI) { 635126353Smlaier warnx("priority out of range: max %d", PRIQ_MAXPRI - 1); 636126353Smlaier return (-1); 637126353Smlaier } 638126353Smlaier /* the priority should be unique for the interface */ 639126353Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 640126353Smlaier if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) == 0 && 641126353Smlaier altq->qname[0] != 0 && altq->priority == pa->priority) { 642126353Smlaier warnx("%s and %s have the same priority", 643126353Smlaier altq->qname, pa->qname); 644126353Smlaier return (-1); 645126353Smlaier } 646126353Smlaier } 647126353Smlaier 648126353Smlaier return (0); 649126353Smlaier} 650126353Smlaier 651126353Smlaierstatic int 652126353Smlaiercheck_commit_priq(int dev, int opts, struct pf_altq *pa) 653126353Smlaier{ 654126353Smlaier struct pf_altq *altq; 655126353Smlaier int default_class; 656126353Smlaier int error = 0; 657126353Smlaier 658126353Smlaier /* 659126353Smlaier * check if priq has one default class for this interface 660126353Smlaier */ 661126353Smlaier default_class = 0; 662126353Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 663126353Smlaier if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) 664126353Smlaier continue; 665126353Smlaier if (altq->qname[0] == 0) /* this is for interface */ 666126353Smlaier continue; 667126353Smlaier if (altq->pq_u.priq_opts.flags & PRCF_DEFAULTCLASS) 668126353Smlaier default_class++; 669126353Smlaier } 670126353Smlaier if (default_class != 1) { 671126353Smlaier warnx("should have one default queue on %s", pa->ifname); 672126353Smlaier error++; 673126353Smlaier } 674126353Smlaier return (error); 675126353Smlaier} 676126353Smlaier 677126353Smlaierstatic int 678126353Smlaierprint_priq_opts(const struct pf_altq *a) 679126353Smlaier{ 680126353Smlaier const struct priq_opts *opts; 681126353Smlaier 682126353Smlaier opts = &a->pq_u.priq_opts; 683126353Smlaier 684126353Smlaier if (opts->flags) { 685126353Smlaier printf("priq("); 686126353Smlaier if (opts->flags & PRCF_RED) 687126353Smlaier printf(" red"); 688126353Smlaier if (opts->flags & PRCF_ECN) 689126353Smlaier printf(" ecn"); 690126353Smlaier if (opts->flags & PRCF_RIO) 691126353Smlaier printf(" rio"); 692287009Sloos if (opts->flags & PRCF_CODEL) 693287009Sloos printf(" codel"); 694126353Smlaier if (opts->flags & PRCF_CLEARDSCP) 695126353Smlaier printf(" cleardscp"); 696126353Smlaier if (opts->flags & PRCF_DEFAULTCLASS) 697126353Smlaier printf(" default"); 698126353Smlaier printf(" ) "); 699126353Smlaier 700126353Smlaier return (1); 701126353Smlaier } else 702126353Smlaier return (0); 703126353Smlaier} 704126353Smlaier 705126353Smlaier/* 706126353Smlaier * HFSC support functions 707126353Smlaier */ 708126353Smlaierstatic int 709126353Smlaiereval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) 710126353Smlaier{ 711126353Smlaier struct pf_altq *altq, *parent; 712126353Smlaier struct hfsc_opts *opts; 713126353Smlaier struct service_curve sc; 714126353Smlaier 715126353Smlaier opts = &pa->pq_u.hfsc_opts; 716126353Smlaier 717126353Smlaier if (pa->parent[0] == 0) { 718126353Smlaier /* root queue */ 719126353Smlaier opts->lssc_m1 = pa->ifbandwidth; 720126353Smlaier opts->lssc_m2 = pa->ifbandwidth; 721126353Smlaier opts->lssc_d = 0; 722126353Smlaier return (0); 723130617Smlaier } 724126353Smlaier 725126353Smlaier LIST_INIT(&rtsc); 726126353Smlaier LIST_INIT(&lssc); 727126353Smlaier 728126353Smlaier /* if link_share is not specified, use bandwidth */ 729126353Smlaier if (opts->lssc_m2 == 0) 730126353Smlaier opts->lssc_m2 = pa->bandwidth; 731126353Smlaier 732126353Smlaier if ((opts->rtsc_m1 > 0 && opts->rtsc_m2 == 0) || 733126353Smlaier (opts->lssc_m1 > 0 && opts->lssc_m2 == 0) || 734126353Smlaier (opts->ulsc_m1 > 0 && opts->ulsc_m2 == 0)) { 735126353Smlaier warnx("m2 is zero for %s", pa->qname); 736126353Smlaier return (-1); 737126353Smlaier } 738126353Smlaier 739126353Smlaier if ((opts->rtsc_m1 < opts->rtsc_m2 && opts->rtsc_m1 != 0) || 740164775Smlaier (opts->lssc_m1 < opts->lssc_m2 && opts->lssc_m1 != 0) || 741164775Smlaier (opts->ulsc_m1 < opts->ulsc_m2 && opts->ulsc_m1 != 0)) { 742126353Smlaier warnx("m1 must be zero for convex curve: %s", pa->qname); 743126353Smlaier return (-1); 744126353Smlaier } 745126353Smlaier 746126353Smlaier /* 747126353Smlaier * admission control: 748126353Smlaier * for the real-time service curve, the sum of the service curves 749126353Smlaier * should not exceed 80% of the interface bandwidth. 20% is reserved 750126353Smlaier * not to over-commit the actual interface bandwidth. 751145840Smlaier * for the linkshare service curve, the sum of the child service 752126353Smlaier * curve should not exceed the parent service curve. 753126353Smlaier * for the upper-limit service curve, the assigned bandwidth should 754126353Smlaier * be smaller than the interface bandwidth, and the upper-limit should 755126353Smlaier * be larger than the real-time service curve when both are defined. 756126353Smlaier */ 757126353Smlaier parent = qname_to_pfaltq(pa->parent, pa->ifname); 758126353Smlaier if (parent == NULL) 759126353Smlaier errx(1, "parent %s not found for %s", pa->parent, pa->qname); 760126353Smlaier 761126353Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 762126353Smlaier if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) 763126353Smlaier continue; 764126353Smlaier if (altq->qname[0] == 0) /* this is for interface */ 765126353Smlaier continue; 766126353Smlaier 767126353Smlaier /* if the class has a real-time service curve, add it. */ 768126353Smlaier if (opts->rtsc_m2 != 0 && altq->pq_u.hfsc_opts.rtsc_m2 != 0) { 769126353Smlaier sc.m1 = altq->pq_u.hfsc_opts.rtsc_m1; 770130617Smlaier sc.d = altq->pq_u.hfsc_opts.rtsc_d; 771126353Smlaier sc.m2 = altq->pq_u.hfsc_opts.rtsc_m2; 772126353Smlaier gsc_add_sc(&rtsc, &sc); 773126353Smlaier } 774126353Smlaier 775126353Smlaier if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0) 776126353Smlaier continue; 777126353Smlaier 778145840Smlaier /* if the class has a linkshare service curve, add it. */ 779126353Smlaier if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) { 780126353Smlaier sc.m1 = altq->pq_u.hfsc_opts.lssc_m1; 781130617Smlaier sc.d = altq->pq_u.hfsc_opts.lssc_d; 782126353Smlaier sc.m2 = altq->pq_u.hfsc_opts.lssc_m2; 783126353Smlaier gsc_add_sc(&lssc, &sc); 784126353Smlaier } 785126353Smlaier } 786126353Smlaier 787126353Smlaier /* check the real-time service curve. reserve 20% of interface bw */ 788126353Smlaier if (opts->rtsc_m2 != 0) { 789145840Smlaier /* add this queue to the sum */ 790145840Smlaier sc.m1 = opts->rtsc_m1; 791145840Smlaier sc.d = opts->rtsc_d; 792145840Smlaier sc.m2 = opts->rtsc_m2; 793145840Smlaier gsc_add_sc(&rtsc, &sc); 794145840Smlaier /* compare the sum with 80% of the interface */ 795126353Smlaier sc.m1 = 0; 796130617Smlaier sc.d = 0; 797126353Smlaier sc.m2 = pa->ifbandwidth / 100 * 80; 798126353Smlaier if (!is_gsc_under_sc(&rtsc, &sc)) { 799145840Smlaier warnx("real-time sc exceeds 80%% of the interface " 800145840Smlaier "bandwidth (%s)", rate2str((double)sc.m2)); 801126353Smlaier goto err_ret; 802126353Smlaier } 803126353Smlaier } 804126353Smlaier 805145840Smlaier /* check the linkshare service curve. */ 806126353Smlaier if (opts->lssc_m2 != 0) { 807145840Smlaier /* add this queue to the child sum */ 808145840Smlaier sc.m1 = opts->lssc_m1; 809145840Smlaier sc.d = opts->lssc_d; 810145840Smlaier sc.m2 = opts->lssc_m2; 811145840Smlaier gsc_add_sc(&lssc, &sc); 812145840Smlaier /* compare the sum of the children with parent's sc */ 813126353Smlaier sc.m1 = parent->pq_u.hfsc_opts.lssc_m1; 814130617Smlaier sc.d = parent->pq_u.hfsc_opts.lssc_d; 815126353Smlaier sc.m2 = parent->pq_u.hfsc_opts.lssc_m2; 816126353Smlaier if (!is_gsc_under_sc(&lssc, &sc)) { 817145840Smlaier warnx("linkshare sc exceeds parent's sc"); 818126353Smlaier goto err_ret; 819126353Smlaier } 820126353Smlaier } 821126353Smlaier 822126353Smlaier /* check the upper-limit service curve. */ 823126353Smlaier if (opts->ulsc_m2 != 0) { 824126353Smlaier if (opts->ulsc_m1 > pa->ifbandwidth || 825126353Smlaier opts->ulsc_m2 > pa->ifbandwidth) { 826126353Smlaier warnx("upper-limit larger than interface bandwidth"); 827126353Smlaier goto err_ret; 828126353Smlaier } 829126353Smlaier if (opts->rtsc_m2 != 0 && opts->rtsc_m2 > opts->ulsc_m2) { 830126353Smlaier warnx("upper-limit sc smaller than real-time sc"); 831126353Smlaier goto err_ret; 832126353Smlaier } 833126353Smlaier } 834126353Smlaier 835126353Smlaier gsc_destroy(&rtsc); 836126353Smlaier gsc_destroy(&lssc); 837126353Smlaier 838126353Smlaier return (0); 839126353Smlaier 840126353Smlaiererr_ret: 841126353Smlaier gsc_destroy(&rtsc); 842126353Smlaier gsc_destroy(&lssc); 843126353Smlaier return (-1); 844126353Smlaier} 845126353Smlaier 846284777Seri/* 847284777Seri * FAIRQ support functions 848284777Seri */ 849126353Smlaierstatic int 850284777Serieval_pfqueue_fairq(struct pfctl *pf __unused, struct pf_altq *pa) 851284777Seri{ 852284777Seri struct pf_altq *altq, *parent; 853284777Seri struct fairq_opts *opts; 854284777Seri struct service_curve sc; 855284777Seri 856284777Seri opts = &pa->pq_u.fairq_opts; 857284777Seri 858284777Seri if (pa->parent[0] == 0) { 859284777Seri /* root queue */ 860284777Seri opts->lssc_m1 = pa->ifbandwidth; 861284777Seri opts->lssc_m2 = pa->ifbandwidth; 862284777Seri opts->lssc_d = 0; 863284777Seri return (0); 864284777Seri } 865284777Seri 866284777Seri LIST_INIT(&lssc); 867284777Seri 868284777Seri /* if link_share is not specified, use bandwidth */ 869284777Seri if (opts->lssc_m2 == 0) 870284777Seri opts->lssc_m2 = pa->bandwidth; 871284777Seri 872284777Seri /* 873284777Seri * admission control: 874284777Seri * for the real-time service curve, the sum of the service curves 875284777Seri * should not exceed 80% of the interface bandwidth. 20% is reserved 876284777Seri * not to over-commit the actual interface bandwidth. 877284777Seri * for the link-sharing service curve, the sum of the child service 878284777Seri * curve should not exceed the parent service curve. 879284777Seri * for the upper-limit service curve, the assigned bandwidth should 880284777Seri * be smaller than the interface bandwidth, and the upper-limit should 881284777Seri * be larger than the real-time service curve when both are defined. 882284777Seri */ 883284777Seri parent = qname_to_pfaltq(pa->parent, pa->ifname); 884284777Seri if (parent == NULL) 885284777Seri errx(1, "parent %s not found for %s", pa->parent, pa->qname); 886284777Seri 887284777Seri TAILQ_FOREACH(altq, &altqs, entries) { 888284777Seri if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) 889284777Seri continue; 890284777Seri if (altq->qname[0] == 0) /* this is for interface */ 891284777Seri continue; 892284777Seri 893284777Seri if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0) 894284777Seri continue; 895284777Seri 896284777Seri /* if the class has a link-sharing service curve, add it. */ 897284777Seri if (opts->lssc_m2 != 0 && altq->pq_u.fairq_opts.lssc_m2 != 0) { 898284777Seri sc.m1 = altq->pq_u.fairq_opts.lssc_m1; 899284777Seri sc.d = altq->pq_u.fairq_opts.lssc_d; 900284777Seri sc.m2 = altq->pq_u.fairq_opts.lssc_m2; 901284777Seri gsc_add_sc(&lssc, &sc); 902284777Seri } 903284777Seri } 904284777Seri 905284777Seri /* check the link-sharing service curve. */ 906284777Seri if (opts->lssc_m2 != 0) { 907284777Seri sc.m1 = parent->pq_u.fairq_opts.lssc_m1; 908284777Seri sc.d = parent->pq_u.fairq_opts.lssc_d; 909284777Seri sc.m2 = parent->pq_u.fairq_opts.lssc_m2; 910284777Seri if (!is_gsc_under_sc(&lssc, &sc)) { 911284777Seri warnx("link-sharing sc exceeds parent's sc"); 912284777Seri goto err_ret; 913284777Seri } 914284777Seri } 915284777Seri 916284777Seri gsc_destroy(&lssc); 917284777Seri 918284777Seri return (0); 919284777Seri 920284777Serierr_ret: 921284777Seri gsc_destroy(&lssc); 922284777Seri return (-1); 923284777Seri} 924284777Seri 925284777Seristatic int 926126353Smlaiercheck_commit_hfsc(int dev, int opts, struct pf_altq *pa) 927126353Smlaier{ 928126353Smlaier struct pf_altq *altq, *def = NULL; 929126353Smlaier int default_class; 930126353Smlaier int error = 0; 931126353Smlaier 932126353Smlaier /* check if hfsc has one default queue for this interface */ 933126353Smlaier default_class = 0; 934126353Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 935126353Smlaier if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) 936126353Smlaier continue; 937126353Smlaier if (altq->qname[0] == 0) /* this is for interface */ 938126353Smlaier continue; 939126353Smlaier if (altq->parent[0] == 0) /* dummy root */ 940126353Smlaier continue; 941126353Smlaier if (altq->pq_u.hfsc_opts.flags & HFCF_DEFAULTCLASS) { 942126353Smlaier default_class++; 943126353Smlaier def = altq; 944126353Smlaier } 945126353Smlaier } 946126353Smlaier if (default_class != 1) { 947126353Smlaier warnx("should have one default queue on %s", pa->ifname); 948126353Smlaier return (1); 949126353Smlaier } 950126353Smlaier /* make sure the default queue is a leaf */ 951126353Smlaier TAILQ_FOREACH(altq, &altqs, entries) { 952126353Smlaier if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) 953126353Smlaier continue; 954126353Smlaier if (altq->qname[0] == 0) /* this is for interface */ 955126353Smlaier continue; 956126353Smlaier if (strncmp(altq->parent, def->qname, PF_QNAME_SIZE) == 0) { 957126353Smlaier warnx("default queue is not a leaf"); 958126353Smlaier error++; 959126353Smlaier } 960126353Smlaier } 961126353Smlaier return (error); 962126353Smlaier} 963126353Smlaier 964126353Smlaierstatic int 965284777Sericheck_commit_fairq(int dev __unused, int opts __unused, struct pf_altq *pa) 966284777Seri{ 967284777Seri struct pf_altq *altq, *def = NULL; 968284777Seri int default_class; 969284777Seri int error = 0; 970284777Seri 971284777Seri /* check if fairq has one default queue for this interface */ 972284777Seri default_class = 0; 973284777Seri TAILQ_FOREACH(altq, &altqs, entries) { 974284777Seri if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) 975284777Seri continue; 976284777Seri if (altq->qname[0] == 0) /* this is for interface */ 977284777Seri continue; 978284777Seri if (altq->pq_u.fairq_opts.flags & FARF_DEFAULTCLASS) { 979284777Seri default_class++; 980284777Seri def = altq; 981284777Seri } 982284777Seri } 983284777Seri if (default_class != 1) { 984284777Seri warnx("should have one default queue on %s", pa->ifname); 985284777Seri return (1); 986284777Seri } 987284777Seri /* make sure the default queue is a leaf */ 988284777Seri TAILQ_FOREACH(altq, &altqs, entries) { 989284777Seri if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) 990284777Seri continue; 991284777Seri if (altq->qname[0] == 0) /* this is for interface */ 992284777Seri continue; 993284777Seri if (strncmp(altq->parent, def->qname, PF_QNAME_SIZE) == 0) { 994284777Seri warnx("default queue is not a leaf"); 995284777Seri error++; 996284777Seri } 997284777Seri } 998284777Seri return (error); 999284777Seri} 1000284777Seri 1001284777Seristatic int 1002126353Smlaierprint_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts) 1003126353Smlaier{ 1004126353Smlaier const struct hfsc_opts *opts; 1005126353Smlaier const struct node_hfsc_sc *rtsc, *lssc, *ulsc; 1006126353Smlaier 1007126353Smlaier opts = &a->pq_u.hfsc_opts; 1008126353Smlaier if (qopts == NULL) 1009126353Smlaier rtsc = lssc = ulsc = NULL; 1010126353Smlaier else { 1011126353Smlaier rtsc = &qopts->data.hfsc_opts.realtime; 1012126353Smlaier lssc = &qopts->data.hfsc_opts.linkshare; 1013126353Smlaier ulsc = &qopts->data.hfsc_opts.upperlimit; 1014126353Smlaier } 1015126353Smlaier 1016126353Smlaier if (opts->flags || opts->rtsc_m2 != 0 || opts->ulsc_m2 != 0 || 1017126353Smlaier (opts->lssc_m2 != 0 && (opts->lssc_m2 != a->bandwidth || 1018126353Smlaier opts->lssc_d != 0))) { 1019126353Smlaier printf("hfsc("); 1020126353Smlaier if (opts->flags & HFCF_RED) 1021126353Smlaier printf(" red"); 1022126353Smlaier if (opts->flags & HFCF_ECN) 1023126353Smlaier printf(" ecn"); 1024126353Smlaier if (opts->flags & HFCF_RIO) 1025126353Smlaier printf(" rio"); 1026287009Sloos if (opts->flags & HFCF_CODEL) 1027287009Sloos printf(" codel"); 1028126353Smlaier if (opts->flags & HFCF_CLEARDSCP) 1029126353Smlaier printf(" cleardscp"); 1030126353Smlaier if (opts->flags & HFCF_DEFAULTCLASS) 1031126353Smlaier printf(" default"); 1032126353Smlaier if (opts->rtsc_m2 != 0) 1033126353Smlaier print_hfsc_sc("realtime", opts->rtsc_m1, opts->rtsc_d, 1034126353Smlaier opts->rtsc_m2, rtsc); 1035126353Smlaier if (opts->lssc_m2 != 0 && (opts->lssc_m2 != a->bandwidth || 1036126353Smlaier opts->lssc_d != 0)) 1037126353Smlaier print_hfsc_sc("linkshare", opts->lssc_m1, opts->lssc_d, 1038126353Smlaier opts->lssc_m2, lssc); 1039126353Smlaier if (opts->ulsc_m2 != 0) 1040126353Smlaier print_hfsc_sc("upperlimit", opts->ulsc_m1, opts->ulsc_d, 1041126353Smlaier opts->ulsc_m2, ulsc); 1042126353Smlaier printf(" ) "); 1043126353Smlaier 1044126353Smlaier return (1); 1045126353Smlaier } else 1046126353Smlaier return (0); 1047126353Smlaier} 1048126353Smlaier 1049284777Seristatic int 1050287009Sloosprint_codel_opts(const struct pf_altq *a, const struct node_queue_opt *qopts) 1051287009Sloos{ 1052287009Sloos const struct codel_opts *opts; 1053287009Sloos 1054287009Sloos opts = &a->pq_u.codel_opts; 1055287009Sloos if (opts->target || opts->interval || opts->ecn) { 1056287009Sloos printf("codel("); 1057287009Sloos if (opts->target) 1058287009Sloos printf(" target %d", opts->target); 1059287009Sloos if (opts->interval) 1060287009Sloos printf(" interval %d", opts->interval); 1061287009Sloos if (opts->ecn) 1062287009Sloos printf("ecn"); 1063287009Sloos printf(" ) "); 1064287009Sloos 1065287009Sloos return (1); 1066287009Sloos } 1067287009Sloos 1068287009Sloos return (0); 1069287009Sloos} 1070287009Sloos 1071287009Sloosstatic int 1072284777Seriprint_fairq_opts(const struct pf_altq *a, const struct node_queue_opt *qopts) 1073284777Seri{ 1074284777Seri const struct fairq_opts *opts; 1075284777Seri const struct node_fairq_sc *loc_lssc; 1076284777Seri 1077284777Seri opts = &a->pq_u.fairq_opts; 1078284777Seri if (qopts == NULL) 1079284777Seri loc_lssc = NULL; 1080284777Seri else 1081284777Seri loc_lssc = &qopts->data.fairq_opts.linkshare; 1082284777Seri 1083284777Seri if (opts->flags || 1084284777Seri (opts->lssc_m2 != 0 && (opts->lssc_m2 != a->bandwidth || 1085284777Seri opts->lssc_d != 0))) { 1086284777Seri printf("fairq("); 1087284777Seri if (opts->flags & FARF_RED) 1088284777Seri printf(" red"); 1089284777Seri if (opts->flags & FARF_ECN) 1090284777Seri printf(" ecn"); 1091284777Seri if (opts->flags & FARF_RIO) 1092284777Seri printf(" rio"); 1093287009Sloos if (opts->flags & FARF_CODEL) 1094287009Sloos printf(" codel"); 1095284777Seri if (opts->flags & FARF_CLEARDSCP) 1096284777Seri printf(" cleardscp"); 1097284777Seri if (opts->flags & FARF_DEFAULTCLASS) 1098284777Seri printf(" default"); 1099284777Seri if (opts->lssc_m2 != 0 && (opts->lssc_m2 != a->bandwidth || 1100284777Seri opts->lssc_d != 0)) 1101284777Seri print_fairq_sc("linkshare", opts->lssc_m1, opts->lssc_d, 1102284777Seri opts->lssc_m2, loc_lssc); 1103284777Seri printf(" ) "); 1104284777Seri 1105284777Seri return (1); 1106284777Seri } else 1107284777Seri return (0); 1108284777Seri} 1109284777Seri 1110126353Smlaier/* 1111126353Smlaier * admission control using generalized service curve 1112126353Smlaier */ 1113126353Smlaier 1114126353Smlaier/* add a new service curve to a generalized service curve */ 1115126353Smlaierstatic void 1116126353Smlaiergsc_add_sc(struct gen_sc *gsc, struct service_curve *sc) 1117126353Smlaier{ 1118126353Smlaier if (is_sc_null(sc)) 1119126353Smlaier return; 1120126353Smlaier if (sc->d != 0) 1121126353Smlaier gsc_add_seg(gsc, 0.0, 0.0, (double)sc->d, (double)sc->m1); 1122126353Smlaier gsc_add_seg(gsc, (double)sc->d, 0.0, INFINITY, (double)sc->m2); 1123126353Smlaier} 1124126353Smlaier 1125126353Smlaier/* 1126126353Smlaier * check whether all points of a generalized service curve have 1127126353Smlaier * their y-coordinates no larger than a given two-piece linear 1128126353Smlaier * service curve. 1129126353Smlaier */ 1130126353Smlaierstatic int 1131126353Smlaieris_gsc_under_sc(struct gen_sc *gsc, struct service_curve *sc) 1132126353Smlaier{ 1133126353Smlaier struct segment *s, *last, *end; 1134126353Smlaier double y; 1135126353Smlaier 1136126353Smlaier if (is_sc_null(sc)) { 1137126353Smlaier if (LIST_EMPTY(gsc)) 1138126353Smlaier return (1); 1139126353Smlaier LIST_FOREACH(s, gsc, _next) { 1140126353Smlaier if (s->m != 0) 1141126353Smlaier return (0); 1142126353Smlaier } 1143126353Smlaier return (1); 1144126353Smlaier } 1145126353Smlaier /* 1146126353Smlaier * gsc has a dummy entry at the end with x = INFINITY. 1147126353Smlaier * loop through up to this dummy entry. 1148126353Smlaier */ 1149126353Smlaier end = gsc_getentry(gsc, INFINITY); 1150126353Smlaier if (end == NULL) 1151126353Smlaier return (1); 1152126353Smlaier last = NULL; 1153126353Smlaier for (s = LIST_FIRST(gsc); s != end; s = LIST_NEXT(s, _next)) { 1154126353Smlaier if (s->y > sc_x2y(sc, s->x)) 1155126353Smlaier return (0); 1156126353Smlaier last = s; 1157126353Smlaier } 1158126353Smlaier /* last now holds the real last segment */ 1159126353Smlaier if (last == NULL) 1160126353Smlaier return (1); 1161126353Smlaier if (last->m > sc->m2) 1162126353Smlaier return (0); 1163126353Smlaier if (last->x < sc->d && last->m > sc->m1) { 1164126353Smlaier y = last->y + (sc->d - last->x) * last->m; 1165126353Smlaier if (y > sc_x2y(sc, sc->d)) 1166126353Smlaier return (0); 1167126353Smlaier } 1168126353Smlaier return (1); 1169126353Smlaier} 1170126353Smlaier 1171126353Smlaierstatic void 1172126353Smlaiergsc_destroy(struct gen_sc *gsc) 1173126353Smlaier{ 1174126353Smlaier struct segment *s; 1175126353Smlaier 1176126353Smlaier while ((s = LIST_FIRST(gsc)) != NULL) { 1177126353Smlaier LIST_REMOVE(s, _next); 1178126353Smlaier free(s); 1179126353Smlaier } 1180126353Smlaier} 1181126353Smlaier 1182126353Smlaier/* 1183126353Smlaier * return a segment entry starting at x. 1184126353Smlaier * if gsc has no entry starting at x, a new entry is created at x. 1185126353Smlaier */ 1186126353Smlaierstatic struct segment * 1187126353Smlaiergsc_getentry(struct gen_sc *gsc, double x) 1188126353Smlaier{ 1189126353Smlaier struct segment *new, *prev, *s; 1190126353Smlaier 1191126353Smlaier prev = NULL; 1192126353Smlaier LIST_FOREACH(s, gsc, _next) { 1193126353Smlaier if (s->x == x) 1194126353Smlaier return (s); /* matching entry found */ 1195126353Smlaier else if (s->x < x) 1196126353Smlaier prev = s; 1197126353Smlaier else 1198126353Smlaier break; 1199126353Smlaier } 1200126353Smlaier 1201126353Smlaier /* we have to create a new entry */ 1202126353Smlaier if ((new = calloc(1, sizeof(struct segment))) == NULL) 1203126353Smlaier return (NULL); 1204126353Smlaier 1205126353Smlaier new->x = x; 1206126353Smlaier if (x == INFINITY || s == NULL) 1207126353Smlaier new->d = 0; 1208126353Smlaier else if (s->x == INFINITY) 1209126353Smlaier new->d = INFINITY; 1210126353Smlaier else 1211126353Smlaier new->d = s->x - x; 1212126353Smlaier if (prev == NULL) { 1213126353Smlaier /* insert the new entry at the head of the list */ 1214126353Smlaier new->y = 0; 1215126353Smlaier new->m = 0; 1216126353Smlaier LIST_INSERT_HEAD(gsc, new, _next); 1217126353Smlaier } else { 1218126353Smlaier /* 1219126353Smlaier * the start point intersects with the segment pointed by 1220126353Smlaier * prev. divide prev into 2 segments 1221126353Smlaier */ 1222126353Smlaier if (x == INFINITY) { 1223126353Smlaier prev->d = INFINITY; 1224126353Smlaier if (prev->m == 0) 1225126353Smlaier new->y = prev->y; 1226126353Smlaier else 1227126353Smlaier new->y = INFINITY; 1228126353Smlaier } else { 1229126353Smlaier prev->d = x - prev->x; 1230126353Smlaier new->y = prev->d * prev->m + prev->y; 1231126353Smlaier } 1232126353Smlaier new->m = prev->m; 1233126353Smlaier LIST_INSERT_AFTER(prev, new, _next); 1234126353Smlaier } 1235126353Smlaier return (new); 1236126353Smlaier} 1237126353Smlaier 1238126353Smlaier/* add a segment to a generalized service curve */ 1239126353Smlaierstatic int 1240126353Smlaiergsc_add_seg(struct gen_sc *gsc, double x, double y, double d, double m) 1241126353Smlaier{ 1242126353Smlaier struct segment *start, *end, *s; 1243126353Smlaier double x2; 1244126353Smlaier 1245126353Smlaier if (d == INFINITY) 1246126353Smlaier x2 = INFINITY; 1247126353Smlaier else 1248126353Smlaier x2 = x + d; 1249126353Smlaier start = gsc_getentry(gsc, x); 1250130617Smlaier end = gsc_getentry(gsc, x2); 1251126353Smlaier if (start == NULL || end == NULL) 1252126353Smlaier return (-1); 1253126353Smlaier 1254126353Smlaier for (s = start; s != end; s = LIST_NEXT(s, _next)) { 1255126353Smlaier s->m += m; 1256126353Smlaier s->y += y + (s->x - x) * m; 1257126353Smlaier } 1258126353Smlaier 1259126353Smlaier end = gsc_getentry(gsc, INFINITY); 1260126353Smlaier for (; s != end; s = LIST_NEXT(s, _next)) { 1261126353Smlaier s->y += m * d; 1262126353Smlaier } 1263126353Smlaier 1264126353Smlaier return (0); 1265126353Smlaier} 1266126353Smlaier 1267126353Smlaier/* get y-projection of a service curve */ 1268126353Smlaierstatic double 1269126353Smlaiersc_x2y(struct service_curve *sc, double x) 1270126353Smlaier{ 1271126353Smlaier double y; 1272126353Smlaier 1273126353Smlaier if (x <= (double)sc->d) 1274126353Smlaier /* y belongs to the 1st segment */ 1275126353Smlaier y = x * (double)sc->m1; 1276126353Smlaier else 1277126353Smlaier /* y belongs to the 2nd segment */ 1278126353Smlaier y = (double)sc->d * (double)sc->m1 1279126353Smlaier + (x - (double)sc->d) * (double)sc->m2; 1280126353Smlaier return (y); 1281126353Smlaier} 1282126353Smlaier 1283126353Smlaier/* 1284126353Smlaier * misc utilities 1285126353Smlaier */ 1286126353Smlaier#define R2S_BUFS 8 1287126353Smlaier#define RATESTR_MAX 16 1288126353Smlaier 1289126353Smlaierchar * 1290126353Smlaierrate2str(double rate) 1291126353Smlaier{ 1292126353Smlaier char *buf; 1293126353Smlaier static char r2sbuf[R2S_BUFS][RATESTR_MAX]; /* ring bufer */ 1294126353Smlaier static int idx = 0; 1295126353Smlaier int i; 1296126353Smlaier static const char unit[] = " KMG"; 1297126353Smlaier 1298126353Smlaier buf = r2sbuf[idx++]; 1299126353Smlaier if (idx == R2S_BUFS) 1300126353Smlaier idx = 0; 1301126353Smlaier 1302126353Smlaier for (i = 0; rate >= 1000 && i <= 3; i++) 1303126353Smlaier rate /= 1000; 1304126353Smlaier 1305126353Smlaier if ((int)(rate * 100) % 100) 1306126353Smlaier snprintf(buf, RATESTR_MAX, "%.2f%cb", rate, unit[i]); 1307126353Smlaier else 1308126353Smlaier snprintf(buf, RATESTR_MAX, "%d%cb", (int)rate, unit[i]); 1309126353Smlaier 1310126353Smlaier return (buf); 1311126353Smlaier} 1312126353Smlaier 1313127024Smlaier#ifdef __FreeBSD__ 1314126355Smlaier/* 1315126355Smlaier * XXX 1316127024Smlaier * FreeBSD does not have SIOCGIFDATA. 1317126355Smlaier * To emulate this, DIOCGIFSPEED ioctl added to pf. 1318126355Smlaier */ 1319126353Smlaieru_int32_t 1320126355Smlaiergetifspeed(int pfdev, char *ifname) 1321126355Smlaier{ 1322126355Smlaier struct pf_ifspeed io; 1323126355Smlaier 1324126355Smlaier bzero(&io, sizeof io); 1325126355Smlaier if (strlcpy(io.ifname, ifname, IFNAMSIZ) >= 1326126355Smlaier sizeof(io.ifname)) 1327126355Smlaier errx(1, "getifspeed: strlcpy"); 1328126355Smlaier if (ioctl(pfdev, DIOCGIFSPEED, &io) == -1) 1329126355Smlaier err(1, "DIOCGIFSPEED"); 1330126355Smlaier return ((u_int32_t)io.baudrate); 1331126355Smlaier} 1332126355Smlaier#else 1333126355Smlaieru_int32_t 1334126353Smlaiergetifspeed(char *ifname) 1335126353Smlaier{ 1336126353Smlaier int s; 1337126353Smlaier struct ifreq ifr; 1338126353Smlaier struct if_data ifrdat; 1339126353Smlaier 1340259916Sbz if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) < 0) 1341126353Smlaier err(1, "socket"); 1342145840Smlaier bzero(&ifr, sizeof(ifr)); 1343126353Smlaier if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= 1344126353Smlaier sizeof(ifr.ifr_name)) 1345126353Smlaier errx(1, "getifspeed: strlcpy"); 1346126353Smlaier ifr.ifr_data = (caddr_t)&ifrdat; 1347126353Smlaier if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1) 1348126353Smlaier err(1, "SIOCGIFDATA"); 1349126353Smlaier if (close(s)) 1350126353Smlaier err(1, "close"); 1351126353Smlaier return ((u_int32_t)ifrdat.ifi_baudrate); 1352126353Smlaier} 1353126355Smlaier#endif 1354126353Smlaier 1355126353Smlaieru_long 1356126353Smlaiergetifmtu(char *ifname) 1357126353Smlaier{ 1358126353Smlaier int s; 1359126353Smlaier struct ifreq ifr; 1360126353Smlaier 1361259916Sbz if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) < 0) 1362126353Smlaier err(1, "socket"); 1363145840Smlaier bzero(&ifr, sizeof(ifr)); 1364126353Smlaier if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= 1365126353Smlaier sizeof(ifr.ifr_name)) 1366126353Smlaier errx(1, "getifmtu: strlcpy"); 1367126353Smlaier if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) == -1) 1368177700Smlaier#ifdef __FreeBSD__ 1369177700Smlaier ifr.ifr_mtu = 1500; 1370177700Smlaier#else 1371126353Smlaier err(1, "SIOCGIFMTU"); 1372177700Smlaier#endif 1373126353Smlaier if (close(s)) 1374126353Smlaier err(1, "close"); 1375126353Smlaier if (ifr.ifr_mtu > 0) 1376126353Smlaier return (ifr.ifr_mtu); 1377126353Smlaier else { 1378126353Smlaier warnx("could not get mtu for %s, assuming 1500", ifname); 1379126353Smlaier return (1500); 1380126353Smlaier } 1381126353Smlaier} 1382126353Smlaier 1383126353Smlaierint 1384126353Smlaiereval_queue_opts(struct pf_altq *pa, struct node_queue_opt *opts, 1385126353Smlaier u_int32_t ref_bw) 1386126353Smlaier{ 1387126353Smlaier int errors = 0; 1388126353Smlaier 1389126353Smlaier switch (pa->scheduler) { 1390126353Smlaier case ALTQT_CBQ: 1391126353Smlaier pa->pq_u.cbq_opts = opts->data.cbq_opts; 1392126353Smlaier break; 1393126353Smlaier case ALTQT_PRIQ: 1394126353Smlaier pa->pq_u.priq_opts = opts->data.priq_opts; 1395126353Smlaier break; 1396126353Smlaier case ALTQT_HFSC: 1397126353Smlaier pa->pq_u.hfsc_opts.flags = opts->data.hfsc_opts.flags; 1398126353Smlaier if (opts->data.hfsc_opts.linkshare.used) { 1399126353Smlaier pa->pq_u.hfsc_opts.lssc_m1 = 1400126353Smlaier eval_bwspec(&opts->data.hfsc_opts.linkshare.m1, 1401126353Smlaier ref_bw); 1402126353Smlaier pa->pq_u.hfsc_opts.lssc_m2 = 1403126353Smlaier eval_bwspec(&opts->data.hfsc_opts.linkshare.m2, 1404126353Smlaier ref_bw); 1405126353Smlaier pa->pq_u.hfsc_opts.lssc_d = 1406126353Smlaier opts->data.hfsc_opts.linkshare.d; 1407126353Smlaier } 1408126353Smlaier if (opts->data.hfsc_opts.realtime.used) { 1409126353Smlaier pa->pq_u.hfsc_opts.rtsc_m1 = 1410126353Smlaier eval_bwspec(&opts->data.hfsc_opts.realtime.m1, 1411126353Smlaier ref_bw); 1412126353Smlaier pa->pq_u.hfsc_opts.rtsc_m2 = 1413126353Smlaier eval_bwspec(&opts->data.hfsc_opts.realtime.m2, 1414126353Smlaier ref_bw); 1415126353Smlaier pa->pq_u.hfsc_opts.rtsc_d = 1416126353Smlaier opts->data.hfsc_opts.realtime.d; 1417126353Smlaier } 1418126353Smlaier if (opts->data.hfsc_opts.upperlimit.used) { 1419126353Smlaier pa->pq_u.hfsc_opts.ulsc_m1 = 1420126353Smlaier eval_bwspec(&opts->data.hfsc_opts.upperlimit.m1, 1421126353Smlaier ref_bw); 1422126353Smlaier pa->pq_u.hfsc_opts.ulsc_m2 = 1423126353Smlaier eval_bwspec(&opts->data.hfsc_opts.upperlimit.m2, 1424126353Smlaier ref_bw); 1425126353Smlaier pa->pq_u.hfsc_opts.ulsc_d = 1426126353Smlaier opts->data.hfsc_opts.upperlimit.d; 1427126353Smlaier } 1428126353Smlaier break; 1429284777Seri case ALTQT_FAIRQ: 1430284777Seri pa->pq_u.fairq_opts.flags = opts->data.fairq_opts.flags; 1431284777Seri pa->pq_u.fairq_opts.nbuckets = opts->data.fairq_opts.nbuckets; 1432284777Seri pa->pq_u.fairq_opts.hogs_m1 = 1433284777Seri eval_bwspec(&opts->data.fairq_opts.hogs_bw, ref_bw); 1434284777Seri 1435284777Seri if (opts->data.fairq_opts.linkshare.used) { 1436284777Seri pa->pq_u.fairq_opts.lssc_m1 = 1437284777Seri eval_bwspec(&opts->data.fairq_opts.linkshare.m1, 1438284777Seri ref_bw); 1439284777Seri pa->pq_u.fairq_opts.lssc_m2 = 1440284777Seri eval_bwspec(&opts->data.fairq_opts.linkshare.m2, 1441284777Seri ref_bw); 1442284777Seri pa->pq_u.fairq_opts.lssc_d = 1443284777Seri opts->data.fairq_opts.linkshare.d; 1444284777Seri } 1445284777Seri break; 1446287009Sloos case ALTQT_CODEL: 1447287009Sloos pa->pq_u.codel_opts.target = opts->data.codel_opts.target; 1448287009Sloos pa->pq_u.codel_opts.interval = opts->data.codel_opts.interval; 1449287009Sloos pa->pq_u.codel_opts.ecn = opts->data.codel_opts.ecn; 1450287009Sloos break; 1451126353Smlaier default: 1452126353Smlaier warnx("eval_queue_opts: unknown scheduler type %u", 1453126353Smlaier opts->qtype); 1454126353Smlaier errors++; 1455126353Smlaier break; 1456126353Smlaier } 1457126353Smlaier 1458126353Smlaier return (errors); 1459126353Smlaier} 1460126353Smlaier 1461126353Smlaieru_int32_t 1462126353Smlaiereval_bwspec(struct node_queue_bw *bw, u_int32_t ref_bw) 1463126353Smlaier{ 1464126353Smlaier if (bw->bw_absolute > 0) 1465126353Smlaier return (bw->bw_absolute); 1466126353Smlaier 1467126353Smlaier if (bw->bw_percent > 0) 1468126353Smlaier return (ref_bw / 100 * bw->bw_percent); 1469126353Smlaier 1470126353Smlaier return (0); 1471126353Smlaier} 1472126353Smlaier 1473126353Smlaiervoid 1474126353Smlaierprint_hfsc_sc(const char *scname, u_int m1, u_int d, u_int m2, 1475126353Smlaier const struct node_hfsc_sc *sc) 1476126353Smlaier{ 1477126353Smlaier printf(" %s", scname); 1478126353Smlaier 1479126353Smlaier if (d != 0) { 1480126353Smlaier printf("("); 1481126353Smlaier if (sc != NULL && sc->m1.bw_percent > 0) 1482126353Smlaier printf("%u%%", sc->m1.bw_percent); 1483126353Smlaier else 1484126353Smlaier printf("%s", rate2str((double)m1)); 1485126353Smlaier printf(" %u", d); 1486126353Smlaier } 1487126353Smlaier 1488126353Smlaier if (sc != NULL && sc->m2.bw_percent > 0) 1489126353Smlaier printf(" %u%%", sc->m2.bw_percent); 1490126353Smlaier else 1491126353Smlaier printf(" %s", rate2str((double)m2)); 1492126353Smlaier 1493126353Smlaier if (d != 0) 1494126353Smlaier printf(")"); 1495126353Smlaier} 1496284777Seri 1497284777Serivoid 1498284777Seriprint_fairq_sc(const char *scname, u_int m1, u_int d, u_int m2, 1499284777Seri const struct node_fairq_sc *sc) 1500284777Seri{ 1501284777Seri printf(" %s", scname); 1502284777Seri 1503284777Seri if (d != 0) { 1504284777Seri printf("("); 1505284777Seri if (sc != NULL && sc->m1.bw_percent > 0) 1506284777Seri printf("%u%%", sc->m1.bw_percent); 1507284777Seri else 1508284777Seri printf("%s", rate2str((double)m1)); 1509284777Seri printf(" %u", d); 1510284777Seri } 1511284777Seri 1512284777Seri if (sc != NULL && sc->m2.bw_percent > 0) 1513284777Seri printf(" %u%%", sc->m2.bw_percent); 1514284777Seri else 1515284777Seri printf(" %s", rate2str((double)m2)); 1516284777Seri 1517284777Seri if (d != 0) 1518284777Seri printf(")"); 1519284777Seri} 1520