Changeset View
Changeset View
Standalone View
Standalone View
head/sbin/pfctl/pfctl_altq.c
Show All 18 Lines | |||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#define PFIOC_USE_LATEST | #define PFIOC_USE_LATEST | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/bitset.h> | |||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <net/pfvar.h> | #include <net/pfvar.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <limits.h> | #include <limits.h> | ||||
#include <math.h> | #include <math.h> | ||||
#include <search.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <net/altq/altq.h> | #include <net/altq/altq.h> | ||||
#include <net/altq/altq_cbq.h> | #include <net/altq/altq_cbq.h> | ||||
#include <net/altq/altq_codel.h> | #include <net/altq/altq_codel.h> | ||||
#include <net/altq/altq_priq.h> | #include <net/altq/altq_priq.h> | ||||
#include <net/altq/altq_hfsc.h> | #include <net/altq/altq_hfsc.h> | ||||
#include <net/altq/altq_fairq.h> | #include <net/altq/altq_fairq.h> | ||||
#include "pfctl_parser.h" | #include "pfctl_parser.h" | ||||
#include "pfctl.h" | #include "pfctl.h" | ||||
#define is_sc_null(sc) (((sc) == NULL) || ((sc)->m1 == 0 && (sc)->m2 == 0)) | #define is_sc_null(sc) (((sc) == NULL) || ((sc)->m1 == 0 && (sc)->m2 == 0)) | ||||
static TAILQ_HEAD(altqs, pf_altq) altqs = TAILQ_HEAD_INITIALIZER(altqs); | static STAILQ_HEAD(interfaces, pfctl_altq) interfaces = STAILQ_HEAD_INITIALIZER(interfaces); | ||||
static LIST_HEAD(gen_sc, segment) rtsc, lssc; | static struct hsearch_data queue_map; | ||||
static struct hsearch_data if_map; | |||||
static struct hsearch_data qid_map; | |||||
struct pf_altq *qname_to_pfaltq(const char *, const char *); | static struct pfctl_altq *pfaltq_lookup(char *ifname); | ||||
u_int32_t qname_to_qid(const char *); | static struct pfctl_altq *qname_to_pfaltq(const char *, const char *); | ||||
static u_int32_t qname_to_qid(char *); | |||||
static int eval_pfqueue_cbq(struct pfctl *, struct pf_altq *); | static int eval_pfqueue_cbq(struct pfctl *, struct pf_altq *, | ||||
struct pfctl_altq *); | |||||
static int cbq_compute_idletime(struct pfctl *, struct pf_altq *); | static int cbq_compute_idletime(struct pfctl *, struct pf_altq *); | ||||
static int check_commit_cbq(int, int, struct pf_altq *); | static int check_commit_cbq(int, int, struct pfctl_altq *); | ||||
static int print_cbq_opts(const struct pf_altq *); | static int print_cbq_opts(const struct pf_altq *); | ||||
static int print_codel_opts(const struct pf_altq *, | static int print_codel_opts(const struct pf_altq *, | ||||
const struct node_queue_opt *); | const struct node_queue_opt *); | ||||
static int eval_pfqueue_priq(struct pfctl *, struct pf_altq *); | static int eval_pfqueue_priq(struct pfctl *, struct pf_altq *, | ||||
static int check_commit_priq(int, int, struct pf_altq *); | struct pfctl_altq *); | ||||
static int check_commit_priq(int, int, struct pfctl_altq *); | |||||
static int print_priq_opts(const struct pf_altq *); | static int print_priq_opts(const struct pf_altq *); | ||||
static int eval_pfqueue_hfsc(struct pfctl *, struct pf_altq *); | static int eval_pfqueue_hfsc(struct pfctl *, struct pf_altq *, | ||||
static int check_commit_hfsc(int, int, struct pf_altq *); | struct pfctl_altq *, struct pfctl_altq *); | ||||
static int check_commit_hfsc(int, int, struct pfctl_altq *); | |||||
static int print_hfsc_opts(const struct pf_altq *, | static int print_hfsc_opts(const struct pf_altq *, | ||||
const struct node_queue_opt *); | const struct node_queue_opt *); | ||||
static int eval_pfqueue_fairq(struct pfctl *, struct pf_altq *); | static int eval_pfqueue_fairq(struct pfctl *, struct pf_altq *, | ||||
struct pfctl_altq *, struct pfctl_altq *); | |||||
static int print_fairq_opts(const struct pf_altq *, | static int print_fairq_opts(const struct pf_altq *, | ||||
const struct node_queue_opt *); | const struct node_queue_opt *); | ||||
static int check_commit_fairq(int, int, struct pf_altq *); | static int check_commit_fairq(int, int, struct pfctl_altq *); | ||||
static void gsc_add_sc(struct gen_sc *, struct service_curve *); | static void gsc_add_sc(struct gen_sc *, struct service_curve *); | ||||
static int is_gsc_under_sc(struct gen_sc *, | static int is_gsc_under_sc(struct gen_sc *, | ||||
struct service_curve *); | struct service_curve *); | ||||
static void gsc_destroy(struct gen_sc *); | static void gsc_destroy(struct gen_sc *); | ||||
static struct segment *gsc_getentry(struct gen_sc *, double); | static struct segment *gsc_getentry(struct gen_sc *, double); | ||||
static int gsc_add_seg(struct gen_sc *, double, double, double, | static int gsc_add_seg(struct gen_sc *, double, double, double, | ||||
double); | double); | ||||
static double sc_x2y(struct service_curve *, double); | static double sc_x2y(struct service_curve *, double); | ||||
#ifdef __FreeBSD__ | #ifdef __FreeBSD__ | ||||
u_int64_t getifspeed(int, char *); | u_int64_t getifspeed(int, char *); | ||||
#else | #else | ||||
u_int32_t getifspeed(char *); | u_int32_t getifspeed(char *); | ||||
#endif | #endif | ||||
u_long getifmtu(char *); | u_long getifmtu(char *); | ||||
int eval_queue_opts(struct pf_altq *, struct node_queue_opt *, | int eval_queue_opts(struct pf_altq *, struct node_queue_opt *, | ||||
u_int64_t); | u_int64_t); | ||||
u_int64_t eval_bwspec(struct node_queue_bw *, u_int64_t); | u_int64_t eval_bwspec(struct node_queue_bw *, u_int64_t); | ||||
void print_hfsc_sc(const char *, u_int, u_int, u_int, | void print_hfsc_sc(const char *, u_int, u_int, u_int, | ||||
const struct node_hfsc_sc *); | const struct node_hfsc_sc *); | ||||
void print_fairq_sc(const char *, u_int, u_int, u_int, | void print_fairq_sc(const char *, u_int, u_int, u_int, | ||||
const struct node_fairq_sc *); | const struct node_fairq_sc *); | ||||
static __attribute__((constructor)) void | |||||
pfctl_altq_init(void) | |||||
{ | |||||
/* | |||||
* As hdestroy() will never be called on these tables, it will be | |||||
* safe to use references into the stored data as keys. | |||||
*/ | |||||
if (hcreate_r(0, &queue_map) == 0) | |||||
err(1, "Failed to create altq queue map"); | |||||
if (hcreate_r(0, &if_map) == 0) | |||||
err(1, "Failed to create altq interface map"); | |||||
if (hcreate_r(0, &qid_map) == 0) | |||||
err(1, "Failed to create altq queue id map"); | |||||
} | |||||
void | void | ||||
pfaltq_store(struct pf_altq *a) | pfaltq_store(struct pf_altq *a) | ||||
{ | { | ||||
struct pf_altq *altq; | struct pfctl_altq *altq; | ||||
ENTRY item; | |||||
ENTRY *ret_item; | |||||
size_t key_size; | |||||
if ((altq = malloc(sizeof(*altq))) == NULL) | if ((altq = malloc(sizeof(*altq))) == NULL) | ||||
err(1, "malloc"); | err(1, "queue malloc"); | ||||
memcpy(altq, a, sizeof(struct pf_altq)); | memcpy(&altq->pa, a, sizeof(struct pf_altq)); | ||||
TAILQ_INSERT_TAIL(&altqs, altq, entries); | memset(&altq->meta, 0, sizeof(altq->meta)); | ||||
if (a->qname[0] == 0) { | |||||
item.key = altq->pa.ifname; | |||||
item.data = altq; | |||||
if (hsearch_r(item, ENTER, &ret_item, &if_map) == 0) | |||||
err(1, "interface map insert"); | |||||
STAILQ_INSERT_TAIL(&interfaces, altq, meta.link); | |||||
} else { | |||||
key_size = sizeof(a->ifname) + sizeof(a->qname); | |||||
if ((item.key = malloc(key_size)) == NULL) | |||||
err(1, "queue map key malloc"); | |||||
snprintf(item.key, key_size, "%s:%s", a->ifname, a->qname); | |||||
item.data = altq; | |||||
if (hsearch_r(item, ENTER, &ret_item, &queue_map) == 0) | |||||
err(1, "queue map insert"); | |||||
item.key = altq->pa.qname; | |||||
item.data = &altq->pa.qid; | |||||
if (hsearch_r(item, ENTER, &ret_item, &qid_map) == 0) | |||||
err(1, "qid map insert"); | |||||
} | } | ||||
} | |||||
struct pf_altq * | static struct pfctl_altq * | ||||
pfaltq_lookup(const char *ifname) | pfaltq_lookup(char *ifname) | ||||
{ | { | ||||
struct pf_altq *altq; | ENTRY item; | ||||
ENTRY *ret_item; | |||||
TAILQ_FOREACH(altq, &altqs, entries) { | item.key = ifname; | ||||
if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 && | if (hsearch_r(item, FIND, &ret_item, &if_map) == 0) | ||||
altq->qname[0] == 0) | |||||
return (altq); | |||||
} | |||||
return (NULL); | return (NULL); | ||||
return (ret_item->data); | |||||
} | } | ||||
struct pf_altq * | static struct pfctl_altq * | ||||
qname_to_pfaltq(const char *qname, const char *ifname) | qname_to_pfaltq(const char *qname, const char *ifname) | ||||
{ | { | ||||
struct pf_altq *altq; | ENTRY item; | ||||
ENTRY *ret_item; | |||||
char key[IFNAMSIZ + PF_QNAME_SIZE]; | |||||
TAILQ_FOREACH(altq, &altqs, entries) { | item.key = key; | ||||
if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 && | snprintf(item.key, sizeof(key), "%s:%s", ifname, qname); | ||||
strncmp(qname, altq->qname, PF_QNAME_SIZE) == 0) | if (hsearch_r(item, FIND, &ret_item, &queue_map) == 0) | ||||
return (altq); | |||||
} | |||||
return (NULL); | return (NULL); | ||||
return (ret_item->data); | |||||
} | } | ||||
u_int32_t | static u_int32_t | ||||
qname_to_qid(const char *qname) | qname_to_qid(char *qname) | ||||
{ | { | ||||
struct pf_altq *altq; | ENTRY item; | ||||
ENTRY *ret_item; | |||||
uint32_t qid; | |||||
/* | /* | ||||
* We guarantee that same named queues on different interfaces | * We guarantee that same named queues on different interfaces | ||||
* have the same qid, so we do NOT need to limit matching on | * have the same qid. | ||||
* one interface! | |||||
*/ | */ | ||||
item.key = qname; | |||||
if (hsearch_r(item, FIND, &ret_item, &qid_map) == 0) | |||||
return (0); | |||||
TAILQ_FOREACH(altq, &altqs, entries) { | qid = *(uint32_t *)ret_item->data; | ||||
if (strncmp(qname, altq->qname, PF_QNAME_SIZE) == 0) | return (qid); | ||||
return (altq->qid); | |||||
} | } | ||||
return (0); | |||||
} | |||||
void | void | ||||
print_altq(const struct pf_altq *a, unsigned int level, | print_altq(const struct pf_altq *a, unsigned int level, | ||||
struct node_queue_bw *bw, struct node_queue_opt *qopts) | struct node_queue_bw *bw, struct node_queue_opt *qopts) | ||||
{ | { | ||||
if (a->qname[0] != 0) { | if (a->qname[0] != 0) { | ||||
print_queue(a, level, bw, 1, qopts); | print_queue(a, level, bw, 1, qopts); | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* check_commit_altq does consistency check for each interface | * check_commit_altq does consistency check for each interface | ||||
*/ | */ | ||||
int | int | ||||
check_commit_altq(int dev, int opts) | check_commit_altq(int dev, int opts) | ||||
{ | { | ||||
struct pf_altq *altq; | struct pfctl_altq *if_ppa; | ||||
int error = 0; | int error = 0; | ||||
/* call the discipline check for each interface. */ | /* call the discipline check for each interface. */ | ||||
TAILQ_FOREACH(altq, &altqs, entries) { | STAILQ_FOREACH(if_ppa, &interfaces, meta.link) { | ||||
if (altq->qname[0] == 0) { | switch (if_ppa->pa.scheduler) { | ||||
switch (altq->scheduler) { | |||||
case ALTQT_CBQ: | case ALTQT_CBQ: | ||||
error = check_commit_cbq(dev, opts, altq); | error = check_commit_cbq(dev, opts, if_ppa); | ||||
break; | break; | ||||
case ALTQT_PRIQ: | case ALTQT_PRIQ: | ||||
error = check_commit_priq(dev, opts, altq); | error = check_commit_priq(dev, opts, if_ppa); | ||||
break; | break; | ||||
case ALTQT_HFSC: | case ALTQT_HFSC: | ||||
error = check_commit_hfsc(dev, opts, altq); | error = check_commit_hfsc(dev, opts, if_ppa); | ||||
break; | break; | ||||
case ALTQT_FAIRQ: | case ALTQT_FAIRQ: | ||||
error = check_commit_fairq(dev, opts, altq); | error = check_commit_fairq(dev, opts, if_ppa); | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | |||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* eval_pfqueue computes the queue parameters. | * eval_pfqueue computes the queue parameters. | ||||
*/ | */ | ||||
int | int | ||||
eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, | eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, | ||||
struct node_queue_opt *opts) | struct node_queue_opt *opts) | ||||
{ | { | ||||
/* should be merged with expand_queue */ | /* should be merged with expand_queue */ | ||||
struct pf_altq *if_pa, *parent, *altq; | struct pfctl_altq *if_ppa, *parent; | ||||
u_int64_t bwsum; | |||||
int error = 0; | int error = 0; | ||||
/* find the corresponding interface and copy fields used by queues */ | /* find the corresponding interface and copy fields used by queues */ | ||||
if ((if_pa = pfaltq_lookup(pa->ifname)) == NULL) { | if ((if_ppa = pfaltq_lookup(pa->ifname)) == NULL) { | ||||
fprintf(stderr, "altq not defined on %s\n", pa->ifname); | fprintf(stderr, "altq not defined on %s\n", pa->ifname); | ||||
return (1); | return (1); | ||||
} | } | ||||
pa->scheduler = if_pa->scheduler; | pa->scheduler = if_ppa->pa.scheduler; | ||||
pa->ifbandwidth = if_pa->ifbandwidth; | pa->ifbandwidth = if_ppa->pa.ifbandwidth; | ||||
if (qname_to_pfaltq(pa->qname, pa->ifname) != NULL) { | if (qname_to_pfaltq(pa->qname, pa->ifname) != NULL) { | ||||
fprintf(stderr, "queue %s already exists on interface %s\n", | fprintf(stderr, "queue %s already exists on interface %s\n", | ||||
pa->qname, pa->ifname); | pa->qname, pa->ifname); | ||||
return (1); | return (1); | ||||
} | } | ||||
pa->qid = qname_to_qid(pa->qname); | pa->qid = qname_to_qid(pa->qname); | ||||
parent = NULL; | parent = NULL; | ||||
if (pa->parent[0] != 0) { | if (pa->parent[0] != 0) { | ||||
parent = qname_to_pfaltq(pa->parent, pa->ifname); | parent = qname_to_pfaltq(pa->parent, pa->ifname); | ||||
if (parent == NULL) { | if (parent == NULL) { | ||||
fprintf(stderr, "parent %s not found for %s\n", | fprintf(stderr, "parent %s not found for %s\n", | ||||
pa->parent, pa->qname); | pa->parent, pa->qname); | ||||
return (1); | return (1); | ||||
} | } | ||||
pa->parent_qid = parent->qid; | pa->parent_qid = parent->pa.qid; | ||||
} | } | ||||
if (pa->qlimit == 0) | if (pa->qlimit == 0) | ||||
pa->qlimit = DEFAULT_QLIMIT; | pa->qlimit = DEFAULT_QLIMIT; | ||||
if (eval_queue_opts(pa, opts, | |||||
parent == NULL ? pa->ifbandwidth : parent->pa.bandwidth)) | |||||
return (1); | |||||
if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC || | if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC || | ||||
pa->scheduler == ALTQT_FAIRQ) { | pa->scheduler == ALTQT_FAIRQ) { | ||||
pa->bandwidth = eval_bwspec(bw, | pa->bandwidth = eval_bwspec(bw, | ||||
parent == NULL ? pa->ifbandwidth : parent->bandwidth); | parent == NULL ? pa->ifbandwidth : parent->pa.bandwidth); | ||||
/* | |||||
* For HFSC, if the linkshare service curve m2 parameter is | |||||
* set, it overrides the provided queue bandwidth parameter, | |||||
* so adjust the queue bandwidth parameter accordingly here | |||||
* to avoid false positives in the total child bandwidth | |||||
* check below. | |||||
*/ | |||||
if ((pa->scheduler == ALTQT_HFSC) && | |||||
(pa->pq_u.hfsc_opts.lssc_m2 != 0)) { | |||||
pa->bandwidth = pa->pq_u.hfsc_opts.lssc_m2; | |||||
} | |||||
if (pa->bandwidth > pa->ifbandwidth) { | if (pa->bandwidth > pa->ifbandwidth) { | ||||
fprintf(stderr, "bandwidth for %s higher than " | fprintf(stderr, "bandwidth for %s higher than " | ||||
"interface\n", pa->qname); | "interface\n", pa->qname); | ||||
return (1); | return (1); | ||||
} | } | ||||
/* check the sum of the child bandwidth is under parent's */ | /* check the sum of the child bandwidth is under parent's */ | ||||
if (parent != NULL) { | if (parent != NULL) { | ||||
if (pa->bandwidth > parent->bandwidth) { | if (pa->bandwidth > parent->pa.bandwidth) { | ||||
warnx("bandwidth for %s higher than parent", | warnx("bandwidth for %s higher than parent", | ||||
pa->qname); | pa->qname); | ||||
return (1); | return (1); | ||||
} | } | ||||
bwsum = 0; | parent->meta.bwsum += pa->bandwidth; | ||||
TAILQ_FOREACH(altq, &altqs, entries) { | if (parent->meta.bwsum > parent->pa.bandwidth) { | ||||
if (strncmp(altq->ifname, pa->ifname, | warnx("the sum of the child bandwidth (%" PRIu64 | ||||
IFNAMSIZ) == 0 && | ") higher than parent \"%s\" (%" PRIu64 ")", | ||||
altq->qname[0] != 0 && | parent->meta.bwsum, parent->pa.qname, | ||||
strncmp(altq->parent, pa->parent, | parent->pa.bandwidth); | ||||
PF_QNAME_SIZE) == 0) | |||||
bwsum += altq->bandwidth; | |||||
} | } | ||||
bwsum += pa->bandwidth; | |||||
if (bwsum > parent->bandwidth) { | |||||
warnx("the sum of the child bandwidth higher" | |||||
" than parent \"%s\"", parent->qname); | |||||
} | } | ||||
} | } | ||||
} | |||||
if (eval_queue_opts(pa, opts, | if (parent != NULL) | ||||
parent == NULL ? pa->ifbandwidth : parent->bandwidth)) | parent->meta.children++; | ||||
return (1); | |||||
switch (pa->scheduler) { | switch (pa->scheduler) { | ||||
case ALTQT_CBQ: | case ALTQT_CBQ: | ||||
error = eval_pfqueue_cbq(pf, pa); | error = eval_pfqueue_cbq(pf, pa, if_ppa); | ||||
break; | break; | ||||
case ALTQT_PRIQ: | case ALTQT_PRIQ: | ||||
error = eval_pfqueue_priq(pf, pa); | error = eval_pfqueue_priq(pf, pa, if_ppa); | ||||
break; | break; | ||||
case ALTQT_HFSC: | case ALTQT_HFSC: | ||||
error = eval_pfqueue_hfsc(pf, pa); | error = eval_pfqueue_hfsc(pf, pa, if_ppa, parent); | ||||
break; | break; | ||||
case ALTQT_FAIRQ: | case ALTQT_FAIRQ: | ||||
error = eval_pfqueue_fairq(pf, pa); | error = eval_pfqueue_fairq(pf, pa, if_ppa, parent); | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* CBQ support functions | * CBQ support functions | ||||
*/ | */ | ||||
#define RM_FILTER_GAIN 5 /* log2 of gain, e.g., 5 => 31/32 */ | #define RM_FILTER_GAIN 5 /* log2 of gain, e.g., 5 => 31/32 */ | ||||
#define RM_NS_PER_SEC (1000000000) | #define RM_NS_PER_SEC (1000000000) | ||||
static int | static int | ||||
eval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *pa) | eval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *pa, struct pfctl_altq *if_ppa) | ||||
{ | { | ||||
struct cbq_opts *opts; | struct cbq_opts *opts; | ||||
u_int ifmtu; | u_int ifmtu; | ||||
if (pa->priority >= CBQ_MAXPRI) { | if (pa->priority >= CBQ_MAXPRI) { | ||||
warnx("priority out of range: max %d", CBQ_MAXPRI - 1); | warnx("priority out of range: max %d", CBQ_MAXPRI - 1); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
Show All 13 Lines | else if (opts->maxpktsize > ifmtu) | ||||
opts->pktsize = ifmtu; | opts->pktsize = ifmtu; | ||||
if (opts->pktsize > opts->maxpktsize) | if (opts->pktsize > opts->maxpktsize) | ||||
opts->pktsize = opts->maxpktsize; | opts->pktsize = opts->maxpktsize; | ||||
if (pa->parent[0] == 0) | if (pa->parent[0] == 0) | ||||
opts->flags |= (CBQCLF_ROOTCLASS | CBQCLF_WRR); | opts->flags |= (CBQCLF_ROOTCLASS | CBQCLF_WRR); | ||||
if (pa->pq_u.cbq_opts.flags & CBQCLF_ROOTCLASS) | |||||
if_ppa->meta.root_classes++; | |||||
if (pa->pq_u.cbq_opts.flags & CBQCLF_DEFCLASS) | |||||
if_ppa->meta.default_classes++; | |||||
cbq_compute_idletime(pf, pa); | cbq_compute_idletime(pf, pa); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* compute ns_per_byte, maxidle, minidle, and offtime | * compute ns_per_byte, maxidle, minidle, and offtime | ||||
*/ | */ | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa) | ||||
opts->maxidle = (u_int)fabs(maxidle); | opts->maxidle = (u_int)fabs(maxidle); | ||||
opts->minidle = (int)minidle; | opts->minidle = (int)minidle; | ||||
opts->offtime = (u_int)fabs(offtime); | opts->offtime = (u_int)fabs(offtime); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
check_commit_cbq(int dev, int opts, struct pf_altq *pa) | check_commit_cbq(int dev, int opts, struct pfctl_altq *if_ppa) | ||||
{ | { | ||||
struct pf_altq *altq; | |||||
int root_class, default_class; | |||||
int error = 0; | int error = 0; | ||||
/* | /* | ||||
* check if cbq has one root queue and one default queue | * check if cbq has one root queue and one default queue | ||||
* for this interface | * for this interface | ||||
*/ | */ | ||||
root_class = default_class = 0; | if (if_ppa->meta.root_classes != 1) { | ||||
TAILQ_FOREACH(altq, &altqs, entries) { | warnx("should have one root queue on %s", if_ppa->pa.ifname); | ||||
if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) | |||||
continue; | |||||
if (altq->qname[0] == 0) /* this is for interface */ | |||||
continue; | |||||
if (altq->pq_u.cbq_opts.flags & CBQCLF_ROOTCLASS) | |||||
root_class++; | |||||
if (altq->pq_u.cbq_opts.flags & CBQCLF_DEFCLASS) | |||||
default_class++; | |||||
} | |||||
if (root_class != 1) { | |||||
warnx("should have one root queue on %s", pa->ifname); | |||||
error++; | error++; | ||||
} | } | ||||
if (default_class != 1) { | if (if_ppa->meta.default_classes != 1) { | ||||
warnx("should have one default queue on %s", pa->ifname); | warnx("should have one default queue on %s", if_ppa->pa.ifname); | ||||
error++; | error++; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
print_cbq_opts(const struct pf_altq *a) | print_cbq_opts(const struct pf_altq *a) | ||||
{ | { | ||||
Show All 30 Lines | print_cbq_opts(const struct pf_altq *a) | ||||
} else | } else | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* PRIQ support functions | * PRIQ support functions | ||||
*/ | */ | ||||
static int | static int | ||||
eval_pfqueue_priq(struct pfctl *pf, struct pf_altq *pa) | eval_pfqueue_priq(struct pfctl *pf, struct pf_altq *pa, struct pfctl_altq *if_ppa) | ||||
{ | { | ||||
struct pf_altq *altq; | |||||
if (pa->priority >= PRIQ_MAXPRI) { | if (pa->priority >= PRIQ_MAXPRI) { | ||||
warnx("priority out of range: max %d", PRIQ_MAXPRI - 1); | warnx("priority out of range: max %d", PRIQ_MAXPRI - 1); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
/* the priority should be unique for the interface */ | if (BIT_ISSET(QPRI_BITSET_SIZE, pa->priority, &if_ppa->meta.qpris)) { | ||||
TAILQ_FOREACH(altq, &altqs, entries) { | warnx("%s does not have a unique priority on interface %s", | ||||
if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) == 0 && | pa->qname, pa->ifname); | ||||
altq->qname[0] != 0 && altq->priority == pa->priority) { | |||||
warnx("%s and %s have the same priority", | |||||
altq->qname, pa->qname); | |||||
return (-1); | return (-1); | ||||
} | } else | ||||
} | BIT_SET(QPRI_BITSET_SIZE, pa->priority, &if_ppa->meta.qpris); | ||||
if (pa->pq_u.priq_opts.flags & PRCF_DEFAULTCLASS) | |||||
if_ppa->meta.default_classes++; | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
check_commit_priq(int dev, int opts, struct pf_altq *pa) | check_commit_priq(int dev, int opts, struct pfctl_altq *if_ppa) | ||||
{ | { | ||||
struct pf_altq *altq; | |||||
int default_class; | |||||
int error = 0; | |||||
/* | /* | ||||
* check if priq has one default class for this interface | * check if priq has one default class for this interface | ||||
*/ | */ | ||||
default_class = 0; | if (if_ppa->meta.default_classes != 1) { | ||||
TAILQ_FOREACH(altq, &altqs, entries) { | warnx("should have one default queue on %s", if_ppa->pa.ifname); | ||||
if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) | return (1); | ||||
continue; | |||||
if (altq->qname[0] == 0) /* this is for interface */ | |||||
continue; | |||||
if (altq->pq_u.priq_opts.flags & PRCF_DEFAULTCLASS) | |||||
default_class++; | |||||
} | } | ||||
if (default_class != 1) { | return (0); | ||||
warnx("should have one default queue on %s", pa->ifname); | |||||
error++; | |||||
} | } | ||||
return (error); | |||||
} | |||||
static int | static int | ||||
print_priq_opts(const struct pf_altq *a) | print_priq_opts(const struct pf_altq *a) | ||||
{ | { | ||||
const struct priq_opts *opts; | const struct priq_opts *opts; | ||||
opts = &a->pq_u.priq_opts; | opts = &a->pq_u.priq_opts; | ||||
Show All 17 Lines | print_priq_opts(const struct pf_altq *a) | ||||
} else | } else | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* HFSC support functions | * HFSC support functions | ||||
*/ | */ | ||||
static int | static int | ||||
eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) | eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa, struct pfctl_altq *if_ppa, | ||||
struct pfctl_altq *parent) | |||||
{ | { | ||||
struct pf_altq *altq, *parent; | |||||
struct hfsc_opts_v1 *opts; | struct hfsc_opts_v1 *opts; | ||||
struct service_curve sc; | struct service_curve sc; | ||||
opts = &pa->pq_u.hfsc_opts; | opts = &pa->pq_u.hfsc_opts; | ||||
if (pa->parent[0] == 0) { | if (parent == NULL) { | ||||
/* root queue */ | /* root queue */ | ||||
opts->lssc_m1 = pa->ifbandwidth; | opts->lssc_m1 = pa->ifbandwidth; | ||||
opts->lssc_m2 = pa->ifbandwidth; | opts->lssc_m2 = pa->ifbandwidth; | ||||
opts->lssc_d = 0; | opts->lssc_d = 0; | ||||
return (0); | return (0); | ||||
} | } | ||||
LIST_INIT(&rtsc); | /* First child initializes the parent's service curve accumulators. */ | ||||
LIST_INIT(&lssc); | if (parent->meta.children == 1) { | ||||
LIST_INIT(&parent->meta.rtsc); | |||||
LIST_INIT(&parent->meta.lssc); | |||||
} | |||||
if (parent->pa.pq_u.hfsc_opts.flags & HFCF_DEFAULTCLASS) { | |||||
warnx("adding %s would make default queue %s not a leaf", | |||||
pa->qname, pa->parent); | |||||
return (-1); | |||||
} | |||||
if (pa->pq_u.hfsc_opts.flags & HFCF_DEFAULTCLASS) | |||||
if_ppa->meta.default_classes++; | |||||
/* if link_share is not specified, use bandwidth */ | /* if link_share is not specified, use bandwidth */ | ||||
if (opts->lssc_m2 == 0) | if (opts->lssc_m2 == 0) | ||||
opts->lssc_m2 = pa->bandwidth; | opts->lssc_m2 = pa->bandwidth; | ||||
if ((opts->rtsc_m1 > 0 && opts->rtsc_m2 == 0) || | if ((opts->rtsc_m1 > 0 && opts->rtsc_m2 == 0) || | ||||
(opts->lssc_m1 > 0 && opts->lssc_m2 == 0) || | (opts->lssc_m1 > 0 && opts->lssc_m2 == 0) || | ||||
(opts->ulsc_m1 > 0 && opts->ulsc_m2 == 0)) { | (opts->ulsc_m1 > 0 && opts->ulsc_m2 == 0)) { | ||||
warnx("m2 is zero for %s", pa->qname); | warnx("m2 is zero for %s", pa->qname); | ||||
Show All 13 Lines | eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa, struct pfctl_altq *if_ppa, | ||||
* should not exceed 80% of the interface bandwidth. 20% is reserved | * should not exceed 80% of the interface bandwidth. 20% is reserved | ||||
* not to over-commit the actual interface bandwidth. | * not to over-commit the actual interface bandwidth. | ||||
* for the linkshare service curve, the sum of the child service | * for the linkshare service curve, the sum of the child service | ||||
* curve should not exceed the parent service curve. | * curve should not exceed the parent service curve. | ||||
* for the upper-limit service curve, the assigned bandwidth should | * for the upper-limit service curve, the assigned bandwidth should | ||||
* be smaller than the interface bandwidth, and the upper-limit should | * be smaller than the interface bandwidth, and the upper-limit should | ||||
* be larger than the real-time service curve when both are defined. | * be larger than the real-time service curve when both are defined. | ||||
*/ | */ | ||||
parent = qname_to_pfaltq(pa->parent, pa->ifname); | |||||
if (parent == NULL) | |||||
errx(1, "parent %s not found for %s", pa->parent, pa->qname); | |||||
TAILQ_FOREACH(altq, &altqs, entries) { | |||||
if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) | |||||
continue; | |||||
if (altq->qname[0] == 0) /* this is for interface */ | |||||
continue; | |||||
/* if the class has a real-time service curve, add it. */ | |||||
if (opts->rtsc_m2 != 0 && altq->pq_u.hfsc_opts.rtsc_m2 != 0) { | |||||
sc.m1 = altq->pq_u.hfsc_opts.rtsc_m1; | |||||
sc.d = altq->pq_u.hfsc_opts.rtsc_d; | |||||
sc.m2 = altq->pq_u.hfsc_opts.rtsc_m2; | |||||
gsc_add_sc(&rtsc, &sc); | |||||
} | |||||
if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0) | |||||
continue; | |||||
/* if the class has a linkshare service curve, add it. */ | |||||
if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) { | |||||
sc.m1 = altq->pq_u.hfsc_opts.lssc_m1; | |||||
sc.d = altq->pq_u.hfsc_opts.lssc_d; | |||||
sc.m2 = altq->pq_u.hfsc_opts.lssc_m2; | |||||
gsc_add_sc(&lssc, &sc); | |||||
} | |||||
} | |||||
/* check the real-time service curve. reserve 20% of interface bw */ | /* check the real-time service curve. reserve 20% of interface bw */ | ||||
if (opts->rtsc_m2 != 0) { | if (opts->rtsc_m2 != 0) { | ||||
/* add this queue to the sum */ | /* add this queue to the sum */ | ||||
sc.m1 = opts->rtsc_m1; | sc.m1 = opts->rtsc_m1; | ||||
sc.d = opts->rtsc_d; | sc.d = opts->rtsc_d; | ||||
sc.m2 = opts->rtsc_m2; | sc.m2 = opts->rtsc_m2; | ||||
gsc_add_sc(&rtsc, &sc); | gsc_add_sc(&parent->meta.rtsc, &sc); | ||||
/* compare the sum with 80% of the interface */ | /* compare the sum with 80% of the interface */ | ||||
sc.m1 = 0; | sc.m1 = 0; | ||||
sc.d = 0; | sc.d = 0; | ||||
sc.m2 = pa->ifbandwidth / 100 * 80; | sc.m2 = pa->ifbandwidth / 100 * 80; | ||||
if (!is_gsc_under_sc(&rtsc, &sc)) { | if (!is_gsc_under_sc(&parent->meta.rtsc, &sc)) { | ||||
warnx("real-time sc exceeds 80%% of the interface " | warnx("real-time sc exceeds 80%% of the interface " | ||||
"bandwidth (%s)", rate2str((double)sc.m2)); | "bandwidth (%s)", rate2str((double)sc.m2)); | ||||
goto err_ret; | return (-1); | ||||
} | } | ||||
} | } | ||||
/* check the linkshare service curve. */ | /* check the linkshare service curve. */ | ||||
if (opts->lssc_m2 != 0) { | if (opts->lssc_m2 != 0) { | ||||
/* add this queue to the child sum */ | /* add this queue to the child sum */ | ||||
sc.m1 = opts->lssc_m1; | sc.m1 = opts->lssc_m1; | ||||
sc.d = opts->lssc_d; | sc.d = opts->lssc_d; | ||||
sc.m2 = opts->lssc_m2; | sc.m2 = opts->lssc_m2; | ||||
gsc_add_sc(&lssc, &sc); | gsc_add_sc(&parent->meta.lssc, &sc); | ||||
/* compare the sum of the children with parent's sc */ | /* compare the sum of the children with parent's sc */ | ||||
sc.m1 = parent->pq_u.hfsc_opts.lssc_m1; | sc.m1 = parent->pa.pq_u.hfsc_opts.lssc_m1; | ||||
sc.d = parent->pq_u.hfsc_opts.lssc_d; | sc.d = parent->pa.pq_u.hfsc_opts.lssc_d; | ||||
sc.m2 = parent->pq_u.hfsc_opts.lssc_m2; | sc.m2 = parent->pa.pq_u.hfsc_opts.lssc_m2; | ||||
if (!is_gsc_under_sc(&lssc, &sc)) { | if (!is_gsc_under_sc(&parent->meta.lssc, &sc)) { | ||||
warnx("linkshare sc exceeds parent's sc"); | warnx("linkshare sc exceeds parent's sc"); | ||||
goto err_ret; | return (-1); | ||||
} | } | ||||
} | } | ||||
/* check the upper-limit service curve. */ | /* check the upper-limit service curve. */ | ||||
if (opts->ulsc_m2 != 0) { | if (opts->ulsc_m2 != 0) { | ||||
if (opts->ulsc_m1 > pa->ifbandwidth || | if (opts->ulsc_m1 > pa->ifbandwidth || | ||||
opts->ulsc_m2 > pa->ifbandwidth) { | opts->ulsc_m2 > pa->ifbandwidth) { | ||||
warnx("upper-limit larger than interface bandwidth"); | warnx("upper-limit larger than interface bandwidth"); | ||||
goto err_ret; | return (-1); | ||||
} | } | ||||
if (opts->rtsc_m2 != 0 && opts->rtsc_m2 > opts->ulsc_m2) { | if (opts->rtsc_m2 != 0 && opts->rtsc_m2 > opts->ulsc_m2) { | ||||
warnx("upper-limit sc smaller than real-time sc"); | warnx("upper-limit sc smaller than real-time sc"); | ||||
goto err_ret; | return (-1); | ||||
} | } | ||||
} | } | ||||
gsc_destroy(&rtsc); | |||||
gsc_destroy(&lssc); | |||||
return (0); | return (0); | ||||
err_ret: | |||||
gsc_destroy(&rtsc); | |||||
gsc_destroy(&lssc); | |||||
return (-1); | |||||
} | } | ||||
/* | /* | ||||
* FAIRQ support functions | * FAIRQ support functions | ||||
*/ | */ | ||||
static int | static int | ||||
eval_pfqueue_fairq(struct pfctl *pf __unused, struct pf_altq *pa) | eval_pfqueue_fairq(struct pfctl *pf __unused, struct pf_altq *pa, | ||||
struct pfctl_altq *if_ppa, struct pfctl_altq *parent) | |||||
{ | { | ||||
struct pf_altq *altq, *parent; | |||||
struct fairq_opts *opts; | struct fairq_opts *opts; | ||||
struct service_curve sc; | struct service_curve sc; | ||||
opts = &pa->pq_u.fairq_opts; | opts = &pa->pq_u.fairq_opts; | ||||
if (pa->parent[0] == 0) { | if (pa->parent == NULL) { | ||||
/* root queue */ | /* root queue */ | ||||
opts->lssc_m1 = pa->ifbandwidth; | opts->lssc_m1 = pa->ifbandwidth; | ||||
opts->lssc_m2 = pa->ifbandwidth; | opts->lssc_m2 = pa->ifbandwidth; | ||||
opts->lssc_d = 0; | opts->lssc_d = 0; | ||||
return (0); | return (0); | ||||
} | } | ||||
LIST_INIT(&lssc); | /* First child initializes the parent's service curve accumulator. */ | ||||
if (parent->meta.children == 1) | |||||
LIST_INIT(&parent->meta.lssc); | |||||
if (parent->pa.pq_u.fairq_opts.flags & FARF_DEFAULTCLASS) { | |||||
warnx("adding %s would make default queue %s not a leaf", | |||||
pa->qname, pa->parent); | |||||
return (-1); | |||||
} | |||||
if (pa->pq_u.fairq_opts.flags & FARF_DEFAULTCLASS) | |||||
if_ppa->meta.default_classes++; | |||||
/* if link_share is not specified, use bandwidth */ | /* if link_share is not specified, use bandwidth */ | ||||
if (opts->lssc_m2 == 0) | if (opts->lssc_m2 == 0) | ||||
opts->lssc_m2 = pa->bandwidth; | opts->lssc_m2 = pa->bandwidth; | ||||
/* | /* | ||||
* admission control: | * admission control: | ||||
* for the real-time service curve, the sum of the service curves | * for the real-time service curve, the sum of the service curves | ||||
* should not exceed 80% of the interface bandwidth. 20% is reserved | * should not exceed 80% of the interface bandwidth. 20% is reserved | ||||
* not to over-commit the actual interface bandwidth. | * not to over-commit the actual interface bandwidth. | ||||
* for the link-sharing service curve, the sum of the child service | * for the link-sharing service curve, the sum of the child service | ||||
* curve should not exceed the parent service curve. | * curve should not exceed the parent service curve. | ||||
* for the upper-limit service curve, the assigned bandwidth should | * for the upper-limit service curve, the assigned bandwidth should | ||||
* be smaller than the interface bandwidth, and the upper-limit should | * be smaller than the interface bandwidth, and the upper-limit should | ||||
* be larger than the real-time service curve when both are defined. | * be larger than the real-time service curve when both are defined. | ||||
*/ | */ | ||||
parent = qname_to_pfaltq(pa->parent, pa->ifname); | |||||
if (parent == NULL) | |||||
errx(1, "parent %s not found for %s", pa->parent, pa->qname); | |||||
TAILQ_FOREACH(altq, &altqs, entries) { | /* check the linkshare service curve. */ | ||||
if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) | |||||
continue; | |||||
if (altq->qname[0] == 0) /* this is for interface */ | |||||
continue; | |||||
if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0) | |||||
continue; | |||||
/* if the class has a link-sharing service curve, add it. */ | |||||
if (opts->lssc_m2 != 0 && altq->pq_u.fairq_opts.lssc_m2 != 0) { | |||||
sc.m1 = altq->pq_u.fairq_opts.lssc_m1; | |||||
sc.d = altq->pq_u.fairq_opts.lssc_d; | |||||
sc.m2 = altq->pq_u.fairq_opts.lssc_m2; | |||||
gsc_add_sc(&lssc, &sc); | |||||
} | |||||
} | |||||
/* check the link-sharing service curve. */ | |||||
if (opts->lssc_m2 != 0) { | if (opts->lssc_m2 != 0) { | ||||
sc.m1 = parent->pq_u.fairq_opts.lssc_m1; | /* add this queue to the child sum */ | ||||
sc.d = parent->pq_u.fairq_opts.lssc_d; | sc.m1 = opts->lssc_m1; | ||||
sc.m2 = parent->pq_u.fairq_opts.lssc_m2; | sc.d = opts->lssc_d; | ||||
if (!is_gsc_under_sc(&lssc, &sc)) { | sc.m2 = opts->lssc_m2; | ||||
gsc_add_sc(&parent->meta.lssc, &sc); | |||||
/* compare the sum of the children with parent's sc */ | |||||
sc.m1 = parent->pa.pq_u.fairq_opts.lssc_m1; | |||||
sc.d = parent->pa.pq_u.fairq_opts.lssc_d; | |||||
sc.m2 = parent->pa.pq_u.fairq_opts.lssc_m2; | |||||
if (!is_gsc_under_sc(&parent->meta.lssc, &sc)) { | |||||
warnx("link-sharing sc exceeds parent's sc"); | warnx("link-sharing sc exceeds parent's sc"); | ||||
goto err_ret; | return (-1); | ||||
} | } | ||||
} | } | ||||
gsc_destroy(&lssc); | |||||
return (0); | return (0); | ||||
err_ret: | |||||
gsc_destroy(&lssc); | |||||
return (-1); | |||||
} | } | ||||
static int | static int | ||||
check_commit_hfsc(int dev, int opts, struct pf_altq *pa) | check_commit_hfsc(int dev, int opts, struct pfctl_altq *if_ppa) | ||||
{ | { | ||||
struct pf_altq *altq, *def = NULL; | |||||
int default_class; | |||||
int error = 0; | |||||
/* check if hfsc has one default queue for this interface */ | /* check if hfsc has one default queue for this interface */ | ||||
default_class = 0; | if (if_ppa->meta.default_classes != 1) { | ||||
TAILQ_FOREACH(altq, &altqs, entries) { | warnx("should have one default queue on %s", if_ppa->pa.ifname); | ||||
if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) | |||||
continue; | |||||
if (altq->qname[0] == 0) /* this is for interface */ | |||||
continue; | |||||
if (altq->parent[0] == 0) /* dummy root */ | |||||
continue; | |||||
if (altq->pq_u.hfsc_opts.flags & HFCF_DEFAULTCLASS) { | |||||
default_class++; | |||||
def = altq; | |||||
} | |||||
} | |||||
if (default_class != 1) { | |||||
warnx("should have one default queue on %s", pa->ifname); | |||||
return (1); | return (1); | ||||
} | } | ||||
/* make sure the default queue is a leaf */ | return (0); | ||||
TAILQ_FOREACH(altq, &altqs, entries) { | |||||
if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) | |||||
continue; | |||||
if (altq->qname[0] == 0) /* this is for interface */ | |||||
continue; | |||||
if (strncmp(altq->parent, def->qname, PF_QNAME_SIZE) == 0) { | |||||
warnx("default queue is not a leaf"); | |||||
error++; | |||||
} | } | ||||
} | |||||
return (error); | |||||
} | |||||
static int | static int | ||||
check_commit_fairq(int dev __unused, int opts __unused, struct pf_altq *pa) | check_commit_fairq(int dev __unused, int opts __unused, struct pfctl_altq *if_ppa) | ||||
{ | { | ||||
struct pf_altq *altq, *def = NULL; | |||||
int default_class; | |||||
int error = 0; | |||||
/* check if fairq has one default queue for this interface */ | /* check if fairq has one default queue for this interface */ | ||||
default_class = 0; | if (if_ppa->meta.default_classes != 1) { | ||||
TAILQ_FOREACH(altq, &altqs, entries) { | warnx("should have one default queue on %s", if_ppa->pa.ifname); | ||||
if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) | |||||
continue; | |||||
if (altq->qname[0] == 0) /* this is for interface */ | |||||
continue; | |||||
if (altq->pq_u.fairq_opts.flags & FARF_DEFAULTCLASS) { | |||||
default_class++; | |||||
def = altq; | |||||
} | |||||
} | |||||
if (default_class != 1) { | |||||
warnx("should have one default queue on %s", pa->ifname); | |||||
return (1); | return (1); | ||||
} | } | ||||
/* make sure the default queue is a leaf */ | return (0); | ||||
TAILQ_FOREACH(altq, &altqs, entries) { | |||||
if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) | |||||
continue; | |||||
if (altq->qname[0] == 0) /* this is for interface */ | |||||
continue; | |||||
if (strncmp(altq->parent, def->qname, PF_QNAME_SIZE) == 0) { | |||||
warnx("default queue is not a leaf"); | |||||
error++; | |||||
} | } | ||||
} | |||||
return (error); | |||||
} | |||||
static int | static int | ||||
print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts) | print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts) | ||||
{ | { | ||||
const struct hfsc_opts_v1 *opts; | const struct hfsc_opts_v1 *opts; | ||||
const struct node_hfsc_sc *rtsc, *lssc, *ulsc; | const struct node_hfsc_sc *rtsc, *lssc, *ulsc; | ||||
opts = &a->pq_u.hfsc_opts; | opts = &a->pq_u.hfsc_opts; | ||||
▲ Show 20 Lines • Show All 324 Lines • ▼ Show 20 Lines | |||||
#else | #else | ||||
u_int32_t | u_int32_t | ||||
getifspeed(char *ifname) | getifspeed(char *ifname) | ||||
{ | { | ||||
int s; | int s; | ||||
struct ifreq ifr; | struct ifreq ifr; | ||||
struct if_data ifrdat; | struct if_data ifrdat; | ||||
if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) < 0) | s = get_query_socket(); | ||||
err(1, "socket"); | |||||
bzero(&ifr, sizeof(ifr)); | bzero(&ifr, sizeof(ifr)); | ||||
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | ||||
sizeof(ifr.ifr_name)) | sizeof(ifr.ifr_name)) | ||||
errx(1, "getifspeed: strlcpy"); | errx(1, "getifspeed: strlcpy"); | ||||
ifr.ifr_data = (caddr_t)&ifrdat; | ifr.ifr_data = (caddr_t)&ifrdat; | ||||
if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1) | if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1) | ||||
err(1, "SIOCGIFDATA"); | err(1, "SIOCGIFDATA"); | ||||
if (close(s)) | |||||
err(1, "close"); | |||||
return ((u_int32_t)ifrdat.ifi_baudrate); | return ((u_int32_t)ifrdat.ifi_baudrate); | ||||
} | } | ||||
#endif | #endif | ||||
u_long | u_long | ||||
getifmtu(char *ifname) | getifmtu(char *ifname) | ||||
{ | { | ||||
int s; | int s; | ||||
struct ifreq ifr; | struct ifreq ifr; | ||||
if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) < 0) | s = get_query_socket(); | ||||
err(1, "socket"); | |||||
bzero(&ifr, sizeof(ifr)); | bzero(&ifr, sizeof(ifr)); | ||||
if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | ||||
sizeof(ifr.ifr_name)) | sizeof(ifr.ifr_name)) | ||||
errx(1, "getifmtu: strlcpy"); | errx(1, "getifmtu: strlcpy"); | ||||
if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) == -1) | if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) == -1) | ||||
#ifdef __FreeBSD__ | #ifdef __FreeBSD__ | ||||
ifr.ifr_mtu = 1500; | ifr.ifr_mtu = 1500; | ||||
#else | #else | ||||
err(1, "SIOCGIFMTU"); | err(1, "SIOCGIFMTU"); | ||||
#endif | #endif | ||||
if (close(s)) | |||||
err(1, "close"); | |||||
if (ifr.ifr_mtu > 0) | if (ifr.ifr_mtu > 0) | ||||
return (ifr.ifr_mtu); | return (ifr.ifr_mtu); | ||||
else { | else { | ||||
warnx("could not get mtu for %s, assuming 1500", ifname); | warnx("could not get mtu for %s, assuming 1500", ifname); | ||||
return (1500); | return (1500); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 147 Lines • Show Last 20 Lines |