static int dsmark_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct rtattr *tail; __u8 tmp; char *end; tail = NLMSG_TAIL(n); addattr_l(n,1024,TCA_OPTIONS,NULL,0); while (argc > 0) { if (!strcmp(*argv,"mask")) { NEXT_ARG(); tmp = strtoul(*argv,&end,0); if (*end) { explain_class(); return -1; } addattr_l(n,1024,TCA_DSMARK_MASK,&tmp,1); } else if (!strcmp(*argv,"value")) { NEXT_ARG(); tmp = strtoul(*argv,&end,0); if (*end) { explain_class(); return -1; } addattr_l(n,1024,TCA_DSMARK_VALUE,&tmp,1); } else { explain_class(); return -1; } argc--; argv++; } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
static int qfq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct rtattr *tail; __u32 tmp; tail = NLMSG_TAIL(n); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "weight") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 10)) { explain1("weight"); return -1; } addattr32(n, 4096, TCA_QFQ_WEIGHT, tmp); } else if (matches(*argv, "maxpkt") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 10)) { explain1("maxpkt"); return -1; } addattr32(n, 4096, TCA_QFQ_LMAX, tmp); } else if (strcmp(*argv, "help") == 0) { explain_class(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain_class(); return -1; } argc--; argv++; } tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail; return 0; }
static int hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { struct tc_service_curve rsc = {}, fsc = {}, usc = {}; int rsc_ok = 0, fsc_ok = 0, usc_ok = 0; struct rtattr *tail; while (argc > 0) { if (matches(*argv, "rt") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &rsc, dev) < 0) { explain1("rt"); return -1; } rsc_ok = 1; } else if (matches(*argv, "ls") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &fsc, dev) < 0) { explain1("ls"); return -1; } fsc_ok = 1; } else if (matches(*argv, "sc") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &rsc, dev) < 0) { explain1("sc"); return -1; } memcpy(&fsc, &rsc, sizeof(fsc)); rsc_ok = 1; fsc_ok = 1; } else if (matches(*argv, "ul") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &usc, dev) < 0) { explain1("ul"); return -1; } usc_ok = 1; } else if (matches(*argv, "help") == 0) { explain_class(); return -1; } else { fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv); explain_class(); return -1; } argc--, argv++; } if (!(rsc_ok || fsc_ok || usc_ok)) { fprintf(stderr, "HFSC: no parameters given\n"); explain_class(); return -1; } if (usc_ok && !fsc_ok) { fprintf(stderr, "HFSC: Upper-limit Service Curve without Link-Share Service Curve\n"); explain_class(); return -1; } tail = addattr_nest(n, 1024, TCA_OPTIONS); if (rsc_ok) addattr_l(n, 1024, TCA_HFSC_RSC, &rsc, sizeof(rsc)); if (fsc_ok) addattr_l(n, 1024, TCA_HFSC_FSC, &fsc, sizeof(fsc)); if (usc_ok) addattr_l(n, 1024, TCA_HFSC_USC, &usc, sizeof(usc)); addattr_nest_end(n, tail); return 0; }
static int hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct tc_service_curve rsc, fsc, usc; int rsc_ok, fsc_ok, usc_ok; struct rtattr *tail; memset(&rsc, 0, sizeof(rsc)); memset(&fsc, 0, sizeof(fsc)); memset(&usc, 0, sizeof(usc)); rsc_ok = fsc_ok = usc_ok = 0; while (argc > 0) { if (matches(*argv, "rt") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &rsc) < 0) { explain1("rt"); return -1; } rsc_ok = 1; } else if (matches(*argv, "ls") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &fsc) < 0) { explain1("ls"); return -1; } fsc_ok = 1; } else if (matches(*argv, "sc") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &rsc) < 0) { explain1("sc"); return -1; } memcpy(&fsc, &rsc, sizeof(fsc)); rsc_ok = 1; fsc_ok = 1; } else if (matches(*argv, "ul") == 0) { NEXT_ARG(); if (hfsc_get_sc(&argc, &argv, &usc) < 0) { explain1("ul"); return -1; } usc_ok = 1; } else if (matches(*argv, "help") == 0) { explain_class(); return -1; } else { fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv); explain_class(); return -1; } argc--, argv++; } if (!(rsc_ok || fsc_ok || usc_ok)) { fprintf(stderr, "HFSC: no parameters given\n"); explain_class(); return -1; } if (usc_ok && !fsc_ok) { fprintf(stderr, "HFSC: Upper-limit Service Curve without " "Link-Share Service Curve\n"); explain_class(); return -1; } tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); if (rsc_ok) addattr_l(n, 1024, TCA_HFSC_RSC, &rsc, sizeof(rsc)); if (fsc_ok) addattr_l(n, 1024, TCA_HFSC_FSC, &fsc, sizeof(fsc)); if (usc_ok) addattr_l(n, 1024, TCA_HFSC_USC, &usc, sizeof(usc)); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { 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; __u32 rtab[256]; unsigned mpu=0; int cell_log=-1; int ewma_log=-1; unsigned bndw = 0; unsigned minburst=0, maxburst=0; 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) { NEXT_ARG(); if (get_rate(&r.rate, *argv)) { explain1("rate"); return -1; } } else if (strcmp(*argv, "bandwidth") == 0) { NEXT_ARG(); if (get_rate(&bndw, *argv)) { explain1("bandwidth"); return -1; } } else if (strcmp(*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) { NEXT_ARG(); if (get_u32(&minburst, *argv, 0)) { explain1("minburst"); return -1; } lss.change |= TCF_CBQ_LSS_OFFTIME; } else if (strcmp(*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) { lss.flags |= TCF_CBQ_LSS_BOUNDED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (strcmp(*argv, "borrow") == 0) { lss.flags &= ~TCF_CBQ_LSS_BOUNDED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (strcmp(*argv, "isolated") == 0) { lss.flags |= TCF_CBQ_LSS_ISOLATED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (strcmp(*argv, "sharing") == 0) { lss.flags &= ~TCF_CBQ_LSS_ISOLATED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (strcmp(*argv, "ewma") == 0) { NEXT_ARG(); if (get_u32(&ewma_log, *argv, 0)) { explain1("ewma"); return -1; } if (ewma_log > 31) { fprintf(stderr, "ewma_log must be < 32\n"); return -1; } lss.change |= TCF_CBQ_LSS_EWMA; } else if (strcmp(*argv, "cell") == 0) { unsigned cell; int i; NEXT_ARG(); if (get_size(&cell, *argv)) { explain1("cell"); return -1; } for (i=0; i<32; i++) if ((1<<i) == cell) break; if (i>=32) { fprintf(stderr, "cell must be 2^n\n"); return -1; } cell_log = i; } else if (strcmp(*argv, "prio") == 0) { unsigned prio; NEXT_ARG(); if (get_u32(&prio, *argv, 0)) { explain1("prio"); return -1; } if (prio > TC_CBQ_MAXPRIO) { fprintf(stderr, "\"prio\" must be number in the range 1...%d\n", TC_CBQ_MAXPRIO); return -1; } wrr.priority = prio; wrr_ok++; } else if (strcmp(*argv, "allot") == 0) { NEXT_ARG(); if (get_size(&wrr.allot, *argv)) { explain1("allot"); return -1; } } else if (strcmp(*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) { NEXT_ARG(); if (get_size(&mpu, *argv)) { explain1("mpu"); return -1; } } else if (strcmp(*argv, "weight") == 0) { NEXT_ARG(); if (get_size(&wrr.weight, *argv)) { explain1("weight"); return -1; } wrr_ok++; } else if (strcmp(*argv, "split") == 0) { NEXT_ARG(); if (get_tc_classid(&fopt.split, *argv)) { fprintf(stderr, "Invalid split node ID.\n"); usage(); } fopt_ok++; } else if (strcmp(*argv, "defmap") == 0) { int err; NEXT_ARG(); err = sscanf(*argv, "%08x/%08x", &fopt.defmap, &fopt.defchange); if (err < 1) { fprintf(stderr, "Invalid defmap, should be MASK32[/MASK]\n"); return -1; } if (err == 1) fopt.defchange = ~0; fopt_ok++; } else if (strcmp(*argv, "help") == 0) { explain_class(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain_class(); return -1; } argc--; argv++; } /* OK. All options are parsed. */ /* 1. Prepare link sharing scheduler parameters */ if (r.rate) { unsigned 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) { 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; if (lss.change&(TCF_CBQ_LSS_OFFTIME|TCF_CBQ_LSS_MAXIDLE)) { if (lss.avpkt == 0) { fprintf(stderr, "CBQ: avpkt is required for max/minburst.\n"); return -1; } if (bndw==0 || r.rate == 0) { fprintf(stderr, "CBQ: bandwidth&rate are required for max/minburst.\n"); return -1; } } if (wrr.priority == 0 && (n->nlmsg_flags&NLM_F_EXCL)) { wrr_ok = 1; wrr.priority = TC_CBQ_MAXPRIO; if (wrr.allot == 0) wrr.allot = (lss.avpkt*3)/2; } if (wrr_ok) { if (wrr.weight == 0) wrr.weight = (wrr.priority == TC_CBQ_MAXPRIO) ? 1 : r.rate; if (wrr.allot == 0) { fprintf(stderr, "CBQ: \"allot\" is required to set WRR parameters.\n"); return -1; } } if (lss.change&TCF_CBQ_LSS_MAXIDLE) { lss.maxidle = tc_cbq_calc_maxidle(bndw, r.rate, lss.avpkt, ewma_log, maxburst); lss.change |= TCF_CBQ_LSS_MAXIDLE; lss.change |= TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT; } if (lss.change&TCF_CBQ_LSS_OFFTIME) { lss.offtime = tc_cbq_calc_offtime(bndw, r.rate, lss.avpkt, ewma_log, minburst); lss.change |= TCF_CBQ_LSS_OFFTIME; lss.change |= TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT; } if (lss.change&TCF_CBQ_LSS_MINIDLE) { lss.minidle <<= lss.ewma_log; lss.change |= TCF_CBQ_LSS_EWMA; } tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len)); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); if (lss.change) { lss.change |= TCF_CBQ_LSS_FLAGS; addattr_l(n, 1024, TCA_CBQ_LSSOPT, &lss, sizeof(lss)); } if (wrr_ok) addattr_l(n, 1024, TCA_CBQ_WRROPT, &wrr, sizeof(wrr)); if (fopt_ok) addattr_l(n, 1024, TCA_CBQ_FOPT, &fopt, sizeof(fopt)); if (r.rate) { addattr_l(n, 1024, TCA_CBQ_RATE, &r, sizeof(r)); addattr_l(n, 3024, TCA_CBQ_RTAB, rtab, 1024); if (show_raw) { int 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; return 0; }