Example #1
0
static int
hfsc_get_sc1(int *argcp, char ***argvp,
	     struct tc_service_curve *sc, const char *dev)
{
	char **argv = *argvp;
	int argc = *argcp;
	unsigned int m1 = 0, d = 0, m2 = 0;

	if (matches(*argv, "m1") == 0) {
		NEXT_ARG();
		if (strchr(*argv, '%')) {
			if (get_percent_rate(&m1, *argv, dev)) {
				explain1("m1");
				return -1;
			}
		} else if (get_rate(&m1, *argv) < 0) {
			explain1("m1");
			return -1;
		}
		NEXT_ARG();
	}

	if (matches(*argv, "d") == 0) {
		NEXT_ARG();
		if (get_time(&d, *argv) < 0) {
			explain1("d");
			return -1;
		}
		NEXT_ARG();
	}

	if (matches(*argv, "m2") == 0) {
		NEXT_ARG();
		if (strchr(*argv, '%')) {
			if (get_percent_rate(&m2, *argv, dev)) {
				explain1("m2");
				return -1;
			}
		} else if (get_rate(&m2, *argv) < 0) {
			explain1("m2");
			return -1;
		}
	} else
		return -1;

	sc->m1 = m1;
	sc->d  = tc_core_time2ktime(d);
	sc->m2 = m2;

	*argvp = argv;
	*argcp = argc;
	return 0;
}
Example #2
0
static int psp_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
			       struct nlmsghdr *n)
{
	struct tc_psp_copt copt;
	struct rtattr *tail;

	memset(&copt, 0, sizeof(copt));
	copt.mode = TC_PSP_MODE_STATIC; /* default mode */

