#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
fprintf(stderr, " [ prio NUMBER ] [ cell BYTES ] [ ewma LOG ]\n");
fprintf(stderr, " [ estimator INTERVAL TIME_CONSTANT ]\n");
fprintf(stderr, " [ split CLASSID ] [ defmap MASK/CHANGE ]\n");
+ fprintf(stderr, " [ overhead BYTES ] [ linklayer TYPE ]\n");
}
static void explain(void)
fprintf(stderr, "Illegal \"%s\"\n", arg);
}
-#define usage() return(-1)
-static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
+static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev)
{
- struct tc_ratespec r;
- struct tc_cbq_lssopt lss;
+ struct tc_ratespec r = {};
+ struct tc_cbq_lssopt lss = {};
__u32 rtab[256];
- unsigned mpu=0, avpkt=0, allot=0;
- int cell_log=-1;
- int ewma_log=-1;
+ unsigned mpu = 0, avpkt = 0, allot = 0;
+ unsigned short overhead = 0;
+ unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
+ int cell_log = -1;
+ int ewma_log = -1;
struct rtattr *tail;
- memset(&lss, 0, sizeof(lss));
- memset(&r, 0, sizeof(r));
-
while (argc > 0) {
- if (strcmp(*argv, "bandwidth") == 0 ||
- strcmp(*argv, "rate") == 0) {
+ if (matches(*argv, "bandwidth") == 0 ||
+ matches(*argv, "rate") == 0) {
NEXT_ARG();
- if (get_rate(&r.rate, *argv)) {
+ if (strchr(*argv, '%')) {
+ if (get_percent_rate(&r.rate, *argv, dev)) {
+ explain1("bandwidth");
+ return -1;
+ }
+ } else if (get_rate(&r.rate, *argv)) {
explain1("bandwidth");
return -1;
}
- } else if (strcmp(*argv, "ewma") == 0) {
+ } else if (matches(*argv, "ewma") == 0) {
NEXT_ARG();
if (get_integer(&ewma_log, *argv, 0)) {
explain1("ewma");
fprintf(stderr, "ewma_log must be < 32\n");
return -1;
}
- } else if (strcmp(*argv, "cell") == 0) {
- unsigned cell;
+ } else if (matches(*argv, "cell") == 0) {
+ unsigned int cell;
int i;
+
NEXT_ARG();
if (get_size(&cell, *argv)) {
explain1("cell");
return -1;
}
- for (i=0; i<32; i++)
+ for (i = 0; i < 32; i++)
if ((1<<i) == cell)
break;
- if (i>=32) {
+ if (i >= 32) {
fprintf(stderr, "cell must be 2^n\n");
return -1;
}
cell_log = i;
- } else if (strcmp(*argv, "avpkt") == 0) {
+ } else if (matches(*argv, "avpkt") == 0) {
NEXT_ARG();
if (get_size(&avpkt, *argv)) {
explain1("avpkt");
return -1;
}
- } else if (strcmp(*argv, "mpu") == 0) {
+ } else if (matches(*argv, "mpu") == 0) {
NEXT_ARG();
if (get_size(&mpu, *argv)) {
explain1("mpu");
return -1;
}
- } else if (strcmp(*argv, "allot") == 0) {
+ } else if (matches(*argv, "allot") == 0) {
NEXT_ARG();
/* Accept and ignore "allot" for backward compatibility */
if (get_size(&allot, *argv)) {
explain1("allot");
return -1;
}
- } else if (strcmp(*argv, "help") == 0) {
+ } else if (matches(*argv, "overhead") == 0) {
+ NEXT_ARG();
+ if (get_u16(&overhead, *argv, 10)) {
+ explain1("overhead"); return -1;
+ }
+ } else if (matches(*argv, "linklayer") == 0) {
+ NEXT_ARG();
+ if (get_linklayer(&linklayer, *argv)) {
+ explain1("linklayer"); return -1;
+ }
+ } else if (matches(*argv, "help") == 0) {
explain();
return -1;
} else {
if (allot < (avpkt*3)/2)
allot = (avpkt*3)/2;
- if ((cell_log = tc_calc_rtable(r.rate, rtab, cell_log, allot, mpu)) < 0) {
+ r.mpu = mpu;
+ r.overhead = overhead;
+ if (tc_calc_rtable(&r, rtab, cell_log, allot, linklayer) < 0) {
fprintf(stderr, "CBQ: failed to calculate rate table.\n");
return -1;
}
- r.cell_log = cell_log;
- r.mpu = mpu;
if (ewma_log < 0)
ewma_log = TC_CBQ_DEF_EWMA;
lss.ewma_log = ewma_log;
- lss.maxidle = tc_cbq_calc_maxidle(r.rate, r.rate, avpkt, lss.ewma_log, 0);
+ lss.maxidle = tc_calc_xmittime(r.rate, avpkt);
lss.change = TCF_CBQ_LSS_MAXIDLE|TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT;
lss.avpkt = avpkt;
- tail = NLMSG_TAIL(n);
- addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+ tail = addattr_nest(n, 1024, TCA_OPTIONS);
addattr_l(n, 1024, TCA_CBQ_RATE, &r, sizeof(r));
addattr_l(n, 1024, TCA_CBQ_LSSOPT, &lss, sizeof(lss));
addattr_l(n, 3024, TCA_CBQ_RTAB, rtab, 1024);
if (show_raw) {
int i;
- for (i=0; i<256; i++)
+
+ for (i = 0; i < 256; i++)
printf("%u ", rtab[i]);
printf("\n");
}
- tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+ addattr_nest_end(n, tail);
return 0;
}
-static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
+static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev)
{
- int wrr_ok=0, fopt_ok=0;
- struct tc_ratespec r;
- struct tc_cbq_lssopt lss;
- struct tc_cbq_wrropt wrr;
- struct tc_cbq_fopt fopt;
- struct tc_cbq_ovl ovl;
+ int wrr_ok = 0, fopt_ok = 0;
+ struct tc_ratespec r = {};
+ struct tc_cbq_lssopt lss = {};
+ struct tc_cbq_wrropt wrr = {};
+ struct tc_cbq_fopt fopt = {};
__u32 rtab[256];
- unsigned mpu=0;
- int cell_log=-1;
- int ewma_log=-1;
- unsigned bndw = 0;
- unsigned minburst=0, maxburst=0;
+ unsigned mpu = 0;
+ int cell_log = -1;
+ int ewma_log = -1;
+ unsigned int bndw = 0;
+ unsigned minburst = 0, maxburst = 0;
+ unsigned short overhead = 0;
+ unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
struct rtattr *tail;
- memset(&r, 0, sizeof(r));
- memset(&lss, 0, sizeof(lss));
- memset(&wrr, 0, sizeof(wrr));
- memset(&fopt, 0, sizeof(fopt));
- memset(&ovl, 0, sizeof(ovl));
-
while (argc > 0) {
- if (strcmp(*argv, "rate") == 0) {
+ if (matches(*argv, "rate") == 0) {
NEXT_ARG();
- if (get_rate(&r.rate, *argv)) {
+ if (strchr(*argv, '%')) {
+ if (get_percent_rate(&r.rate, *argv, dev)) {
+ explain1("rate");
+ return -1;
+ }
+ } else if (get_rate(&r.rate, *argv)) {
explain1("rate");
return -1;
}
- } else if (strcmp(*argv, "bandwidth") == 0) {
+ } else if (matches(*argv, "bandwidth") == 0) {
NEXT_ARG();
- if (get_rate(&bndw, *argv)) {
+ if (strchr(*argv, '%')) {
+ if (get_percent_rate(&bndw, *argv, dev)) {
+ explain1("bandwidth");
+ return -1;
+ }
+ } else if (get_rate(&bndw, *argv)) {
explain1("bandwidth");
return -1;
}
- } else if (strcmp(*argv, "minidle") == 0) {
+ } else if (matches(*argv, "minidle") == 0) {
NEXT_ARG();
if (get_u32(&lss.minidle, *argv, 0)) {
explain1("minidle");
return -1;
}
lss.change |= TCF_CBQ_LSS_MINIDLE;
- } else if (strcmp(*argv, "minburst") == 0) {
+ } else if (matches(*argv, "minburst") == 0) {
NEXT_ARG();
if (get_u32(&minburst, *argv, 0)) {
explain1("minburst");
return -1;
}
lss.change |= TCF_CBQ_LSS_OFFTIME;
- } else if (strcmp(*argv, "maxburst") == 0) {
+ } else if (matches(*argv, "maxburst") == 0) {
NEXT_ARG();
if (get_u32(&maxburst, *argv, 0)) {
explain1("maxburst");
return -1;
}
lss.change |= TCF_CBQ_LSS_MAXIDLE;
- } else if (strcmp(*argv, "bounded") == 0) {
+ } else if (matches(*argv, "bounded") == 0) {
lss.flags |= TCF_CBQ_LSS_BOUNDED;
lss.change |= TCF_CBQ_LSS_FLAGS;
- } else if (strcmp(*argv, "borrow") == 0) {
+ } else if (matches(*argv, "borrow") == 0) {
lss.flags &= ~TCF_CBQ_LSS_BOUNDED;
lss.change |= TCF_CBQ_LSS_FLAGS;
- } else if (strcmp(*argv, "isolated") == 0) {
+ } else if (matches(*argv, "isolated") == 0) {
lss.flags |= TCF_CBQ_LSS_ISOLATED;
lss.change |= TCF_CBQ_LSS_FLAGS;
- } else if (strcmp(*argv, "sharing") == 0) {
+ } else if (matches(*argv, "sharing") == 0) {
lss.flags &= ~TCF_CBQ_LSS_ISOLATED;
lss.change |= TCF_CBQ_LSS_FLAGS;
- } else if (strcmp(*argv, "ewma") == 0) {
+ } else if (matches(*argv, "ewma") == 0) {
NEXT_ARG();
if (get_integer(&ewma_log, *argv, 0)) {
explain1("ewma");
return -1;
}
lss.change |= TCF_CBQ_LSS_EWMA;
- } else if (strcmp(*argv, "cell") == 0) {
- unsigned cell;
+ } else if (matches(*argv, "cell") == 0) {
+ unsigned int cell;
int i;
+
NEXT_ARG();
if (get_size(&cell, *argv)) {
explain1("cell");
return -1;
}
- for (i=0; i<32; i++)
+ for (i = 0; i < 32; i++)
if ((1<<i) == cell)
break;
- if (i>=32) {
+ if (i >= 32) {
fprintf(stderr, "cell must be 2^n\n");
return -1;
}
cell_log = i;
- } else if (strcmp(*argv, "prio") == 0) {
- unsigned prio;
+ } else if (matches(*argv, "prio") == 0) {
+ unsigned int prio;
+
NEXT_ARG();
if (get_u32(&prio, *argv, 0)) {
explain1("prio");
}
wrr.priority = prio;
wrr_ok++;
- } else if (strcmp(*argv, "allot") == 0) {
+ } else if (matches(*argv, "allot") == 0) {
NEXT_ARG();
if (get_size(&wrr.allot, *argv)) {
explain1("allot");
return -1;
}
- } else if (strcmp(*argv, "avpkt") == 0) {
+ } else if (matches(*argv, "avpkt") == 0) {
NEXT_ARG();
if (get_size(&lss.avpkt, *argv)) {
explain1("avpkt");
return -1;
}
lss.change |= TCF_CBQ_LSS_AVPKT;
- } else if (strcmp(*argv, "mpu") == 0) {
+ } else if (matches(*argv, "mpu") == 0) {
NEXT_ARG();
if (get_size(&mpu, *argv)) {
explain1("mpu");
return -1;
}
- } else if (strcmp(*argv, "weight") == 0) {
+ } else if (matches(*argv, "weight") == 0) {
NEXT_ARG();
if (get_size(&wrr.weight, *argv)) {
explain1("weight");
return -1;
}
wrr_ok++;
- } else if (strcmp(*argv, "split") == 0) {
+ } else if (matches(*argv, "split") == 0) {
NEXT_ARG();
if (get_tc_classid(&fopt.split, *argv)) {
fprintf(stderr, "Invalid split node ID.\n");
- usage();
+ return -1;
}
fopt_ok++;
- } else if (strcmp(*argv, "defmap") == 0) {
+ } else if (matches(*argv, "defmap") == 0) {
int err;
+
NEXT_ARG();
err = sscanf(*argv, "%08x/%08x", &fopt.defmap, &fopt.defchange);
if (err < 1) {
if (err == 1)
fopt.defchange = ~0;
fopt_ok++;
- } else if (strcmp(*argv, "help") == 0) {
+ } else if (matches(*argv, "overhead") == 0) {
+ NEXT_ARG();
+ if (get_u16(&overhead, *argv, 10)) {
+ explain1("overhead"); return -1;
+ }
+ } else if (matches(*argv, "linklayer") == 0) {
+ NEXT_ARG();
+ if (get_linklayer(&linklayer, *argv)) {
+ explain1("linklayer"); return -1;
+ }
+ } else if (matches(*argv, "help") == 0) {
explain_class();
return -1;
} else {
/* 1. Prepare link sharing scheduler parameters */
if (r.rate) {
- unsigned pktsize = wrr.allot;
+ unsigned int pktsize = wrr.allot;
+
if (wrr.allot < (lss.avpkt*3)/2)
wrr.allot = (lss.avpkt*3)/2;
- if ((cell_log = tc_calc_rtable(r.rate, rtab, cell_log, pktsize, mpu)) < 0) {
+ r.mpu = mpu;
+ r.overhead = overhead;
+ if (tc_calc_rtable(&r, rtab, cell_log, pktsize, linklayer) < 0) {
fprintf(stderr, "CBQ: failed to calculate rate table.\n");
return -1;
}
- r.cell_log = cell_log;
- r.mpu = mpu;
}
if (ewma_log < 0)
ewma_log = TC_CBQ_DEF_EWMA;
fprintf(stderr, "CBQ: avpkt is required for max/minburst.\n");
return -1;
}
- if (bndw==0 || r.rate == 0) {
+ if (bndw == 0 || r.rate == 0) {
fprintf(stderr, "CBQ: bandwidth&rate are required for max/minburst.\n");
return -1;
}
lss.change |= TCF_CBQ_LSS_EWMA;
}
- tail = NLMSG_TAIL(n);
- addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+ tail = addattr_nest(n, 1024, TCA_OPTIONS);
if (lss.change) {
lss.change |= TCF_CBQ_LSS_FLAGS;
addattr_l(n, 1024, TCA_CBQ_LSSOPT, &lss, sizeof(lss));
addattr_l(n, 3024, TCA_CBQ_RTAB, rtab, 1024);
if (show_raw) {
int i;
- for (i=0; i<256; i++)
+
+ for (i = 0; i < 256; i++)
printf("%u ", rtab[i]);
printf("\n");
}
}
- tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+ addattr_nest_end(n, tail);
return 0;
}
struct tc_cbq_wrropt *wrr = NULL;
struct tc_cbq_fopt *fopt = NULL;
struct tc_cbq_ovl *ovl = NULL;
+ unsigned int linklayer;
+
+ SPRINT_BUF(b1);
+ SPRINT_BUF(b2);
if (opt == NULL)
return 0;
if (tb[TCA_CBQ_OVL_STRATEGY]) {
if (RTA_PAYLOAD(tb[TCA_CBQ_OVL_STRATEGY]) < sizeof(*ovl))
fprintf(stderr, "CBQ: too short overlimit strategy %u/%u\n",
- (unsigned) RTA_PAYLOAD(tb[TCA_CBQ_OVL_STRATEGY]),
- (unsigned) sizeof(*ovl));
+ (unsigned int) RTA_PAYLOAD(tb[TCA_CBQ_OVL_STRATEGY]),
+ (unsigned int) sizeof(*ovl));
else
ovl = RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY]);
}
if (r) {
char buf[64];
+
print_rate(buf, sizeof(buf), r->rate);
fprintf(f, "rate %s ", buf);
+ linklayer = (r->linklayer & TC_LINKLAYER_MASK);
+ if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
+ fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b2));
if (show_details) {
fprintf(f, "cell %ub ", 1<<r->cell_log);
if (r->mpu)
fprintf(f, "mpu %ub ", r->mpu);
+ if (r->overhead)
+ fprintf(f, "overhead %ub ", r->overhead);
}
}
if (lss && lss->flags) {
- int comma=0;
+ int comma = 0;
+
fprintf(f, "(");
if (lss->flags&TCF_CBQ_LSS_BOUNDED) {
fprintf(f, "bounded");
- comma=1;
+ comma = 1;
}
if (lss->flags&TCF_CBQ_LSS_ISOLATED) {
if (comma)
fprintf(f, "prio no-transmit");
if (show_details) {
char buf[64];
+
fprintf(f, "/%u ", wrr->cpriority);
if (wrr->weight != 1) {
print_rate(buf, sizeof(buf), wrr->weight);
if (lss && show_details) {
fprintf(f, "\nlevel %u ewma %u avpkt %ub ", lss->level, lss->ewma_log, lss->avpkt);
if (lss->maxidle) {
- fprintf(f, "maxidle %luus ", tc_core_tick2usec(lss->maxidle>>lss->ewma_log));
+ fprintf(f, "maxidle %s ", sprint_ticks(lss->maxidle>>lss->ewma_log, b1));
if (show_raw)
fprintf(f, "[%08x] ", lss->maxidle);
}
- if (lss->minidle!=0x7fffffff) {
- fprintf(f, "minidle %luus ", tc_core_tick2usec(lss->minidle>>lss->ewma_log));
+ if (lss->minidle != 0x7fffffff) {
+ fprintf(f, "minidle %s ", sprint_ticks(lss->minidle>>lss->ewma_log, b1));
if (show_raw)
fprintf(f, "[%08x] ", lss->minidle);
}
if (lss->offtime) {
- fprintf(f, "offtime %luus ", tc_core_tick2usec(lss->offtime));
+ fprintf(f, "offtime %s ", sprint_ticks(lss->offtime, b1));
if (show_raw)
fprintf(f, "[%08x] ", lss->offtime);
}
}
if (fopt && show_details) {
char buf[64];
+
print_tc_classid(buf, sizeof(buf), fopt->split);
fprintf(f, "\nsplit %s ", buf);
if (fopt->defmap) {
.parse_copt = cbq_parse_class_opt,
.print_copt = cbq_print_opt,
};
-