]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - tc/q_cbq.c
tc: Remove pointless assignments in batch()
[mirror_iproute2.git] / tc / q_cbq.c
index 51ed87a2993181db09615786934a97e6c875ad2a..e7f1a3bfaf5dbb2565d4f1bafdab9639d8a2ec06 100644 (file)
@@ -13,7 +13,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <syslog.h>
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -32,6 +31,7 @@ static void explain_class(void)
        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)
@@ -45,32 +45,35 @@ static void explain1(char *arg)
        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_unsigned(&ewma_log, *argv, 0)) {
+                       if (get_integer(&ewma_log, *argv, 0)) {
                                explain1("ewma");
                                return -1;
                        }
@@ -78,42 +81,53 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
                                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 {
@@ -137,106 +151,111 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl
        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 = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
-       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*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (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_u32(&ewma_log, *argv, 0)) {
+                       if (get_integer(&ewma_log, *argv, 0)) {
                                explain1("ewma");
                                return -1;
                        }
@@ -245,24 +264,26 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
                                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");
@@ -274,41 +295,42 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
                        }
                        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) {
@@ -318,7 +340,17 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
                        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 {
@@ -333,15 +365,16 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
 
        /* 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;
@@ -351,7 +384,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
                        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;
                }
@@ -385,8 +418,7 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
                lss.change |= TCF_CBQ_LSS_EWMA;
        }
 
-       tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
-       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));
@@ -400,12 +432,13 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
                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*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
+       addattr_nest_end(n, tail);
        return 0;
 }
 
@@ -418,12 +451,15 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
        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;
 
-       memset(tb, 0, sizeof(tb));
-       parse_rtattr(tb, TCA_CBQ_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt));
+       parse_rtattr_nested(tb, TCA_CBQ_MAX, opt);
 
        if (tb[TCA_CBQ_RATE]) {
                if (RTA_PAYLOAD(tb[TCA_CBQ_RATE]) < sizeof(*r))
@@ -452,27 +488,35 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
        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",
-                               RTA_PAYLOAD(tb[TCA_CBQ_OVL_STRATEGY]), 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)
@@ -488,6 +532,7 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
                        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);
@@ -500,23 +545,24 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
        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) {
@@ -542,14 +588,11 @@ static int cbq_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstat
        return 0;
 }
 
-struct qdisc_util cbq_util = {
-       NULL,
-       "cbq",
-       cbq_parse_opt,
-       cbq_print_opt,
-       cbq_print_xstats,
-
-       cbq_parse_class_opt,
-       cbq_print_opt,
+struct qdisc_util cbq_qdisc_util = {
+       .id             = "cbq",
+       .parse_qopt     = cbq_parse_opt,
+       .print_qopt     = cbq_print_opt,
+       .print_xstats   = cbq_print_xstats,
+       .parse_copt     = cbq_parse_class_opt,
+       .print_copt     = cbq_print_opt,
 };
-