diff options
Diffstat (limited to 'freebsd/sbin/pfctl/pfctl_altq.c')
-rw-r--r-- | freebsd/sbin/pfctl/pfctl_altq.c | 69 |
1 files changed, 47 insertions, 22 deletions
diff --git a/freebsd/sbin/pfctl/pfctl_altq.c b/freebsd/sbin/pfctl/pfctl_altq.c index 145d60ae..1220cfc6 100644 --- a/freebsd/sbin/pfctl/pfctl_altq.c +++ b/freebsd/sbin/pfctl/pfctl_altq.c @@ -24,12 +24,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #ifdef __rtems__ #include <machine/rtems-bsd-program.h> #endif /* __rtems__ */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#define PFIOC_USE_LATEST + #include <sys/types.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -40,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include <err.h> #include <errno.h> +#include <inttypes.h> #include <limits.h> #include <math.h> #include <stdio.h> @@ -100,14 +103,14 @@ static int gsc_add_seg(struct gen_sc *, double, double, double, static double sc_x2y(struct service_curve *, double); #ifdef __FreeBSD__ -u_int32_t getifspeed(int, char *); +u_int64_t getifspeed(int, char *); #else u_int32_t getifspeed(char *); #endif u_long getifmtu(char *); int eval_queue_opts(struct pf_altq *, struct node_queue_opt *, - u_int32_t); -u_int32_t eval_bwspec(struct node_queue_bw *, u_int32_t); + 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, const struct node_hfsc_sc *); void print_fairq_sc(const char *, u_int, u_int, u_int, @@ -270,7 +273,8 @@ int eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, struct node_queue_opt *opts) { - u_int rate, size, errors = 0; + u_int64_t rate; + u_int size, errors = 0; if (bw->bw_absolute > 0) pa->ifbandwidth = bw->bw_absolute; @@ -287,6 +291,15 @@ eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, } else if ((pa->ifbandwidth = eval_bwspec(bw, rate)) == 0) pa->ifbandwidth = rate; + /* + * Limit bandwidth to UINT_MAX for schedulers that aren't 64-bit ready. + */ + if ((pa->scheduler != ALTQT_HFSC) && (pa->ifbandwidth > UINT_MAX)) { + pa->ifbandwidth = UINT_MAX; + warnx("interface %s bandwidth limited to %" PRIu64 " bps " + "because selected scheduler is 32-bit limited\n", pa->ifname, + pa->ifbandwidth); + } errors += eval_queue_opts(pa, opts, pa->ifbandwidth); /* if tbrsize is not specified, use heuristics */ @@ -298,11 +311,11 @@ eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, size = 4; else if (rate <= 200 * 1000 * 1000) size = 8; - else + else if (rate <= 2500 * 1000 * 1000ULL) size = 24; + else + size = 128; size = size * getifmtu(pa->ifname); - if (size > 0xffff) - size = 0xffff; pa->tbrsize = size; } return (errors); @@ -350,7 +363,7 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, { /* should be merged with expand_queue */ struct pf_altq *if_pa, *parent, *altq; - u_int32_t bwsum; + u_int64_t bwsum; int error = 0; /* find the corresponding interface and copy fields used by queues */ @@ -384,7 +397,7 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC || pa->scheduler == ALTQT_FAIRQ) { pa->bandwidth = eval_bwspec(bw, - parent == NULL ? 0 : parent->bandwidth); + parent == NULL ? pa->ifbandwidth : parent->bandwidth); if (pa->bandwidth > pa->ifbandwidth) { fprintf(stderr, "bandwidth for %s higher than " @@ -415,7 +428,8 @@ eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw, } } - if (eval_queue_opts(pa, opts, parent == NULL? 0 : parent->bandwidth)) + if (eval_queue_opts(pa, opts, + parent == NULL ? pa->ifbandwidth : parent->bandwidth)) return (1); switch (pa->scheduler) { @@ -509,12 +523,13 @@ cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa) * this causes integer overflow in kernel! * (bandwidth < 6Kbps when max_pkt_size=1500) */ - if (pa->bandwidth != 0 && (pf->opts & PF_OPT_QUIET) == 0) + if (pa->bandwidth != 0 && (pf->opts & PF_OPT_QUIET) == 0) { warnx("queue bandwidth must be larger than %s", rate2str(ifnsPerByte * (double)opts->maxpktsize / (double)INT_MAX * (double)pa->ifbandwidth)); fprintf(stderr, "cbq: queue %s is too slow!\n", pa->qname); + } nsPerByte = (double)(INT_MAX / opts->maxpktsize); } @@ -720,7 +735,7 @@ static int eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) { struct pf_altq *altq, *parent; - struct hfsc_opts *opts; + struct hfsc_opts_v1 *opts; struct service_curve sc; opts = &pa->pq_u.hfsc_opts; @@ -1012,7 +1027,7 @@ check_commit_fairq(int dev __unused, int opts __unused, struct pf_altq *pa) static int print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts) { - const struct hfsc_opts *opts; + const struct hfsc_opts_v1 *opts; const struct node_hfsc_sc *rtsc, *lssc, *ulsc; opts = &a->pq_u.hfsc_opts; @@ -1333,7 +1348,7 @@ rate2str(double rate) * FreeBSD does not have SIOCGIFDATA. * To emulate this, DIOCGIFSPEED ioctl added to pf. */ -u_int32_t +u_int64_t getifspeed(int pfdev, char *ifname) { struct pf_ifspeed io; @@ -1344,7 +1359,7 @@ getifspeed(int pfdev, char *ifname) errx(1, "getifspeed: strlcpy"); if (ioctl(pfdev, DIOCGIFSPEED, &io) == -1) err(1, "DIOCGIFSPEED"); - return ((u_int32_t)io.baudrate); + return (io.baudrate); } #else u_int32_t @@ -1399,7 +1414,7 @@ getifmtu(char *ifname) int eval_queue_opts(struct pf_altq *pa, struct node_queue_opt *opts, - u_int32_t ref_bw) + u_int64_t ref_bw) { int errors = 0; @@ -1475,11 +1490,21 @@ eval_queue_opts(struct pf_altq *pa, struct node_queue_opt *opts, return (errors); } -u_int32_t -eval_bwspec(struct node_queue_bw *bw, u_int32_t ref_bw) +/* + * If absolute bandwidth if set, return the lesser of that value and the + * reference bandwidth. Limiting to the reference bandwidth allows simple + * limiting of configured bandwidth parameters for schedulers that are + * 32-bit limited, as the root/interface bandwidth (top-level reference + * bandwidth) will be properly limited in that case. + * + * Otherwise, if the absolute bandwidth is not set, return given percentage + * of reference bandwidth. + */ +u_int64_t +eval_bwspec(struct node_queue_bw *bw, u_int64_t ref_bw) { if (bw->bw_absolute > 0) - return (bw->bw_absolute); + return (MIN(bw->bw_absolute, ref_bw)); if (bw->bw_percent > 0) return (ref_bw / 100 * bw->bw_percent); |