	while (argc > 0) {
		if (matches(*argv, "rate") == 0) {
			NEXT_ARG();
			if (GET_RATE(&copt.rate, *argv)) {
				explain1("rate");
				return -1;
			}
		} else if (matches(*argv, "mode") == 0) {
			NEXT_ARG();
			if (get_u32(&copt.mode, *argv, 16)) {
				explain1("mode");
				return -1;
			}
		} else if (matches(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	if (copt.mode == TC_PSP_MODE_NORMAL && copt.rate != 0) {
		fprintf(stderr, "You can not set to \"rate\" parameter "
			"in normal mode\n");
		explain1("rate");
		return -1;
	} else if (copt.mode == TC_PSP_MODE_STATIC && copt.rate == 0) {
		fprintf(stderr, "You need set to \"rate\" parameter "
			"in static target rate mode.\n");
		explain1("rate");
		return -1;
	}

	tail = NLMSG_TAIL(n);
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	addattr_l(n, 1024, TCA_PSP_COPT, &copt, sizeof(copt));
	tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
	return 0;
}
Example #3
0
static int
hfsc_parse_opt(struct qdisc_util *qu, int argc, char **argv,
	       struct nlmsghdr *n, const char *dev)
{
	struct tc_hfsc_qopt qopt = {};

	while (argc > 0) {
		if (matches(*argv, "default") == 0) {
			NEXT_ARG();
			if (qopt.defcls != 0) {
				fprintf(stderr, "HFSC: Double \"default\"\n");
				return -1;
			}
			if (get_u16(&qopt.defcls, *argv, 16) < 0) {
				explain1("default");
				return -1;
			}
		} else if (matches(*argv, "help") == 0) {
			explain_qdisc();
			return -1;
		} else {
			fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv);
			explain_qdisc();
			return -1;
		}
		argc--, argv++;
	}

	addattr_l(n, 1024, TCA_OPTIONS, &qopt, sizeof(qopt));
	return 0;
}
Example #4
0
static int psp_parse_opt(struct qdisc_util *qu, int argc, char **argv,
			 struct nlmsghdr *n)
{
	struct tc_psp_qopt qopt;
	struct rtattr *tail;

	memset(&qopt, 0, sizeof(qopt));
	qopt.ifg = 12;

	while (argc > 0) {
		if (matches(*argv, "rate") == 0) {
			NEXT_ARG();
			if (GET_RATE(&qopt.rate, *argv)) {
				explain1("rate");
				return -1;
			}
		} else if (matches(*argv, "default") == 0) {
			NEXT_ARG();
			if (get_u32(&qopt.defcls, *argv, 16)) {
				explain1("default");
				return -1;
			}
		} else if (matches(*argv, "ifg") == 0) {
			NEXT_ARG();
			if (get_u32(&qopt.ifg, *argv, 10)) {
				explain1("ifg");
				return -1;
			}
		} else if (matches(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--;
		argv++;
	}

	tail = NLMSG_TAIL(n);
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	addattr_l(n, 1024, TCA_PSP_QOPT, &qopt, sizeof(qopt));
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	return 0;
}
static int
hfsc_get_sc1(int *argcp, char ***argvp, struct tc_service_curve *sc)
{
	char **argv = *argvp;
	int argc = *argcp;
	unsigned int m1 = 0, d = 0, m2 = 0;

	if (matches(*argv, "m1") == 0) {
		NEXT_ARG();
		if (get_rate(&m1, *argv) < 0) {
			explain1("m1");
			return -1;
		}
		NEXT_ARG();
	}

	if (matches(*argv, "d") == 0) {
		NEXT_ARG();
		if (get_usecs(&d, *argv) < 0) {
			explain1("d");
			return -1;
		}
		NEXT_ARG();
	}

	if (matches(*argv, "m2") == 0) {
		NEXT_ARG();
		if (get_rate(&m2, *argv) < 0) {
			explain1("m2");
			return -1;
		}
	} else
		return -1;

	sc->m1 = m1;
	sc->d  = d;
	sc->m2 = m2;

	*argvp = argv;
	*argcp = argc;
	return 0;
}
Example #6
0
static int htb_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	struct tc_htb_glob opt;
	struct rtattr *tail;
	unsigned i; char *p;
	memset(&opt,0,sizeof(opt));
	opt.rate2quantum = 10;
	opt.version = 3;

	while (argc > 0) {
		if (matches(*argv, "r2q") == 0) {
		    NEXT_ARG();
		    if (get_u32(&opt.rate2quantum, *argv, 10)) {
			explain1("r2q"); return -1;
		    }
		} else if (matches(*argv, "default") == 0) {
		    NEXT_ARG();
		    if (get_u32(&opt.defcls, *argv, 16)) {
			explain1("default"); return -1;
		    }
		} else if (matches(*argv, "debug") == 0) {
		    NEXT_ARG(); p = *argv;
		    for (i=0; i<16; i++,p++) {
			if (*p<'0' || *p>'3') break;
			opt.debug |= (*p-'0')<<(2*i);
		    }
		} else {
//			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}
	tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	addattr_l(n, 2024, TCA_HTB_INIT, &opt, NLMSG_ALIGN(sizeof(opt)));
	tail->rta_len = (((void*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
	return 0;
}
Example #7
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_get_sc2(int *argcp, char ***argvp, struct tc_service_curve *sc)
{
	char **argv = *argvp;
	int argc = *argcp;
	unsigned int umax = 0, dmax = 0, rate = 0;

	if (matches(*argv, "umax") == 0) {
		NEXT_ARG();
		if (get_size(&umax, *argv) < 0) {
			explain1("umax");
			return -1;
		}
		NEXT_ARG();
	}

	if (matches(*argv, "dmax") == 0) {
		NEXT_ARG();
		if (get_usecs(&dmax, *argv) < 0) {
			explain1("dmax");
			return -1;
		}
		NEXT_ARG();
	}

	if (matches(*argv, "rate") == 0) {
		NEXT_ARG();
		if (get_rate(&rate, *argv) < 0) {
			explain1("rate");
			return -1;
		}
	} else
		return -1;

	if (umax != 0 && dmax == 0) {
		fprintf(stderr, "HFSC: umax given but dmax is zero.\n");
		return -1;
	}

	if (dmax != 0 && ceil(umax * 1000000.0 / dmax) > rate) {
		/*
		 * concave curve, slope of first segment is umax/dmax,
		 * intersection is at dmax
		 */
		sc->m1 = ceil(umax * 1000000.0 / dmax); /* in bps */
		sc->d  = dmax;
		sc->m2 = rate;
	} else {
		/*
		 * convex curve, slope of first segment is 0, intersection
		 * is at dmax - umax / rate
		 */
		sc->m1 = 0;
		sc->d  = ceil(dmax - umax * 1000000.0 / rate); /* in usec */
		sc->m2 = rate;
	}

	*argvp = argv;
	*argcp = argc;
	return 0;
}
Example #9
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;
}
Example #11
0
static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
                           struct nlmsghdr *n)
{
    size_t dist_size = 0;
    struct rtattr *tail;
    struct tc_netem_qopt opt;
    struct tc_netem_corr cor;
    struct tc_netem_reorder reorder;
    __s16 dist_data[MAXDIST];

    memset(&opt, 0, sizeof(opt));
    opt.limit = 1000;
    memset(&cor, 0, sizeof(cor));
    memset(&reorder, 0, sizeof(reorder));

    while (argc > 0) {
        if (matches(*argv, "limit") == 0) {
            NEXT_ARG();
            if (get_size(&opt.limit, *argv)) {
                explain1("limit");
                return -1;
            }
        } else if (matches(*argv, "latency") == 0 ||
                   matches(*argv, "delay") == 0) {
            NEXT_ARG();
            if (get_ticks(&opt.latency, *argv)) {
                explain1("latency");
                return -1;
            }

            if (NEXT_IS_NUMBER()) {
                NEXT_ARG();
                if (get_ticks(&opt.jitter, *argv)) {
                    explain1("latency");
                    return -1;
                }

                if (NEXT_IS_NUMBER()) {
                    NEXT_ARG();
                    if (get_percent(&cor.delay_corr,
                                    *argv)) {
                        explain1("latency");
                        return -1;
                    }
                }
            }
        } else if (matches(*argv, "loss") == 0 ||
                   matches(*argv, "drop") == 0) {
            NEXT_ARG();
            if (get_percent(&opt.loss, *argv)) {
                explain1("loss");
                return -1;
            }
            if (NEXT_IS_NUMBER()) {
                NEXT_ARG();
                if (get_percent(&cor.loss_corr, *argv)) {
                    explain1("loss");
                    return -1;
                }
            }
        } else if (matches(*argv, "reorder") == 0) {
            NEXT_ARG();
            if (get_percent(&reorder.probability, *argv)) {
                explain1("reorder");
                return -1;
            }
            if (NEXT_IS_NUMBER()) {
                NEXT_ARG();
                if (get_percent(&reorder.correlation, *argv)) {
                    explain1("reorder");
                    return -1;
                }
            }
        } else if (matches(*argv, "gap") == 0) {
            NEXT_ARG();
            if (get_u32(&opt.gap, *argv, 0)) {
                explain1("gap");
                return -1;
            }
        } else if (matches(*argv, "duplicate") == 0) {
            NEXT_ARG();
            if (get_percent(&opt.duplicate, *argv)) {
                explain1("duplicate");
                return -1;
            }
            if (NEXT_IS_NUMBER()) {
                NEXT_ARG();
                if (get_percent(&cor.dup_corr, *argv)) {
                    explain1("duplicate");
                    return -1;
                }
            }
        } else if (matches(*argv, "distribution") == 0) {
            NEXT_ARG();
            dist_size = get_distribution(*argv, dist_data);
            if (dist_size < 0)
                return -1;
        } else if (strcmp(*argv, "help") == 0) {
            explain();
            return -1;
        } else {
            fprintf(stderr, "What is \"%s\"?\n", *argv);
            explain();
            return -1;
        }
        argc--;
        argv++;
    }

    tail = NLMSG_TAIL(n);

    if (reorder.probability) {
        if (opt.latency == 0) {
            fprintf(stderr, "reordering not possible without specifying some delay\n");
        }
        if (opt.gap == 0)
            opt.gap = 1;
    } else if (opt.gap > 0) {
        fprintf(stderr, "gap specified without reorder probability\n");
        explain();
        return -1;
    }

    if (dist_size > 0 && (opt.latency == 0 || opt.jitter == 0)) {
        fprintf(stderr, "distribution specified but no latency and jitter values\n");
        explain();
        return -1;
    }

    addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
    addattr_l(n, 1024, TCA_NETEM_CORR, &cor, sizeof(cor));
    addattr_l(n, 1024, TCA_NETEM_REORDER, &reorder, sizeof(reorder));

    if (dist_size > 0) {
        addattr_l(n, 32768, TCA_NETEM_DELAY_DIST,
                  dist_data, dist_size*sizeof(dist_data[0]));
    }
    tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
    return 0;
}
Example #12
0
static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	int ok=0;
	struct tc_tbf_qopt opt;
	__u32 rtab[256];
	__u32 ptab[256];
	unsigned buffer=0, mtu=0, mpu=0, latency=0;
	int Rcell_log=-1, Pcell_log = -1; 
	struct rtattr *tail;

	memset(&opt, 0, sizeof(opt));

	while (argc > 0) {
		if (matches(*argv, "limit") == 0) {
			NEXT_ARG();
			if (opt.limit || latency) {
				fprintf(stderr, "Double \"limit/latency\" spec\n");
				return -1;
			}
			if (get_size(&opt.limit, *argv)) {
				explain1("limit");
				return -1;
			}
			ok++;
		} else if (matches(*argv, "latency") == 0) {
			NEXT_ARG();
			if (opt.limit || latency) {
				fprintf(stderr, "Double \"limit/latency\" spec\n");
				return -1;
			}
			if (get_usecs(&latency, *argv)) {
				explain1("latency");
				return -1;
			}
			ok++;
		} else if (matches(*argv, "burst") == 0 ||
			strcmp(*argv, "buffer") == 0 ||
			strcmp(*argv, "maxburst") == 0) {
			NEXT_ARG();
			if (buffer) {
				fprintf(stderr, "Double \"buffer/burst\" spec\n");
				return -1;
			}
			if (get_size_and_cell(&buffer, &Rcell_log, *argv) < 0) {
				explain1("buffer");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "mtu") == 0 ||
			   strcmp(*argv, "minburst") == 0) {
			NEXT_ARG();
			if (mtu) {
				fprintf(stderr, "Double \"mtu/minburst\" spec\n");
				return -1;
			}
			if (get_size_and_cell(&mtu, &Pcell_log, *argv) < 0) {
				explain1("mtu");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "mpu") == 0) {
			NEXT_ARG();
			if (mpu) {
				fprintf(stderr, "Double \"mpu\" spec\n");
				return -1;
			}
			if (get_size(&mpu, *argv)) {
				explain1("mpu");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "rate") == 0) {
			NEXT_ARG();
			if (opt.rate.rate) {
				fprintf(stderr, "Double \"rate\" spec\n");
				return -1;
			}
			if (get_rate(&opt.rate.rate, *argv)) {
				explain1("rate");
				return -1;
			}
			ok++;
		} else if (matches(*argv, "peakrate") == 0) {
			NEXT_ARG();
			if (opt.peakrate.rate) {
				fprintf(stderr, "Double \"peakrate\" spec\n");
				return -1;
			}
			if (get_rate(&opt.peakrate.rate, *argv)) {
				explain1("peakrate");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	if (!ok)
		return 0;

	if (opt.rate.rate == 0 || !buffer) {
		fprintf(stderr, "Both \"rate\" and \"burst\" are required.\n");
		return -1;
	}
	if (opt.peakrate.rate) {
		if (!mtu) {
			fprintf(stderr, "\"mtu\" is required, if \"peakrate\" is requested.\n");
			return -1;
		}
	}

	if (opt.limit == 0 && latency == 0) {
		fprintf(stderr, "Either \"limit\" or \"latency\" are required.\n");
		return -1;
	}

	if (opt.limit == 0) {
		double lim = opt.rate.rate*(double)latency/1000000 + buffer;
		if (opt.peakrate.rate) {
			double lim2 = opt.peakrate.rate*(double)latency/1000000 + mtu;
			if (lim2 < lim)
				lim = lim2;
		}
		opt.limit = lim;
	}

	if ((Rcell_log = tc_calc_rtable(opt.rate.rate, rtab, Rcell_log, mtu, mpu)) < 0) {
		fprintf(stderr, "TBF: failed to calculate rate table.\n");
		return -1;
	}
	opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer);
	opt.rate.cell_log = Rcell_log;
	opt.rate.mpu = mpu;
	if (opt.peakrate.rate) {
		if ((Pcell_log = tc_calc_rtable(opt.peakrate.rate, ptab, Pcell_log, mtu, mpu)) < 0) {
			fprintf(stderr, "TBF: failed to calculate peak rate table.\n");
			return -1;
		}
		opt.mtu = tc_calc_xmittime(opt.peakrate.rate, mtu);
		opt.peakrate.cell_log = Pcell_log;
		opt.peakrate.mpu = mpu;
	}

	tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	addattr_l(n, 2024, TCA_TBF_PARMS, &opt, sizeof(opt));
	addattr_l(n, 3024, TCA_TBF_RTAB, rtab, 1024);
	if (opt.peakrate.rate)
		addattr_l(n, 4096, TCA_TBF_PTAB, ptab, 1024);
	tail->rta_len = (((void*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
	return 0;
}
Example #13
0
static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
			   struct nlmsghdr *n)
{
	int dist_size = 0;
	struct rtattr *tail;
	struct tc_netem_qopt opt = { .limit = 1000 };
	struct tc_netem_corr cor;
	struct tc_netem_reorder reorder;
	struct tc_netem_corrupt corrupt;
	struct tc_netem_gimodel gimodel;
	struct tc_netem_gemodel gemodel;
	struct tc_netem_rate rate;
	__s16 *dist_data = NULL;
	__u16 loss_type = NETEM_LOSS_UNSPEC;
	int present[__TCA_NETEM_MAX];
	__u64 rate64 = 0;

	memset(&cor, 0, sizeof(cor));
	memset(&reorder, 0, sizeof(reorder));
	memset(&corrupt, 0, sizeof(corrupt));
	memset(&rate, 0, sizeof(rate));
	memset(present, 0, sizeof(present));

	for( ; argc > 0; --argc, ++argv) {
		if (matches(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_size(&opt.limit, *argv)) {
				explain1("limit");
				return -1;
			}
		} else if (matches(*argv, "latency") == 0 ||
			   matches(*argv, "delay") == 0) {
			NEXT_ARG();
			if (get_ticks(&opt.latency, *argv)) {
				explain1("latency");
				return -1;
			}

			if (NEXT_IS_NUMBER()) {
				NEXT_ARG();
				if (get_ticks(&opt.jitter, *argv)) {
					explain1("latency");
					return -1;
				}

				if (NEXT_IS_NUMBER()) {
					NEXT_ARG();
					++present[TCA_NETEM_CORR];
					if (get_percent(&cor.delay_corr, *argv)) {
						explain1("latency");
						return -1;
					}
				}
			}
		} else if (matches(*argv, "loss") == 0 ||
			   matches(*argv, "drop") == 0) {
			if (opt.loss > 0 || loss_type != NETEM_LOSS_UNSPEC) {
				explain1("duplicate loss argument\n");
				return -1;
			}

			NEXT_ARG();
			/* Old (deprecated) random loss model syntax */
			if (isdigit(argv[0][0]))
				goto random_loss_model;

			if (!strcmp(*argv, "random")) {
				NEXT_ARG();
	random_loss_model:
				if (get_percent(&opt.loss, *argv)) {
					explain1("loss percent");
					return -1;
				}
				if (NEXT_IS_NUMBER()) {
					NEXT_ARG();
					++present[TCA_NETEM_CORR];
					if (get_percent(&cor.loss_corr, *argv)) {
						explain1("loss correllation");
						return -1;
					}
				}
			} else if (!strcmp(*argv, "state")) {
				double p13;

				NEXT_ARG();
				if (parse_percent(&p13, *argv)) {
					explain1("loss p13");
					return -1;
				}

				/* set defaults */
				set_percent(&gimodel.p13, p13);
				set_percent(&gimodel.p31, 1. - p13);
				set_percent(&gimodel.p32, 0);
				set_percent(&gimodel.p23, 1.);
				set_percent(&gimodel.p14, 0);
				loss_type = NETEM_LOSS_GI;

				if (!NEXT_IS_NUMBER())
					continue;
				NEXT_ARG();
				if (get_percent(&gimodel.p31, *argv)) {
					explain1("loss p31");
					return -1;
				}

				if (!NEXT_IS_NUMBER())
					continue;
				NEXT_ARG();
				if (get_percent(&gimodel.p32, *argv)) {
					explain1("loss p32");
					return -1;
				}

				if (!NEXT_IS_NUMBER())
					continue;
				NEXT_ARG();
				if (get_percent(&gimodel.p23, *argv)) {
					explain1("loss p23");
					return -1;
				}
				if (!NEXT_IS_NUMBER())
					continue;
				NEXT_ARG();
				if (get_percent(&gimodel.p14, *argv)) {
					explain1("loss p14");
					return -1;
				}

			} else if (!strcmp(*argv, "gemodel")) {
				NEXT_ARG();
				if (get_percent(&gemodel.p, *argv)) {
					explain1("loss gemodel p");
					return -1;
				}

				/* set defaults */
				set_percent(&gemodel.r, 1.);
				set_percent(&gemodel.h, 0);
				set_percent(&gemodel.k1, 0);
				loss_type = NETEM_LOSS_GE;

				if (!NEXT_IS_NUMBER())
					continue;
				NEXT_ARG();
				if (get_percent(&gemodel.r, *argv)) {
					explain1("loss gemodel r");
					return -1;
				}

				if (!NEXT_IS_NUMBER())
					continue;
				NEXT_ARG();
				if (get_percent(&gemodel.h, *argv)) {
					explain1("loss gemodel h");
					return -1;
				}
				/* netem option is "1-h" but kernel
				 * expects "h".
				 */
				gemodel.h = max_percent_value - gemodel.h;

				if (!NEXT_IS_NUMBER())
					continue;
				NEXT_ARG();
				if (get_percent(&gemodel.k1, *argv)) {
					explain1("loss gemodel k");
					return -1;
				}
			} else {
				fprintf(stderr, "Unknown loss parameter: %s\n",
					*argv);
				return -1;
			}
		} else if (matches(*argv, "ecn") == 0) {
				present[TCA_NETEM_ECN] = 1;
		} else if (matches(*argv, "reorder") == 0) {
			NEXT_ARG();
			present[TCA_NETEM_REORDER] = 1;
			if (get_percent(&reorder.probability, *argv)) {
				explain1("reorder");
				return -1;
			}
			if (NEXT_IS_NUMBER()) {
				NEXT_ARG();
				++present[TCA_NETEM_CORR];
				if (get_percent(&reorder.correlation, *argv)) {
					explain1("reorder");
					return -1;
				}
			}
		} else if (matches(*argv, "corrupt") == 0) {
			NEXT_ARG();
			present[TCA_NETEM_CORRUPT] = 1;
			if (get_percent(&corrupt.probability, *argv)) {
				explain1("corrupt");
				return -1;
			}
			if (NEXT_IS_NUMBER()) {
				NEXT_ARG();
				++present[TCA_NETEM_CORR];
				if (get_percent(&corrupt.correlation, *argv)) {
					explain1("corrupt");
					return -1;
				}
			}
		} else if (matches(*argv, "gap") == 0) {
			NEXT_ARG();
			if (get_u32(&opt.gap, *argv, 0)) {
				explain1("gap");
				return -1;
			}
		} else if (matches(*argv, "duplicate") == 0) {
			NEXT_ARG();
			if (get_percent(&opt.duplicate, *argv)) {
				explain1("duplicate");
				return -1;
			}
			if (NEXT_IS_NUMBER()) {
				NEXT_ARG();
				if (get_percent(&cor.dup_corr, *argv)) {
					explain1("duplicate");
					return -1;
				}
			}
		} else if (matches(*argv, "distribution") == 0) {
			NEXT_ARG();
			dist_data = calloc(sizeof(dist_data[0]), MAX_DIST);
			dist_size = get_distribution(*argv, dist_data, MAX_DIST);
			if (dist_size <= 0) {
				free(dist_data);
				return -1;
			}
		} else if (matches(*argv, "rate") == 0) {
			++present[TCA_NETEM_RATE];
			NEXT_ARG();
			if (get_rate64(&rate64, *argv)) {
				explain1("rate");
				return -1;
			}
			if (NEXT_IS_SIGNED_NUMBER()) {
				NEXT_ARG();
				if (get_s32(&rate.packet_overhead, *argv, 0)) {
					explain1("rate");
					return -1;
				}
			}
			if (NEXT_IS_NUMBER()) {
				NEXT_ARG();
				if (get_u32(&rate.cell_size, *argv, 0)) {
					explain1("rate");
					return -1;
				}
			}
			if (NEXT_IS_SIGNED_NUMBER()) {
				NEXT_ARG();
				if (get_s32(&rate.cell_overhead, *argv, 0)) {
					explain1("rate");
					return -1;
				}
			}
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
	}

	tail = NLMSG_TAIL(n);

	if (reorder.probability) {
		if (opt.latency == 0) {
			fprintf(stderr, "reordering not possible without specifying some delay\n");
			explain();
			return -1;
		}
		if (opt.gap == 0)
			opt.gap = 1;
	} else if (opt.gap > 0) {
		fprintf(stderr, "gap specified without reorder probability\n");
		explain();
		return -1;
	}

	if (present[TCA_NETEM_ECN]) {
		if (opt.loss <= 0 && loss_type == NETEM_LOSS_UNSPEC) {
			fprintf(stderr, "ecn requested without loss model\n");
			explain();
			return -1;
		}
	}

	if (dist_data && (opt.latency == 0 || opt.jitter == 0)) {
		fprintf(stderr, "distribution specified but no latency and jitter values\n");
		explain();
		return -1;
	}

	if (addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)) < 0)
		return -1;

	if (present[TCA_NETEM_CORR] &&
	    addattr_l(n, 1024, TCA_NETEM_CORR, &cor, sizeof(cor)) < 0)
			return -1;

	if (present[TCA_NETEM_REORDER] &&
	    addattr_l(n, 1024, TCA_NETEM_REORDER, &reorder, sizeof(reorder)) < 0)
		return -1;

	if (present[TCA_NETEM_ECN] &&
	    addattr_l(n, 1024, TCA_NETEM_ECN, &present[TCA_NETEM_ECN],
		      sizeof(present[TCA_NETEM_ECN])) < 0)
			return -1;

	if (present[TCA_NETEM_CORRUPT] &&
	    addattr_l(n, 1024, TCA_NETEM_CORRUPT, &corrupt, sizeof(corrupt)) < 0)
		return -1;

	if (loss_type != NETEM_LOSS_UNSPEC) {
		struct rtattr *start;

		start = addattr_nest(n, 1024, TCA_NETEM_LOSS | NLA_F_NESTED);
		if (loss_type == NETEM_LOSS_GI) {
			if (addattr_l(n, 1024, NETEM_LOSS_GI,
				      &gimodel, sizeof(gimodel)) < 0)
			    return -1;
		} else if (loss_type == NETEM_LOSS_GE) {
			if (addattr_l(n, 1024, NETEM_LOSS_GE,
				      &gemodel, sizeof(gemodel)) < 0)
			    return -1;
		} else {
			fprintf(stderr, "loss in the weeds!\n");
			return -1;
		}
		
		addattr_nest_end(n, start);
	}

	if (present[TCA_NETEM_RATE]) {
		if (rate64 >= (1ULL << 32)) {
			if (addattr_l(n, 1024,
				      TCA_NETEM_RATE64, &rate64, sizeof(rate64)) < 0)
				return -1;
			rate.rate = ~0U;
		} else {
			rate.rate = rate64;
		}
		if (addattr_l(n, 1024, TCA_NETEM_RATE, &rate, sizeof(rate)) < 0)
			return -1;
	}

	if (dist_data) {
		if (addattr_l(n, MAX_DIST * sizeof(dist_data[0]),
			      TCA_NETEM_DELAY_DIST,
			      dist_data, dist_size * sizeof(dist_data[0])) < 0)
			return -1;
		free(dist_data);
	}
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	return 0;
}

static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
	const struct tc_netem_corr *cor = NULL;
	const struct tc_netem_reorder *reorder = NULL;
	const struct tc_netem_corrupt *corrupt = NULL;
	const struct tc_netem_gimodel *gimodel = NULL;
	const struct tc_netem_gemodel *gemodel = NULL;
	int *ecn = NULL;
	struct tc_netem_qopt qopt;
	const struct tc_netem_rate *rate = NULL;
	int len = RTA_PAYLOAD(opt) - sizeof(qopt);
	__u64 rate64 = 0;
	SPRINT_BUF(b1);

	if (opt == NULL)
		return 0;

	if (len < 0) {
		fprintf(stderr, "options size error\n");
		return -1;
	}
	memcpy(&qopt, RTA_DATA(opt), sizeof(qopt));

	if (len > 0) {
		struct rtattr *tb[TCA_NETEM_MAX+1];
		parse_rtattr(tb, TCA_NETEM_MAX, RTA_DATA(opt) + sizeof(qopt),
			     len);

		if (tb[TCA_NETEM_CORR]) {
			if (RTA_PAYLOAD(tb[TCA_NETEM_CORR]) < sizeof(*cor))
				return -1;
			cor = RTA_DATA(tb[TCA_NETEM_CORR]);
		}
		if (tb[TCA_NETEM_REORDER]) {
			if (RTA_PAYLOAD(tb[TCA_NETEM_REORDER]) < sizeof(*reorder))
				return -1;
			reorder = RTA_DATA(tb[TCA_NETEM_REORDER]);
		}
		if (tb[TCA_NETEM_CORRUPT]) {
			if (RTA_PAYLOAD(tb[TCA_NETEM_CORRUPT]) < sizeof(*corrupt))
				return -1;
			corrupt = RTA_DATA(tb[TCA_NETEM_CORRUPT]);
		}
		if (tb[TCA_NETEM_LOSS]) {
			struct rtattr *lb[NETEM_LOSS_MAX + 1];

			parse_rtattr_nested(lb, NETEM_LOSS_MAX, tb[TCA_NETEM_LOSS]);
			if (lb[NETEM_LOSS_GI])
				gimodel = RTA_DATA(lb[NETEM_LOSS_GI]);
			if (lb[NETEM_LOSS_GE])
				gemodel = RTA_DATA(lb[NETEM_LOSS_GE]);
		}			
		if (tb[TCA_NETEM_RATE]) {
			if (RTA_PAYLOAD(tb[TCA_NETEM_RATE]) < sizeof(*rate))
				return -1;
			rate = RTA_DATA(tb[TCA_NETEM_RATE]);
		}
		if (tb[TCA_NETEM_ECN]) {
			if (RTA_PAYLOAD(tb[TCA_NETEM_ECN]) < sizeof(*ecn))
				return -1;
			ecn = RTA_DATA(tb[TCA_NETEM_ECN]);
		}
		if (tb[TCA_NETEM_RATE64]) {
			if (RTA_PAYLOAD(tb[TCA_NETEM_RATE64]) < sizeof(rate64))
				return -1;
			rate64 = rta_getattr_u64(tb[TCA_NETEM_RATE64]);
		}
	}

	fprintf(f, "limit %d", qopt.limit);

	if (qopt.latency) {
		fprintf(f, " delay %s", sprint_ticks(qopt.latency, b1));

		if (qopt.jitter) {
			fprintf(f, "  %s", sprint_ticks(qopt.jitter, b1));
			if (cor && cor->delay_corr)
				fprintf(f, " %s", sprint_percent(cor->delay_corr, b1));
		}
	}

	if (qopt.loss) {
		fprintf(f, " loss %s", sprint_percent(qopt.loss, b1));
		if (cor && cor->loss_corr)
			fprintf(f, " %s", sprint_percent(cor->loss_corr, b1));
	}

	if (gimodel) {
		fprintf(f, " loss state p13 %s", sprint_percent(gimodel->p13, b1));
		fprintf(f, " p31 %s", sprint_percent(gimodel->p31, b1));
		fprintf(f, " p32 %s", sprint_percent(gimodel->p32, b1));
		fprintf(f, " p23 %s", sprint_percent(gimodel->p23, b1));
		fprintf(f, " p14 %s", sprint_percent(gimodel->p14, b1));
	}

	if (gemodel) {
		fprintf(f, " loss gemodel p %s",
			sprint_percent(gemodel->p, b1));
		fprintf(f, " r %s", sprint_percent(gemodel->r, b1));
		fprintf(f, " 1-h %s", sprint_percent(max_percent_value -
						     gemodel->h, b1));
		fprintf(f, " 1-k %s", sprint_percent(gemodel->k1, b1));
	}

	if (qopt.duplicate) {
		fprintf(f, " duplicate %s",
			sprint_percent(qopt.duplicate, b1));
		if (cor && cor->dup_corr)
			fprintf(f, " %s", sprint_percent(cor->dup_corr, b1));
	}

	if (reorder && reorder->probability) {
		fprintf(f, " reorder %s",
			sprint_percent(reorder->probability, b1));
		if (reorder->correlation)
			fprintf(f, " %s",
				sprint_percent(reorder->correlation, b1));
	}

	if (corrupt && corrupt->probability) {
		fprintf(f, " corrupt %s",
			sprint_percent(corrupt->probability, b1));
		if (corrupt->correlation)
			fprintf(f, " %s",
				sprint_percent(corrupt->correlation, b1));
	}

	if (rate && rate->rate) {
		if (rate64)
			fprintf(f, " rate %s", sprint_rate(rate64, b1));
		else
			fprintf(f, " rate %s", sprint_rate(rate->rate, b1));
		if (rate->packet_overhead)
			fprintf(f, " packetoverhead %d", rate->packet_overhead);
		if (rate->cell_size)
			fprintf(f, " cellsize %u", rate->cell_size);
		if (rate->cell_overhead)
			fprintf(f, " celloverhead %d", rate->cell_overhead);
	}

	if (ecn)
		fprintf(f, " ecn ");

	if (qopt.gap)
		fprintf(f, " gap %lu", (unsigned long)qopt.gap);


	return 0;
}

struct qdisc_util netem_qdisc_util = {
	.id	   	= "netem",
	.parse_qopt	= netem_parse_opt,
	.print_qopt	= netem_print_opt,
};
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;
}
Example #15
0
static int
hfsc_get_sc2(int *argcp, char ***argvp, struct tc_service_curve *sc, const char *dev)
{
	char **argv = *argvp;
	int argc = *argcp;
	unsigned int umax = 0, dmax = 0, rate = 0;

	if (matches(*argv, "umax") == 0) {
		NEXT_ARG();
		if (get_size(&umax, *argv) < 0) {
			explain1("umax");
			return -1;
		}
		NEXT_ARG();
	}

	if (matches(*argv, "dmax") == 0) {
		NEXT_ARG();
		if (get_time(&dmax, *argv) < 0) {
			explain1("dmax");
			return -1;
		}
		NEXT_ARG();
	}

	if (matches(*argv, "rate") == 0) {
		NEXT_ARG();
		if (strchr(*argv, '%')) {
			if (get_percent_rate(&rate, *argv, dev)) {
				explain1("rate");
				return -1;
			}
		} else if (get_rate(&rate, *argv) < 0) {
			explain1("rate");
			return -1;
		}
	} else
		return -1;

	if (umax != 0 && dmax == 0) {
		fprintf(stderr, "HFSC: umax given but dmax is zero.\n");
		return -1;
	}

	if (dmax != 0 && ceil(1.0 * umax * TIME_UNITS_PER_SEC / dmax) > rate) {
		/*
		 * concave curve, slope of first segment is umax/dmax,
		 * intersection is at dmax
		 */
		sc->m1 = ceil(1.0 * umax * TIME_UNITS_PER_SEC / dmax); /* in bps */
		sc->d  = tc_core_time2ktime(dmax);
		sc->m2 = rate;
	} else {
		/*
		 * convex curve, slope of first segment is 0, intersection
		 * is at dmax - umax / rate
		 */
		sc->m1 = 0;
		sc->d  = tc_core_time2ktime(ceil(dmax - umax * TIME_UNITS_PER_SEC / rate));
		sc->m2 = rate;
	}

	*argvp = argv;
	*argcp = argc;
	return 0;
}
Example #16
0
int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	int ok=0;
	struct tc_htb_opt opt;
	__u32 * rtab = vmalloc(256*sizeof(__u32));
	__u32 * ctab = vmalloc(256*sizeof(__u32));
	unsigned buffer=0,cbuffer=0;
	int cell_log=-1,ccell_log = -1;
	unsigned mtu;
	unsigned short mpu = 0;
	unsigned short overhead = 0;
	unsigned int linklayer  = LINKLAYER_ETHERNET;
	struct rtattr *tail;

	memset(&opt, 0, sizeof(opt)); 
	mtu = 1600;

	while (argc > 0) {
		if (matches(*argv, "prio") == 0) {
			NEXT_ARG();
			if (get_u32(&opt.prio, *argv, 10)) {
				explain1("prio"); return -1;
			}
			ok++;
		} else if (matches(*argv, "mtu") == 0) {
			NEXT_ARG();
			if (get_u32(&mtu, *argv, 10)) {
				explain1("mtu"); return -1;
			}
		} else if (matches(*argv, "mpu") == 0) {
			NEXT_ARG();
			if (get_u16(&mpu, *argv, 10)) {
				explain1("mpu"); return -1;
			}
		} 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, "quantum") == 0) {
			NEXT_ARG();
			if (get_u32(&opt.quantum, *argv, 10)) {
				explain1("quantum"); return -1;
			}
		}    /* else if (matches(*argv, "burst") == 0 ||
			strcmp(*argv, "buffer") == 0 ||
			strcmp(*argv, "maxburst") == 0) {
			NEXT_ARG();
			if (get_size_and_cell(&buffer, &cell_log, *argv) < 0) {
				explain1("buffer");
				return -1;
			}
			ok++;
		} */ /* else if (matches(*argv, "cburst") == 0 ||
			strcmp(*argv, "cbuffer") == 0 ||
			strcmp(*argv, "cmaxburst") == 0) {
			NEXT_ARG(); 
			if (get_size_and_cell(&cbuffer, &ccell_log, *argv) < 0) {
				explain1("cbuffer");
				return -1;
			}
			ok++;
		} */ else if (strcmp(*argv, "ceil") == 0) {
			NEXT_ARG();
			if (opt.ceil.rate) {
				printk(KERN_DEBUG "[MTC] [Q_HTB] Double \"ceil\" spec\n");
				return -1;
			}
			if (get_rate(&opt.ceil.rate, *argv)) {
				explain1("ceil");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "rate") == 0) {
			NEXT_ARG();
			if (opt.rate.rate) {
				printk(KERN_DEBUG "[MTC] [Q_HTB] Double \"rate\" spec\n");
				return -1;
			}
			if (get_rate(&opt.rate.rate, *argv)) {
				explain1("rate");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "help") == 0) {
			return -1;
		} else {
			printk(KERN_DEBUG "[MTC] [Q_HTB] What is \"%s\"?\n", *argv);
			return -1;
		}
		argc--; argv++;
	}

/*	if (!ok)
		return 0;*/

	
	if (opt.rate.rate == 0) {
		printk(KERN_DEBUG "[MTC] [Q_HTB] \"rate\" is required.\n");
		return -1;
	}
	if (!opt.ceil.rate) opt.ceil = opt.rate;

	if (!buffer) buffer = opt.rate.rate / get_hz() + mtu;
	if (!cbuffer) cbuffer = opt.ceil.rate / get_hz() + mtu;
	
	opt.ceil.overhead = overhead;
	opt.rate.overhead = overhead;

	opt.ceil.mpu = mpu;
	opt.rate.mpu = mpu;

	if (tc_calc_rtable(&opt.rate, rtab, cell_log, mtu, linklayer) < 0) {
		printk(KERN_DEBUG "[MTC] [Q_HTB] error: failed to calculate rate table.\n");
		return -1;
	}
	opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer);
	
	
	if (tc_calc_rtable(&opt.ceil, ctab, ccell_log, mtu, linklayer) < 0) {
		printk(KERN_DEBUG "[MTC] [Q_HTB] error: failed to calculate ceil rate table.\n");
		return -1;
	}
	opt.cbuffer = tc_calc_xmittime(opt.ceil.rate, cbuffer);

	
	tail = NLMSG_TAIL(n);
	
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	addattr_l(n, 2024, TCA_HTB_PARMS, &opt, sizeof(opt));
	addattr_l(n, 3024, TCA_HTB_RTAB, rtab, 1024);
	addattr_l(n, 4024, TCA_HTB_CTAB, ctab, 1024);
	
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	
	return 0;
}
Example #17
0
static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	int ok=0;
	struct tc_htb_opt opt;
	__u32 rtab[256],ctab[256];
	unsigned buffer=0,cbuffer=0;
	int cell_log=-1,ccell_log = -1;
	unsigned mtu, mpu;
	unsigned char mpu8 = 0, overhead = 0;
	struct rtattr *tail;

	memset(&opt, 0, sizeof(opt)); mtu = 1600; /* eth packet len */

	while (argc > 0) {
		if (matches(*argv, "prio") == 0) {
			NEXT_ARG();
			if (get_u32(&opt.prio, *argv, 10)) {
				explain1("prio"); return -1;
			}
			ok++;
		} else if (matches(*argv, "mtu") == 0) {
			NEXT_ARG();
			if (get_u32(&mtu, *argv, 10)) {
				explain1("mtu"); return -1;
			}
		} else if (matches(*argv, "mpu") == 0) {
			NEXT_ARG();
			if (get_u8(&mpu8, *argv, 10)) {
				explain1("mpu"); return -1;
			}
		} else if (matches(*argv, "overhead") == 0) {
			NEXT_ARG();
			if (get_u8(&overhead, *argv, 10)) {
				explain1("overhead"); return -1;
			}
		} else if (matches(*argv, "quantum") == 0) {
			NEXT_ARG();
			if (get_u32(&opt.quantum, *argv, 10)) {
				explain1("quantum"); return -1;
			}
		} else if (matches(*argv, "burst") == 0 ||
			strcmp(*argv, "buffer") == 0 ||
			strcmp(*argv, "maxburst") == 0) {
			NEXT_ARG();
			if (get_size_and_cell(&buffer, &cell_log, *argv) < 0) {
				explain1("buffer");
				return -1;
			}
			ok++;
		} else if (matches(*argv, "cburst") == 0 ||
			strcmp(*argv, "cbuffer") == 0 ||
			strcmp(*argv, "cmaxburst") == 0) {
			NEXT_ARG();
			if (get_size_and_cell(&cbuffer, &ccell_log, *argv) < 0) {
				explain1("cbuffer");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "ceil") == 0) {
			NEXT_ARG();
			if (opt.ceil.rate) {
//				fprintf(stderr, "Double \"ceil\" spec\n");
				return -1;
			}
			if (get_rate(&opt.ceil.rate, *argv)) {
				explain1("ceil");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "rate") == 0) {
			NEXT_ARG();
			if (opt.rate.rate) {
//				fprintf(stderr, "Double \"rate\" spec\n");
				return -1;
			}
			if (get_rate(&opt.rate.rate, *argv)) {
				explain1("rate");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
//			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

/*	if (!ok)
		return 0;*/

	if (opt.rate.rate == 0) {
//		fprintf(stderr, "\"rate\" is required.\n");
		return -1;
	}
	/* if ceil params are missing, use the same as rate */
	if (!opt.ceil.rate) opt.ceil = opt.rate;

	/* compute minimal allowed burst from rate; mtu is added here to make
	   sute that buffer is larger than mtu and to have some safeguard space */
	if (!buffer) buffer = opt.rate.rate / HZ + mtu;
	if (!cbuffer) cbuffer = opt.ceil.rate / HZ + mtu;

/* encode overhead and mpu, 8 bits each, into lower 16 bits */
	mpu = (unsigned)mpu8 | (unsigned)overhead << 8;
	opt.ceil.mpu = mpu; opt.rate.mpu = mpu;

	if ((cell_log = tc_calc_rtable(opt.rate.rate, rtab, cell_log, mtu, mpu)) < 0) {
//		fprintf(stderr, "htb: failed to calculate rate table.\n");
		return -1;
	}
	opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer);
	opt.rate.cell_log = cell_log;
	
	if ((ccell_log = tc_calc_rtable(opt.ceil.rate, ctab, cell_log, mtu, mpu)) < 0) {
//		fprintf(stderr, "htb: failed to calculate ceil rate table.\n");
		return -1;
	}
	opt.cbuffer = tc_calc_xmittime(opt.ceil.rate, cbuffer);
	opt.ceil.cell_log = ccell_log;

	tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	addattr_l(n, 2024, TCA_HTB_PARMS, &opt, sizeof(opt));
	addattr_l(n, 3024, TCA_HTB_RTAB, rtab, 1024);
	addattr_l(n, 4024, TCA_HTB_CTAB, ctab, 1024);
	tail->rta_len = (((void*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
	return 0;
}
static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	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;
	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) {
			NEXT_ARG();
			if (get_rate(&r.rate, *argv)) {
				explain1("bandwidth");
				return -1;
			}
		} else if (strcmp(*argv, "ewma") == 0) {
			NEXT_ARG();
			if (get_unsigned(&ewma_log, *argv, 0)) {
				explain1("ewma");
				return -1;
			}
			if (ewma_log > 31) {
				fprintf(stderr, "ewma_log must be < 32\n");
				return -1;
			}
		} 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, "avpkt") == 0) {
			NEXT_ARG();
			if (get_size(&avpkt, *argv)) {
				explain1("avpkt");
				return -1;
			}
		} else if (strcmp(*argv, "mpu") == 0) {
			NEXT_ARG();
			if (get_size(&mpu, *argv)) {
				explain1("mpu");
				return -1;
			}
		} else if (strcmp(*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) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	/* OK. All options are parsed. */

	if (r.rate == 0) {
		fprintf(stderr, "CBQ: bandwidth is required parameter.\n");
		return -1;
	}
	if (avpkt == 0) {
		fprintf(stderr, "CBQ: \"avpkt\" is required.\n");
		return -1;
	}
	if (allot < (avpkt*3)/2)
		allot = (avpkt*3)/2;

	if ((cell_log = tc_calc_rtable(r.rate, rtab, cell_log, allot, 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;
	lss.maxidle = tc_cbq_calc_maxidle(r.rate, r.rate, avpkt, lss.ewma_log, 0);
	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);
	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++)
			printf("%u ", rtab[i]);
		printf("\n");
	}
	tail->rta_len = (((void*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
	return 0;
}
int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
{
	int argc = *argc_p;
	char **argv = *argv_p;
	int res = -1;
	int ok=0;
	struct tc_police p;
	__u32 rtab[256];
	__u32 ptab[256];
	__u32 avrate = 0;
	int presult = 0;
	unsigned buffer=0, mtu=0, mpu=0;
	unsigned short overhead=0;
	unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
	int Rcell_log=-1, Pcell_log = -1;
	struct rtattr *tail;

	memset(&p, 0, sizeof(p));
	p.action = TC_POLICE_RECLASSIFY;

	if (a) /* new way of doing things */
		NEXT_ARG();

	if (argc <= 0)
		return -1;

	while (argc > 0) {

		if (matches(*argv, "index") == 0) {
			NEXT_ARG();
			if (get_u32(&p.index, *argv, 10)) {
				fprintf(stderr, "Illegal \"index\"\n");
				return -1;
			}
		} else if (matches(*argv, "burst") == 0 ||
			strcmp(*argv, "buffer") == 0 ||
			strcmp(*argv, "maxburst") == 0) {
			NEXT_ARG();
			if (buffer) {
				fprintf(stderr, "Double \"buffer/burst\" spec\n");
				return -1;
			}
			if (get_size_and_cell(&buffer, &Rcell_log, *argv) < 0) {
				explain1("buffer");
				return -1;
			}
		} else if (strcmp(*argv, "mtu") == 0 ||
			   strcmp(*argv, "minburst") == 0) {
			NEXT_ARG();
			if (mtu) {
				fprintf(stderr, "Double \"mtu/minburst\" spec\n");
				return -1;
			}
			if (get_size_and_cell(&mtu, &Pcell_log, *argv) < 0) {
				explain1("mtu");
				return -1;
			}
		} else if (strcmp(*argv, "mpu") == 0) {
			NEXT_ARG();
			if (mpu) {
				fprintf(stderr, "Double \"mpu\" spec\n");
				return -1;
			}
			if (get_size(&mpu, *argv)) {
				explain1("mpu");
				return -1;
			}
		} else if (strcmp(*argv, "rate") == 0) {
			NEXT_ARG();
			if (p.rate.rate) {
				fprintf(stderr, "Double \"rate\" spec\n");
				return -1;
			}
			if (get_rate(&p.rate.rate, *argv)) {
				explain1("rate");
				return -1;
			}
		} else if (strcmp(*argv, "avrate") == 0) {
			NEXT_ARG();
			if (avrate) {
				fprintf(stderr, "Double \"avrate\" spec\n");
				return -1;
			}
			if (get_rate(&avrate, *argv)) {
				explain1("avrate");
				return -1;
			}
		} else if (matches(*argv, "peakrate") == 0) {
			NEXT_ARG();
			if (p.peakrate.rate) {
				fprintf(stderr, "Double \"peakrate\" spec\n");
				return -1;
			}
			if (get_rate(&p.peakrate.rate, *argv)) {
				explain1("peakrate");
				return -1;
			}
		} else if (matches(*argv, "reclassify") == 0) {
			p.action = TC_POLICE_RECLASSIFY;
		} else if (matches(*argv, "drop") == 0 ||
			   matches(*argv, "shot") == 0) {
			p.action = TC_POLICE_SHOT;
		} else if (matches(*argv, "continue") == 0) {
			p.action = TC_POLICE_UNSPEC;
		} else if (matches(*argv, "pass") == 0) {
			p.action = TC_POLICE_OK;
		} else if (matches(*argv, "pipe") == 0) {
			p.action = TC_POLICE_PIPE;
		} else if (strcmp(*argv, "action") == 0 ||
			   strcmp(*argv, "conform-exceed") == 0) {
			NEXT_ARG();
			if (get_police_result(&p.action, &presult, *argv)) {
				fprintf(stderr, "Illegal \"action\"\n");
				return -1;
			}
		} 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 (strcmp(*argv, "help") == 0) {
			usage();
		} else {
			break;
		}
		ok++;
		argc--; argv++;
	}

	if (!ok)
		return -1;

	if (p.rate.rate && !buffer) {
		fprintf(stderr, "\"burst\" requires \"rate\".\n");
		return -1;
	}
	if (p.peakrate.rate) {
		if (!p.rate.rate) {
			fprintf(stderr, "\"peakrate\" requires \"rate\".\n");
			return -1;
		}
		if (!mtu) {
			fprintf(stderr, "\"mtu\" is required, if \"peakrate\" is requested.\n");
			return -1;
		}
	}

	if (p.rate.rate) {
		p.rate.mpu = mpu;
		p.rate.overhead = overhead;
		if (tc_calc_rtable(&p.rate, rtab, Rcell_log, mtu, linklayer) < 0) {
			fprintf(stderr, "TBF: failed to calculate rate table.\n");
			return -1;
		}
		p.burst = tc_calc_xmittime(p.rate.rate, buffer);
	}
	p.mtu = mtu;
	if (p.peakrate.rate) {
		p.peakrate.mpu = mpu;
		p.peakrate.overhead = overhead;
		if (tc_calc_rtable(&p.peakrate, ptab, Pcell_log, mtu, linklayer) < 0) {
			fprintf(stderr, "POLICE: failed to calculate peak rate table.\n");
			return -1;
		}
	}

	tail = NLMSG_TAIL(n);
	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
	addattr_l(n, MAX_MSG, TCA_POLICE_TBF, &p, sizeof(p));
	if (p.rate.rate)
		addattr_l(n, MAX_MSG, TCA_POLICE_RATE, rtab, 1024);
	if (p.peakrate.rate)
                addattr_l(n, MAX_MSG, TCA_POLICE_PEAKRATE, ptab, 1024);
	if (avrate)
		addattr32(n, MAX_MSG, TCA_POLICE_AVRATE, avrate);
	if (presult)
		addattr32(n, MAX_MSG, TCA_POLICE_RESULT, presult);

	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	res = 0;

	*argc_p = argc;
	*argv_p = argv;
	return res;
}
Example #20
0
static int esfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	int ok=0;
	struct tc_esfq_qopt opt;

	memset(&opt, 0, sizeof(opt));

	opt.hash_kind= TCA_SFQ_HASH_CLASSIC;

	while (argc > 0) {
		if (strcmp(*argv, "quantum") == 0) {
			NEXT_ARG();
			if (get_size(&opt.quantum, *argv)) {
				explain1("quantum"); return -1;
			}
			ok++;
		} else if (strcmp(*argv, "perturb") == 0) {
			NEXT_ARG();
			if (get_integer(&opt.perturb_period, *argv, 0)) {
				explain1("perturb"); return -1;
			}
			ok++;
		} else if (strcmp(*argv, "depth") == 0) {
			NEXT_ARG();
			if (get_integer((int *) &opt.flows, *argv, 0)) {
				explain1("depth"); return -1;
			}
			ok++;
		} else if (strcmp(*argv, "divisor") == 0) {
			NEXT_ARG();
			if (get_integer((int *) &opt.divisor, *argv, 0)) {
				explain1("divisor"); return -1;
			}
			if(opt.divisor >= 14) {
				fprintf(stderr, "Illegal \"divisor\": must be < 14\n");
				return -1;
			}
			opt.divisor=pow(2,opt.divisor);
			ok++;
		} else if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_integer((int *) &opt.limit, *argv, 0)) {
				explain1("limit"); return -1;
			}
			ok++;
		} else if (strcmp(*argv, "hash") == 0) {
			NEXT_ARG();
			if(strcmp(*argv, "classic") == 0) {
				opt.hash_kind= TCA_SFQ_HASH_CLASSIC;
			} else
			if(strcmp(*argv, "dst") == 0) {
				opt.hash_kind= TCA_SFQ_HASH_DST;
			} else
			if(strcmp(*argv, "src") == 0) {
				opt.hash_kind= TCA_SFQ_HASH_SRC;
			} else
			if(strcmp(*argv, "fwmark") == 0) {
				opt.hash_kind= TCA_SFQ_HASH_FWMARK;
			} else
			if(strcmp(*argv, "ctorigsrc") == 0) {
				opt.hash_kind= TCA_SFQ_HASH_CTORIGSRC;
			} else
			if(strcmp(*argv, "ctorigdst") == 0) {
				opt.hash_kind= TCA_SFQ_HASH_CTORIGDST;
			} else
			if(strcmp(*argv, "ctreplsrc") == 0) {
				opt.hash_kind= TCA_SFQ_HASH_CTREPLSRC;
			} else
			if(strcmp(*argv, "ctrepldst") == 0) {
				opt.hash_kind= TCA_SFQ_HASH_CTREPLDST;
			} else
			if(strcmp(*argv, "ctnatchg") == 0) {
				opt.hash_kind= TCA_SFQ_HASH_CTNATCHG;
			} else {
				explain1("hash"); return -1;
			}
			ok++;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	if (ok)
		addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
	return 0;
}