1309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger/*
2309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger * q_netem.c		NETEM.
3309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger *
4309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger *		This program is free software; you can redistribute it and/or
5309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger *		modify it under the terms of the GNU General Public License
6309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger *		as published by the Free Software Foundation; either version
7309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger *		2 of the License, or (at your option) any later version.
8309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger *
959a935d2045b233539a2d0be00310d355a9e0ebdStephen Hemminger * Authors:	Stephen Hemminger <shemminger@linux-foundation.org>
10309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger *
11309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger */
12309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
13309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <stdio.h>
14309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <stdlib.h>
153c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger#include <math.h>
163c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger#include <ctype.h>
17309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <unistd.h>
18309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <syslog.h>
19309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <fcntl.h>
20309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <sys/socket.h>
21309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <netinet/in.h>
22309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <arpa/inet.h>
23309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <string.h>
24b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger#include <errno.h>
25309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
26309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include "utils.h"
27309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include "tc_util.h"
28b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger#include "tc_common.h"
29309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
30309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemmingerstatic void explain(void)
31309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{
32ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger	fprintf(stderr,
33b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger"Usage: ... netem [ limit PACKETS ] \n" \
34ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger"                 [ delay TIME [ JITTER [CORRELATION]]]\n" \
35ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger"                 [ distribution {uniform|normal|pareto|paretonormal} ]\n" \
36a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger"                 [ corrupt PERCENT [CORRELATION]] \n" \
37b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger"                 [ duplicate PERCENT [CORRELATION]]\n" \
383c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger"                 [ loss random PERCENT [CORRELATION]]\n" \
393c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger"                 [ loss state P13 [P31 [P32 [P23 P14]]]\n" \
403c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger"                 [ loss gemodel PERCENT [R [1-H [1-K]]]\n" \
411070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian"                 [ ecn ]\n" \
426b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer"                 [ reorder PRECENT [CORRELATION] [ gap DISTANCE ]]\n" \
436b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer"                 [ rate RATE [PACKETOVERHEAD] [CELLSIZE] [CELLOVERHEAD]]\n");
44309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger}
45309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
46309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemmingerstatic void explain1(const char *arg)
47309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{
48309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger	fprintf(stderr, "Illegal \"%s\"\n", arg);
49309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger}
50309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
513c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger/* Upper bound on size of distribution
52c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger *  really (TCA_BUF_MAX - other headers) / sizeof (__s16)
53c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger */
54c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger#define MAX_DIST	(16*1024)
55c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger
563c7950af598beab378a291ee0540da438978a4b2Stephen Hemmingerstatic const double max_percent_value = 0xffffffff;
573c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
583c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger/* scaled value used to percent of maximum. */
593c7950af598beab378a291ee0540da438978a4b2Stephen Hemmingerstatic void set_percent(__u32 *percent, double per)
603c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger{
613c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	*percent = (unsigned) rint(per * max_percent_value);
623c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger}
633c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
643c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
653c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger/* Parse either a fraction '.3' or percent '30%
663c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger * return: 0 = ok, -1 = error, 1 = out of range
673c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger */
683c7950af598beab378a291ee0540da438978a4b2Stephen Hemmingerstatic int parse_percent(double *val, const char *str)
693c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger{
703c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	char *p;
713c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
723c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	*val = strtod(str, &p) / 100.;
733c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (*p && strcmp(p, "%") )
743c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		return -1;
753c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
763c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	return 0;
773c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger}
783c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
793c7950af598beab378a291ee0540da438978a4b2Stephen Hemmingerstatic int get_percent(__u32 *percent, const char *str)
803c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger{
813c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	double per;
823c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
833c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (parse_percent(&per, str))
843c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		return -1;
853c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
863c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	set_percent(percent, per);
873c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	return 0;
883c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger}
893c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
90d1f28cf181a6f77f230d90267eef0ecfbcb25f30Stephen Hemmingerstatic void print_percent(char *buf, int len, __u32 per)
913c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger{
923c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	snprintf(buf, len, "%g%%", 100. * (double) per / max_percent_value);
933c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger}
943c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
95d1f28cf181a6f77f230d90267eef0ecfbcb25f30Stephen Hemmingerstatic char * sprint_percent(__u32 per, char *buf)
963c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger{
973c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	print_percent(buf, SPRINT_BSIZE-1, per);
983c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	return buf;
993c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger}
1003c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
1012e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger/*
1022e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger * Simplistic file parser for distrbution data.
1032e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger * Format is:
1042e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger *	# comment line(s)
105c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger *	data0 data1 ...
1062e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger */
107c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemmingerstatic int get_distribution(const char *type, __s16 *data, int maxdata)
108b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger{
109b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	FILE *f;
110b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	int n;
1112e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	long x;
1122e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	size_t len;
113fb9b1d0f6a9f355bceae435ea43f1c8f3635b2dfosdl.net!shemminger	char *line = NULL;
1142e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	char name[128];
115b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
116aa27f88c8444ad6a87ebb563d6ffacb4fe95d87cStephen Hemminger	snprintf(name, sizeof(name), "%s/%s.dist", get_tc_lib(), type);
1172e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if ((f = fopen(name, "r")) == NULL) {
118ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger		fprintf(stderr, "No distribution data for %s (%s: %s)\n",
1192e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			type, name, strerror(errno));
120b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		return -1;
121b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
122ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
123b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	n = 0;
1242e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	while (getline(&line, &len, f) != -1) {
1252e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		char *p, *endp;
1262e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		if (*line == '\n' || *line == '#')
127b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			continue;
128b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
1292e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		for (p = line; ; p = endp) {
1302e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			x = strtol(p, &endp, 0);
131ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger			if (endp == p)
1322e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				break;
1332e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger
134c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			if (n >= maxdata) {
1352e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				fprintf(stderr, "%s: too much data\n",
1362e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger					name);
1372e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				n = -1;
1382e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				goto error;
1392e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			}
140b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			data[n++] = x;
141b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		}
142b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
1432e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger error:
1442e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	free(line);
145b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	fclose(f);
146b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	return n;
147b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger}
148b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
1493c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger#define NEXT_IS_NUMBER() (NEXT_ARG_OK() && isdigit(argv[1][0]))
150e72ca3fbb0aeaa382e6a5a14dada38a56ffab160Johannes Naab#define NEXT_IS_SIGNED_NUMBER() \
151e72ca3fbb0aeaa382e6a5a14dada38a56ffab160Johannes Naab	(NEXT_ARG_OK() && (isdigit(argv[1][0]) || argv[1][0] == '-'))
152b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
153ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger/* Adjust for the fact that psched_ticks aren't always usecs
154b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger   (based on kernel PSCHED_CLOCK configuration */
155b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemmingerstatic int get_ticks(__u32 *ticks, const char *str)
156b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger{
157b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	unsigned t;
158b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
1598f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	if(get_time(&t, str))
160b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		return -1;
161ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
1628f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	if (tc_core_time2big(t)) {
1638f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy		fprintf(stderr, "Illegal %u time (too large)\n", t);
164fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger		return -1;
165fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger	}
166fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger
1678f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	*ticks = tc_core_time2tick(t);
168b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	return 0;
169b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger}
170b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
171ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemmingerstatic int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
172309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			   struct nlmsghdr *n)
173309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{
174fcbd0165fcf6d0efdfb02220ac77342ce0c0e224Thomas Jarosch	int dist_size = 0;
1752e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	struct rtattr *tail;
1763c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	struct tc_netem_qopt opt = { .limit = 1000 };
1772e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	struct tc_netem_corr cor;
178ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	struct tc_netem_reorder reorder;
179a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	struct tc_netem_corrupt corrupt;
1803c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	struct tc_netem_gimodel gimodel;
1813c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	struct tc_netem_gemodel gemodel;
1826b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	struct tc_netem_rate rate;
183a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	__s16 *dist_data = NULL;
1843c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	__u16 loss_type = NETEM_LOSS_UNSPEC;
18540076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger	int present[__TCA_NETEM_MAX];
186dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang	__u64 rate64 = 0;
187309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
1882e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	memset(&cor, 0, sizeof(cor));
189ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	memset(&reorder, 0, sizeof(reorder));
190a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	memset(&corrupt, 0, sizeof(corrupt));
1916b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	memset(&rate, 0, sizeof(rate));
19240076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger	memset(present, 0, sizeof(present));
193309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
1943c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	for( ; argc > 0; --argc, ++argv) {
195309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		if (matches(*argv, "limit") == 0) {
196309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			NEXT_ARG();
1972e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (get_size(&opt.limit, *argv)) {
198309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				explain1("limit");
199309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
200309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			}
201b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		} else if (matches(*argv, "latency") == 0 ||
202b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			   matches(*argv, "delay") == 0) {
203309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			NEXT_ARG();
2042e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (get_ticks(&opt.latency, *argv)) {
205309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				explain1("latency");
206309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
207309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			}
208b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
209b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			if (NEXT_IS_NUMBER()) {
210b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				NEXT_ARG();
2112e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				if (get_ticks(&opt.jitter, *argv)) {
212b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					explain1("latency");
213b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					return -1;
214b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				}
215b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
216b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				if (NEXT_IS_NUMBER()) {
217b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					NEXT_ARG();
21840076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger					++present[TCA_NETEM_CORR];
2193c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					if (get_percent(&cor.delay_corr, *argv)) {
220b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger						explain1("latency");
221b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger						return -1;
222b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					}
223b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				}
224b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			}
225b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		} else if (matches(*argv, "loss") == 0 ||
226b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			   matches(*argv, "drop") == 0) {
2273c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (opt.loss > 0 || loss_type != NETEM_LOSS_UNSPEC) {
2283c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				explain1("duplicate loss argument\n");
229309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
230309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			}
2313c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2323c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			NEXT_ARG();
2333c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			/* Old (deprecated) random loss model syntax */
2343c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (isdigit(argv[0][0]))
2353c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				goto random_loss_model;
2363c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2373c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (!strcmp(*argv, "random")) {
238b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				NEXT_ARG();
2393c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	random_loss_model:
2403c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&opt.loss, *argv)) {
2413c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss percent");
2423c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2433c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2443c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (NEXT_IS_NUMBER()) {
2453c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					NEXT_ARG();
2463c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					++present[TCA_NETEM_CORR];
2473c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					if (get_percent(&cor.loss_corr, *argv)) {
2483c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger						explain1("loss correllation");
2493c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger						return -1;
2503c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					}
2513c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2523c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			} else if (!strcmp(*argv, "state")) {
2533c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				double p13;
2543c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2553c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
2563c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (parse_percent(&p13, *argv)) {
2573c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss p13");
2583c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2593c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2603c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2613c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				/* set defaults */
2623c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gimodel.p13, p13);
2633c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gimodel.p31, 1. - p13);
2643c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gimodel.p32, 0);
2653c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gimodel.p23, 1.);
2668f9672af7af74608278ab45546cf64d7bdfcd15fJay Vosburgh				set_percent(&gimodel.p14, 0);
2673c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				loss_type = NETEM_LOSS_GI;
2683c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2693c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
2703c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
2713c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
2723c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gimodel.p31, *argv)) {
2733c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss p31");
2743c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2753c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2763c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2773c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
2783c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
2793c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
2803c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gimodel.p32, *argv)) {
2813c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss p32");
2823c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2833c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2843c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2853c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
2863c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
2873c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
2883c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gimodel.p23, *argv)) {
2893c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss p23");
2903c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2913c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2928f9672af7af74608278ab45546cf64d7bdfcd15fJay Vosburgh				if (!NEXT_IS_NUMBER())
2938f9672af7af74608278ab45546cf64d7bdfcd15fJay Vosburgh					continue;
2948f9672af7af74608278ab45546cf64d7bdfcd15fJay Vosburgh				NEXT_ARG();
2958f9672af7af74608278ab45546cf64d7bdfcd15fJay Vosburgh				if (get_percent(&gimodel.p14, *argv)) {
2968f9672af7af74608278ab45546cf64d7bdfcd15fJay Vosburgh					explain1("loss p14");
2978f9672af7af74608278ab45546cf64d7bdfcd15fJay Vosburgh					return -1;
2988f9672af7af74608278ab45546cf64d7bdfcd15fJay Vosburgh				}
2993c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
3003c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			} else if (!strcmp(*argv, "gemodel")) {
3013c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
3023c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gemodel.p, *argv)) {
3033c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss gemodel p");
3043c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
3053c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
3063c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
3073c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				/* set defaults */
3083c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gemodel.r, 1.);
3093c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gemodel.h, 0);
3103757185b29bba37943107ce49c21553054023f44Jay Vosburgh				set_percent(&gemodel.k1, 0);
3113c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				loss_type = NETEM_LOSS_GE;
3123c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
3133c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
3143c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
3153c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
3163c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gemodel.r, *argv)) {
3173c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss gemodel r");
3183c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
3193c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
3203c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
3213c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
3223c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
3233c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
3243c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gemodel.h, *argv)) {
3253c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss gemodel h");
3263c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
3273c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
3283757185b29bba37943107ce49c21553054023f44Jay Vosburgh				/* netem option is "1-h" but kernel
3293757185b29bba37943107ce49c21553054023f44Jay Vosburgh				 * expects "h".
3303757185b29bba37943107ce49c21553054023f44Jay Vosburgh				 */
3313757185b29bba37943107ce49c21553054023f44Jay Vosburgh				gemodel.h = max_percent_value - gemodel.h;
3323c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
3333c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
3343c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
3353c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
3363c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gemodel.k1, *argv)) {
3373c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss gemodel k");
338b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					return -1;
339b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				}
3403c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			} else {
3413c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				fprintf(stderr, "Unknown loss parameter: %s\n",
3423c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					*argv);
3433c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				return -1;
344b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			}
3451070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian		} else if (matches(*argv, "ecn") == 0) {
3461070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian				present[TCA_NETEM_ECN] = 1;
347ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		} else if (matches(*argv, "reorder") == 0) {
348ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			NEXT_ARG();
34940076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger			present[TCA_NETEM_REORDER] = 1;
350ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			if (get_percent(&reorder.probability, *argv)) {
351ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				explain1("reorder");
352ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				return -1;
353ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			}
354ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			if (NEXT_IS_NUMBER()) {
355ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				NEXT_ARG();
35640076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger				++present[TCA_NETEM_CORR];
357ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				if (get_percent(&reorder.correlation, *argv)) {
358ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger					explain1("reorder");
359ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger					return -1;
360ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				}
361ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			}
362a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger		} else if (matches(*argv, "corrupt") == 0) {
363a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			NEXT_ARG();
36440076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger			present[TCA_NETEM_CORRUPT] = 1;
365a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			if (get_percent(&corrupt.probability, *argv)) {
366a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				explain1("corrupt");
367a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				return -1;
368a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			}
369a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			if (NEXT_IS_NUMBER()) {
370a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				NEXT_ARG();
37140076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger				++present[TCA_NETEM_CORR];
372a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				if (get_percent(&corrupt.correlation, *argv)) {
373a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger					explain1("corrupt");
374a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger					return -1;
375a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				}
376a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			}
377309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		} else if (matches(*argv, "gap") == 0) {
378309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			NEXT_ARG();
3792e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (get_u32(&opt.gap, *argv, 0)) {
380309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				explain1("gap");
381309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
382309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			}
383ffb79d06915fe3b1ee5d2e4e37c1db67c3c06cdfosdl.net!shemminger		} else if (matches(*argv, "duplicate") == 0) {
384309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			NEXT_ARG();
3852e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (get_percent(&opt.duplicate, *argv)) {
386ffb79d06915fe3b1ee5d2e4e37c1db67c3c06cdfosdl.net!shemminger				explain1("duplicate");
387309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
388309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			}
389b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			if (NEXT_IS_NUMBER()) {
390b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				NEXT_ARG();
3912e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				if (get_percent(&cor.dup_corr, *argv)) {
392b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					explain1("duplicate");
393b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					return -1;
394b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				}
395b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			}
396b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		} else if (matches(*argv, "distribution") == 0) {
397309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			NEXT_ARG();
398c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			dist_data = calloc(sizeof(dist_data[0]), MAX_DIST);
399c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			dist_size = get_distribution(*argv, dist_data, MAX_DIST);
400c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			if (dist_size <= 0) {
401c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger				free(dist_data);
402309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
403c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			}
4046b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		} else if (matches(*argv, "rate") == 0) {
4056b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			++present[TCA_NETEM_RATE];
4066b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			NEXT_ARG();
407dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang			if (get_rate64(&rate64, *argv)) {
4086b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				explain1("rate");
4096b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				return -1;
4106b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			}
411e72ca3fbb0aeaa382e6a5a14dada38a56ffab160Johannes Naab			if (NEXT_IS_SIGNED_NUMBER()) {
4126b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				NEXT_ARG();
4136b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				if (get_s32(&rate.packet_overhead, *argv, 0)) {
4146b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					explain1("rate");
4156b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					return -1;
4166b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				}
4176b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			}
4186b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			if (NEXT_IS_NUMBER()) {
4196b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				NEXT_ARG();
4206b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				if (get_u32(&rate.cell_size, *argv, 0)) {
4216b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					explain1("rate");
4226b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					return -1;
4236b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				}
4246b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			}
425e72ca3fbb0aeaa382e6a5a14dada38a56ffab160Johannes Naab			if (NEXT_IS_SIGNED_NUMBER()) {
4266b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				NEXT_ARG();
4276b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				if (get_s32(&rate.cell_overhead, *argv, 0)) {
4286b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					explain1("rate");
4296b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					return -1;
4306b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				}
4316b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			}
432309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		} else if (strcmp(*argv, "help") == 0) {
433309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			explain();
434309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			return -1;
435309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		} else {
436309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			fprintf(stderr, "What is \"%s\"?\n", *argv);
437309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			explain();
438309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			return -1;
439309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		}
440309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger	}
441309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
4421a1d22a72284acf43f7aff5210db018076e66194n);	tail = NLMSG_TAIL(n);
443025dc69a25f016c3035212517bae481dafbb2651osdl.net!shemminger
444ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	if (reorder.probability) {
445ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		if (opt.latency == 0) {
446ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			fprintf(stderr, "reordering not possible without specifying some delay\n");
44714a1c164d12e32415acc44ef566fcf52ff4dd113Vijay Subramanian			explain();
44814a1c164d12e32415acc44ef566fcf52ff4dd113Vijay Subramanian			return -1;
449ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		}
450ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		if (opt.gap == 0)
451ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			opt.gap = 1;
452ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	} else if (opt.gap > 0) {
453ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		fprintf(stderr, "gap specified without reorder probability\n");
454ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		explain();
455ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		return -1;
456ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	}
457ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger
4581070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian	if (present[TCA_NETEM_ECN]) {
4591070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian		if (opt.loss <= 0 && loss_type == NETEM_LOSS_UNSPEC) {
4601070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian			fprintf(stderr, "ecn requested without loss model\n");
4611070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian			explain();
4621070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian			return -1;
4631070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian		}
4641070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian	}
4651070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian
466a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	if (dist_data && (opt.latency == 0 || opt.jitter == 0)) {
467ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		fprintf(stderr, "distribution specified but no latency and jitter values\n");
468ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		explain();
469ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		return -1;
470ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	}
471ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger
472c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger	if (addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)) < 0)
473a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger		return -1;
4742e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger
47540076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger	if (present[TCA_NETEM_CORR] &&
476c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger	    addattr_l(n, 1024, TCA_NETEM_CORR, &cor, sizeof(cor)) < 0)
477a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			return -1;
478a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger
4793c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (present[TCA_NETEM_REORDER] &&
480c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger	    addattr_l(n, 1024, TCA_NETEM_REORDER, &reorder, sizeof(reorder)) < 0)
481e9bc3c40d0c96fff2236b404dc93de511ac1a301shemminger		return -1;
482a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger
4831070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian	if (present[TCA_NETEM_ECN] &&
4841070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian	    addattr_l(n, 1024, TCA_NETEM_ECN, &present[TCA_NETEM_ECN],
4851070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian		      sizeof(present[TCA_NETEM_ECN])) < 0)
4861070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian			return -1;
4871070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian
48840076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger	if (present[TCA_NETEM_CORRUPT] &&
489c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger	    addattr_l(n, 1024, TCA_NETEM_CORRUPT, &corrupt, sizeof(corrupt)) < 0)
49040076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger		return -1;
491a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger
4923c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (loss_type != NETEM_LOSS_UNSPEC) {
4933c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		struct rtattr *start;
4943c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
4953c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		start = addattr_nest(n, 1024, TCA_NETEM_LOSS | NLA_F_NESTED);
4963c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		if (loss_type == NETEM_LOSS_GI) {
4973c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (addattr_l(n, 1024, NETEM_LOSS_GI,
4983c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				      &gimodel, sizeof(gimodel)) < 0)
4993c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			    return -1;
5003c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		} else if (loss_type == NETEM_LOSS_GE) {
5013c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (addattr_l(n, 1024, NETEM_LOSS_GE,
5023c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				      &gemodel, sizeof(gemodel)) < 0)
5033c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			    return -1;
5043c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		} else {
5053c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			fprintf(stderr, "loss in the weeds!\n");
5063c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			return -1;
5073c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		}
5083d0b7439dfac96d93386295a4c961b89bd3d8463Stephen Hemminger
5093c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		addattr_nest_end(n, start);
5103c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	}
5113c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
512dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang	if (present[TCA_NETEM_RATE]) {
513dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang		if (rate64 >= (1ULL << 32)) {
514dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang			if (addattr_l(n, 1024,
515dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang				      TCA_NETEM_RATE64, &rate64, sizeof(rate64)) < 0)
516dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang				return -1;
517dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang			rate.rate = ~0U;
518dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang		} else {
519dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang			rate.rate = rate64;
520dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang		}
521dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang		if (addattr_l(n, 1024, TCA_NETEM_RATE, &rate, sizeof(rate)) < 0)
522dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang			return -1;
523dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang	}
5246b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer
525a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	if (dist_data) {
526c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger		if (addattr_l(n, MAX_DIST * sizeof(dist_data[0]),
527c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			      TCA_NETEM_DELAY_DIST,
528c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			      dist_data, dist_size * sizeof(dist_data[0])) < 0)
529a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			return -1;
530c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger		free(dist_data);
5312e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	}
5321a1d22a72284acf43f7aff5210db018076e66194void *) NLMSG_TAIL(n) - (void *) tail;	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
533b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	return 0;
534309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger}
535309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
536309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemmingerstatic int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
537309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{
5382e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	const struct tc_netem_corr *cor = NULL;
539ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	const struct tc_netem_reorder *reorder = NULL;
540a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	const struct tc_netem_corrupt *corrupt = NULL;
5413c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	const struct tc_netem_gimodel *gimodel = NULL;
5423c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	const struct tc_netem_gemodel *gemodel = NULL;
5431070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian	int *ecn = NULL;
5442e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	struct tc_netem_qopt qopt;
5456b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	const struct tc_netem_rate *rate = NULL;
5462e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	int len = RTA_PAYLOAD(opt) - sizeof(qopt);
547dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang	__u64 rate64 = 0;
548309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger	SPRINT_BUF(b1);
549309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
550309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger	if (opt == NULL)
551309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		return 0;
552309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
5532e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (len < 0) {
5542e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		fprintf(stderr, "options size error\n");
555309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		return -1;
556b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
5572e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	memcpy(&qopt, RTA_DATA(opt), sizeof(qopt));
5582e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger
5592e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (len > 0) {
5601d2d1cb52255b01a764aa59cd17876cf87685f34net[shemminger]!shemminger		struct rtattr *tb[TCA_NETEM_MAX+1];
5612e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		parse_rtattr(tb, TCA_NETEM_MAX, RTA_DATA(opt) + sizeof(qopt),
5622e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			     len);
563ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
5642e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		if (tb[TCA_NETEM_CORR]) {
5652e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (RTA_PAYLOAD(tb[TCA_NETEM_CORR]) < sizeof(*cor))
5662e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				return -1;
5672e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			cor = RTA_DATA(tb[TCA_NETEM_CORR]);
5682e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		}
569ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		if (tb[TCA_NETEM_REORDER]) {
570ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			if (RTA_PAYLOAD(tb[TCA_NETEM_REORDER]) < sizeof(*reorder))
571ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				return -1;
572ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			reorder = RTA_DATA(tb[TCA_NETEM_REORDER]);
573ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		}
574a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger		if (tb[TCA_NETEM_CORRUPT]) {
575a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			if (RTA_PAYLOAD(tb[TCA_NETEM_CORRUPT]) < sizeof(*corrupt))
576a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				return -1;
577e9bc3c40d0c96fff2236b404dc93de511ac1a301shemminger			corrupt = RTA_DATA(tb[TCA_NETEM_CORRUPT]);
578a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger		}
5793c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		if (tb[TCA_NETEM_LOSS]) {
5803c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			struct rtattr *lb[NETEM_LOSS_MAX + 1];
5813c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
5823c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			parse_rtattr_nested(lb, NETEM_LOSS_MAX, tb[TCA_NETEM_LOSS]);
5833c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (lb[NETEM_LOSS_GI])
5848f9672af7af74608278ab45546cf64d7bdfcd15fJay Vosburgh				gimodel = RTA_DATA(lb[NETEM_LOSS_GI]);
5853c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (lb[NETEM_LOSS_GE])
5863c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				gemodel = RTA_DATA(lb[NETEM_LOSS_GE]);
5873d0b7439dfac96d93386295a4c961b89bd3d8463Stephen Hemminger		}
5886b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		if (tb[TCA_NETEM_RATE]) {
5896b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			if (RTA_PAYLOAD(tb[TCA_NETEM_RATE]) < sizeof(*rate))
5906b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				return -1;
5916b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			rate = RTA_DATA(tb[TCA_NETEM_RATE]);
5926b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		}
5931070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian		if (tb[TCA_NETEM_ECN]) {
5941070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian			if (RTA_PAYLOAD(tb[TCA_NETEM_ECN]) < sizeof(*ecn))
5951070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian				return -1;
5961070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian			ecn = RTA_DATA(tb[TCA_NETEM_ECN]);
5971070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian		}
598dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang		if (tb[TCA_NETEM_RATE64]) {
599dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang			if (RTA_PAYLOAD(tb[TCA_NETEM_RATE64]) < sizeof(rate64))
600dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang				return -1;
601dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang			rate64 = rta_getattr_u64(tb[TCA_NETEM_RATE64]);
602dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang		}
6032e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	}
604309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
6052e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	fprintf(f, "limit %d", qopt.limit);
60631fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger
6072e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (qopt.latency) {
6082e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		fprintf(f, " delay %s", sprint_ticks(qopt.latency, b1));
609b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
6102e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		if (qopt.jitter) {
6112e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			fprintf(f, "  %s", sprint_ticks(qopt.jitter, b1));
6122e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (cor && cor->delay_corr)
6132e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				fprintf(f, " %s", sprint_percent(cor->delay_corr, b1));
614b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		}
615b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
616b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
6172e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (qopt.loss) {
6182e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		fprintf(f, " loss %s", sprint_percent(qopt.loss, b1));
6192e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		if (cor && cor->loss_corr)
6202e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			fprintf(f, " %s", sprint_percent(cor->loss_corr, b1));
621b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
622b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
6233c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (gimodel) {
6243c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " loss state p13 %s", sprint_percent(gimodel->p13, b1));
6253c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " p31 %s", sprint_percent(gimodel->p31, b1));
6263c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " p32 %s", sprint_percent(gimodel->p32, b1));
6273c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " p23 %s", sprint_percent(gimodel->p23, b1));
6283c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " p14 %s", sprint_percent(gimodel->p14, b1));
6293c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	}
6303c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
6313c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (gemodel) {
6323757185b29bba37943107ce49c21553054023f44Jay Vosburgh		fprintf(f, " loss gemodel p %s",
6333c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			sprint_percent(gemodel->p, b1));
6343c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " r %s", sprint_percent(gemodel->r, b1));
6353757185b29bba37943107ce49c21553054023f44Jay Vosburgh		fprintf(f, " 1-h %s", sprint_percent(max_percent_value -
6363757185b29bba37943107ce49c21553054023f44Jay Vosburgh						     gemodel->h, b1));
6373c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " 1-k %s", sprint_percent(gemodel->k1, b1));
6383c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	}
6393c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
6402e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (qopt.duplicate) {
641b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		fprintf(f, " duplicate %s",
6422e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			sprint_percent(qopt.duplicate, b1));
6432e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		if (cor && cor->dup_corr)
6442e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			fprintf(f, " %s", sprint_percent(cor->dup_corr, b1));
645b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
646ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
647ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	if (reorder && reorder->probability) {
648ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger		fprintf(f, " reorder %s",
649ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			sprint_percent(reorder->probability, b1));
650ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		if (reorder->correlation)
651ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger			fprintf(f, " %s",
652ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				sprint_percent(reorder->correlation, b1));
653ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	}
654b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
655a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	if (corrupt && corrupt->probability) {
656ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger		fprintf(f, " corrupt %s",
657a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			sprint_percent(corrupt->probability, b1));
658a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger		if (corrupt->correlation)
659ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger			fprintf(f, " %s",
660a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				sprint_percent(corrupt->correlation, b1));
661a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	}
662a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger
6636b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	if (rate && rate->rate) {
664dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang		if (rate64)
665dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang			fprintf(f, " rate %s", sprint_rate(rate64, b1));
666dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang		else
667dad2f72befc064d3ee8dea95b75b85c350cd2758Yang Yingliang			fprintf(f, " rate %s", sprint_rate(rate->rate, b1));
6686b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		if (rate->packet_overhead)
6696b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			fprintf(f, " packetoverhead %d", rate->packet_overhead);
6706b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		if (rate->cell_size)
6716b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			fprintf(f, " cellsize %u", rate->cell_size);
6726b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		if (rate->cell_overhead)
6736b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			fprintf(f, " celloverhead %d", rate->cell_overhead);
6746b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	}
6756b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer
6761070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian	if (ecn)
6771070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian		fprintf(f, " ecn ");
6781070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian
6792e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (qopt.gap)
6802e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		fprintf(f, " gap %lu", (unsigned long)qopt.gap);
681309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
6821070205dc042825dddcc30b478173f85c6b6a509Vijay Subramanian
683309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger	return 0;
684309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger}
685309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
68695812b56a5a66e7e9a21744cfe8bc0bb9791ea98net[shemminger]!kaberstruct qdisc_util netem_qdisc_util = {
68731fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger	.id	   	= "netem",
68831fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger	.parse_qopt	= netem_parse_opt,
68931fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger	.print_qopt	= netem_print_opt,
690309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger};
691