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;
}
Exemple #2
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;
}
Exemple #3
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;
}