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" \
416b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer"                 [ reorder PRECENT [CORRELATION] [ gap DISTANCE ]]\n" \
426b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer"                 [ rate RATE [PACKETOVERHEAD] [CELLSIZE] [CELLOVERHEAD]]\n");
43309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger}
44309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
45309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemmingerstatic void explain1(const char *arg)
46309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{
47309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger	fprintf(stderr, "Illegal \"%s\"\n", arg);
48309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger}
49309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
503c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger/* Upper bound on size of distribution
51c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger *  really (TCA_BUF_MAX - other headers) / sizeof (__s16)
52c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger */
53c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger#define MAX_DIST	(16*1024)
54c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger
553c7950af598beab378a291ee0540da438978a4b2Stephen Hemmingerstatic const double max_percent_value = 0xffffffff;
563c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
573c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger/* scaled value used to percent of maximum. */
583c7950af598beab378a291ee0540da438978a4b2Stephen Hemmingerstatic void set_percent(__u32 *percent, double per)
593c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger{
603c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	*percent = (unsigned) rint(per * max_percent_value);
613c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger}
623c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
633c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
643c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger/* Parse either a fraction '.3' or percent '30%
653c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger * return: 0 = ok, -1 = error, 1 = out of range
663c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger */
673c7950af598beab378a291ee0540da438978a4b2Stephen Hemmingerstatic int parse_percent(double *val, const char *str)
683c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger{
693c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	char *p;
703c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
713c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	*val = strtod(str, &p) / 100.;
723c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (*p && strcmp(p, "%") )
733c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		return -1;
743c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
753c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	return 0;
763c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger}
773c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
783c7950af598beab378a291ee0540da438978a4b2Stephen Hemmingerstatic int get_percent(__u32 *percent, const char *str)
793c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger{
803c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	double per;
813c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
823c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (parse_percent(&per, str))
833c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		return -1;
843c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
853c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	set_percent(percent, per);
863c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	return 0;
873c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger}
883c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
893c7950af598beab378a291ee0540da438978a4b2Stephen Hemmingervoid print_percent(char *buf, int len, __u32 per)
903c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger{
913c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	snprintf(buf, len, "%g%%", 100. * (double) per / max_percent_value);
923c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger}
933c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
943c7950af598beab378a291ee0540da438978a4b2Stephen Hemmingerchar * sprint_percent(__u32 per, char *buf)
953c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger{
963c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	print_percent(buf, SPRINT_BSIZE-1, per);
973c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	return buf;
983c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger}
993c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
1002e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger/*
1012e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger * Simplistic file parser for distrbution data.
1022e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger * Format is:
1032e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger *	# comment line(s)
104c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger *	data0 data1 ...
1052e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger */
106c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemmingerstatic int get_distribution(const char *type, __s16 *data, int maxdata)
107b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger{
108b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	FILE *f;
109b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	int n;
1102e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	long x;
1112e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	size_t len;
112fb9b1d0f6a9f355bceae435ea43f1c8f3635b2dfosdl.net!shemminger	char *line = NULL;
1132e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	char name[128];
114b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
115aa27f88c8444ad6a87ebb563d6ffacb4fe95d87cStephen Hemminger	snprintf(name, sizeof(name), "%s/%s.dist", get_tc_lib(), type);
1162e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if ((f = fopen(name, "r")) == NULL) {
117ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger		fprintf(stderr, "No distribution data for %s (%s: %s)\n",
1182e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			type, name, strerror(errno));
119b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		return -1;
120b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
121ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
122b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	n = 0;
1232e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	while (getline(&line, &len, f) != -1) {
1242e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		char *p, *endp;
1252e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		if (*line == '\n' || *line == '#')
126b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			continue;
127b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
1282e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		for (p = line; ; p = endp) {
1292e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			x = strtol(p, &endp, 0);
130ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger			if (endp == p)
1312e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				break;
1322e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger
133c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			if (n >= maxdata) {
1342e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				fprintf(stderr, "%s: too much data\n",
1352e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger					name);
1362e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				n = -1;
1372e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				goto error;
1382e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			}
139b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			data[n++] = x;
140b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		}
141b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
1422e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger error:
1432e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	free(line);
144b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	fclose(f);
145b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	return n;
146b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger}
147b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
1483c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger#define NEXT_IS_NUMBER() (NEXT_ARG_OK() && isdigit(argv[1][0]))
149b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
150ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger/* Adjust for the fact that psched_ticks aren't always usecs
151b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger   (based on kernel PSCHED_CLOCK configuration */
152b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemmingerstatic int get_ticks(__u32 *ticks, const char *str)
153b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger{
154b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	unsigned t;
155b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
1568f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	if(get_time(&t, str))
157b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		return -1;
158ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
1598f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	if (tc_core_time2big(t)) {
1608f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy		fprintf(stderr, "Illegal %u time (too large)\n", t);
161fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger		return -1;
162fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger	}
163fa56513034c839e444ab7ca986ddb178dece86c7Stephen Hemminger
1648f34caafbdbc8f87d228d577872591e138caadb1Patrick McHardy	*ticks = tc_core_time2tick(t);
165b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	return 0;
166b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger}
167b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
168ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemmingerstatic int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
169309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			   struct nlmsghdr *n)
170309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{
171fcbd0165fcf6d0efdfb02220ac77342ce0c0e224Thomas Jarosch	int dist_size = 0;
1722e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	struct rtattr *tail;
1733c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	struct tc_netem_qopt opt = { .limit = 1000 };
1742e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	struct tc_netem_corr cor;
175ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	struct tc_netem_reorder reorder;
176a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	struct tc_netem_corrupt corrupt;
1773c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	struct tc_netem_gimodel gimodel;
1783c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	struct tc_netem_gemodel gemodel;
1796b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	struct tc_netem_rate rate;
180a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	__s16 *dist_data = NULL;
1813c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	__u16 loss_type = NETEM_LOSS_UNSPEC;
18240076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger	int present[__TCA_NETEM_MAX];
183309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
1842e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	memset(&cor, 0, sizeof(cor));
185ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	memset(&reorder, 0, sizeof(reorder));
186a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	memset(&corrupt, 0, sizeof(corrupt));
1876b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	memset(&rate, 0, sizeof(rate));
18840076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger	memset(present, 0, sizeof(present));
189309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
1903c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	for( ; argc > 0; --argc, ++argv) {
191309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		if (matches(*argv, "limit") == 0) {
192309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			NEXT_ARG();
1932e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (get_size(&opt.limit, *argv)) {
194309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				explain1("limit");
195309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
196309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			}
197b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		} else if (matches(*argv, "latency") == 0 ||
198b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			   matches(*argv, "delay") == 0) {
199309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			NEXT_ARG();
2002e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (get_ticks(&opt.latency, *argv)) {
201309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				explain1("latency");
202309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
203309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			}
204b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
205b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			if (NEXT_IS_NUMBER()) {
206b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				NEXT_ARG();
2072e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				if (get_ticks(&opt.jitter, *argv)) {
208b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					explain1("latency");
209b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					return -1;
210b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				}
211b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
212b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				if (NEXT_IS_NUMBER()) {
213b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					NEXT_ARG();
21440076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger					++present[TCA_NETEM_CORR];
2153c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					if (get_percent(&cor.delay_corr, *argv)) {
216b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger						explain1("latency");
217b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger						return -1;
218b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					}
219b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				}
220b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			}
221b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		} else if (matches(*argv, "loss") == 0 ||
222b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			   matches(*argv, "drop") == 0) {
2233c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (opt.loss > 0 || loss_type != NETEM_LOSS_UNSPEC) {
2243c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				explain1("duplicate loss argument\n");
225309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
226309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			}
2273c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2283c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			NEXT_ARG();
2293c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			/* Old (deprecated) random loss model syntax */
2303c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (isdigit(argv[0][0]))
2313c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				goto random_loss_model;
2323c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2333c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (!strcmp(*argv, "random")) {
234b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				NEXT_ARG();
2353c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	random_loss_model:
2363c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&opt.loss, *argv)) {
2373c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss percent");
2383c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2393c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2403c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (NEXT_IS_NUMBER()) {
2413c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					NEXT_ARG();
2423c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					++present[TCA_NETEM_CORR];
2433c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					if (get_percent(&cor.loss_corr, *argv)) {
2443c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger						explain1("loss correllation");
2453c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger						return -1;
2463c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					}
2473c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2483c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			} else if (!strcmp(*argv, "state")) {
2493c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				double p13;
2503c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2513c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
2523c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (parse_percent(&p13, *argv)) {
2533c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss p13");
2543c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2553c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2563c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2573c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				/* set defaults */
2583c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gimodel.p13, p13);
2593c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gimodel.p31, 1. - p13);
2603c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gimodel.p32, 0);
2613c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gimodel.p23, 1.);
2623c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				loss_type = NETEM_LOSS_GI;
2633c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2643c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
2653c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
2663c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
2673c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gimodel.p31, *argv)) {
2683c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss p31");
2693c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2703c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2713c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2723c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
2733c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
2743c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
2753c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gimodel.p32, *argv)) {
2763c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss p32");
2773c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2783c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2793c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2803c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
2813c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
2823c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
2833c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gimodel.p23, *argv)) {
2843c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss p23");
2853c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2863c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2873c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2883c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			} else if (!strcmp(*argv, "gemodel")) {
2893c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
2903c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gemodel.p, *argv)) {
2913c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss gemodel p");
2923c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
2933c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
2943c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
2953c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				/* set defaults */
2963c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gemodel.r, 1.);
2973c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gemodel.h, 0);
2983c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				set_percent(&gemodel.k1, 1.);
2993c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				loss_type = NETEM_LOSS_GE;
3003c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
3013c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
3023c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
3033c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
3043c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gemodel.r, *argv)) {
3053c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss gemodel r");
3063c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
3073c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
3083c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
3093c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
3103c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
3113c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
3123c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gemodel.h, *argv)) {
3133c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss gemodel h");
3143c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					return -1;
3153c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				}
3163c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
3173c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (!NEXT_IS_NUMBER())
3183c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					continue;
3193c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				NEXT_ARG();
3203c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				if (get_percent(&gemodel.k1, *argv)) {
3213c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					explain1("loss gemodel k");
322b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					return -1;
323b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				}
3243c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			} else {
3253c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				fprintf(stderr, "Unknown loss parameter: %s\n",
3263c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger					*argv);
3273c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				return -1;
328b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			}
329ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		} else if (matches(*argv, "reorder") == 0) {
330ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			NEXT_ARG();
33140076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger			present[TCA_NETEM_REORDER] = 1;
332ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			if (get_percent(&reorder.probability, *argv)) {
333ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				explain1("reorder");
334ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				return -1;
335ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			}
336ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			if (NEXT_IS_NUMBER()) {
337ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				NEXT_ARG();
33840076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger				++present[TCA_NETEM_CORR];
339ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				if (get_percent(&reorder.correlation, *argv)) {
340ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger					explain1("reorder");
341ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger					return -1;
342ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				}
343ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			}
344a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger		} else if (matches(*argv, "corrupt") == 0) {
345a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			NEXT_ARG();
34640076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger			present[TCA_NETEM_CORRUPT] = 1;
347a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			if (get_percent(&corrupt.probability, *argv)) {
348a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				explain1("corrupt");
349a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				return -1;
350a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			}
351a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			if (NEXT_IS_NUMBER()) {
352a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				NEXT_ARG();
35340076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger				++present[TCA_NETEM_CORR];
354a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				if (get_percent(&corrupt.correlation, *argv)) {
355a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger					explain1("corrupt");
356a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger					return -1;
357a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				}
358a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			}
359309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		} else if (matches(*argv, "gap") == 0) {
360309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			NEXT_ARG();
3612e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (get_u32(&opt.gap, *argv, 0)) {
362309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				explain1("gap");
363309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
364309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			}
365ffb79d06915fe3b1ee5d2e4e37c1db67c3c06cdfosdl.net!shemminger		} else if (matches(*argv, "duplicate") == 0) {
366309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			NEXT_ARG();
3672e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (get_percent(&opt.duplicate, *argv)) {
368ffb79d06915fe3b1ee5d2e4e37c1db67c3c06cdfosdl.net!shemminger				explain1("duplicate");
369309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
370309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			}
371b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			if (NEXT_IS_NUMBER()) {
372b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				NEXT_ARG();
3732e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				if (get_percent(&cor.dup_corr, *argv)) {
374b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					explain1("duplicate");
375b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger					return -1;
376b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger				}
377b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger			}
378b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		} else if (matches(*argv, "distribution") == 0) {
379309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			NEXT_ARG();
380c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			dist_data = calloc(sizeof(dist_data[0]), MAX_DIST);
381c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			dist_size = get_distribution(*argv, dist_data, MAX_DIST);
382c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			if (dist_size <= 0) {
383c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger				free(dist_data);
384309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger				return -1;
385c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			}
3866b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		} else if (matches(*argv, "rate") == 0) {
3876b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			++present[TCA_NETEM_RATE];
3886b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			NEXT_ARG();
3896b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			if (get_rate(&rate.rate, *argv)) {
3906b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				explain1("rate");
3916b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				return -1;
3926b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			}
3936b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			if (NEXT_IS_NUMBER()) {
3946b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				NEXT_ARG();
3956b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				if (get_s32(&rate.packet_overhead, *argv, 0)) {
3966b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					explain1("rate");
3976b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					return -1;
3986b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				}
3996b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			}
4006b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			if (NEXT_IS_NUMBER()) {
4016b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				NEXT_ARG();
4026b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				if (get_u32(&rate.cell_size, *argv, 0)) {
4036b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					explain1("rate");
4046b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					return -1;
4056b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				}
4066b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			}
4076b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			if (NEXT_IS_NUMBER()) {
4086b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				NEXT_ARG();
4096b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				if (get_s32(&rate.cell_overhead, *argv, 0)) {
4106b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					explain1("rate");
4116b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer					return -1;
4126b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				}
4136b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			}
414309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		} else if (strcmp(*argv, "help") == 0) {
415309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			explain();
416309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			return -1;
417309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		} else {
418309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			fprintf(stderr, "What is \"%s\"?\n", *argv);
419309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			explain();
420309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger			return -1;
421309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		}
422309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger	}
423309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
4241a1d22a72284acf43f7aff5210db018076e66194n);	tail = NLMSG_TAIL(n);
425025dc69a25f016c3035212517bae481dafbb2651osdl.net!shemminger
426ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	if (reorder.probability) {
427ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		if (opt.latency == 0) {
428ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			fprintf(stderr, "reordering not possible without specifying some delay\n");
42914a1c164d12e32415acc44ef566fcf52ff4dd113Vijay Subramanian			explain();
43014a1c164d12e32415acc44ef566fcf52ff4dd113Vijay Subramanian			return -1;
431ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		}
432ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		if (opt.gap == 0)
433ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			opt.gap = 1;
434ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	} else if (opt.gap > 0) {
435ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		fprintf(stderr, "gap specified without reorder probability\n");
436ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		explain();
437ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		return -1;
438ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	}
439ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger
440a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	if (dist_data && (opt.latency == 0 || opt.jitter == 0)) {
441ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		fprintf(stderr, "distribution specified but no latency and jitter values\n");
442ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		explain();
443ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		return -1;
444ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	}
445ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger
446c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger	if (addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)) < 0)
447a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger		return -1;
4482e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger
44940076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger	if (present[TCA_NETEM_CORR] &&
450c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger	    addattr_l(n, 1024, TCA_NETEM_CORR, &cor, sizeof(cor)) < 0)
451a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			return -1;
452a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger
4533c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (present[TCA_NETEM_REORDER] &&
454c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger	    addattr_l(n, 1024, TCA_NETEM_REORDER, &reorder, sizeof(reorder)) < 0)
455e9bc3c40d0c96fff2236b404dc93de511ac1a301shemminger		return -1;
456a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger
45740076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger	if (present[TCA_NETEM_CORRUPT] &&
458c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger	    addattr_l(n, 1024, TCA_NETEM_CORRUPT, &corrupt, sizeof(corrupt)) < 0)
45940076f622e0aacb2b792d3ac1b5d12aa97c4da9cStephen Hemminger		return -1;
460a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger
4613c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (loss_type != NETEM_LOSS_UNSPEC) {
4623c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		struct rtattr *start;
4633c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
4643c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		start = addattr_nest(n, 1024, TCA_NETEM_LOSS | NLA_F_NESTED);
4653c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		if (loss_type == NETEM_LOSS_GI) {
4663c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (addattr_l(n, 1024, NETEM_LOSS_GI,
4673c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				      &gimodel, sizeof(gimodel)) < 0)
4683c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			    return -1;
4693c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		} else if (loss_type == NETEM_LOSS_GE) {
4703c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (addattr_l(n, 1024, NETEM_LOSS_GE,
4713c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				      &gemodel, sizeof(gemodel)) < 0)
4723c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			    return -1;
4733c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		} else {
4743c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			fprintf(stderr, "loss in the weeds!\n");
4753c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			return -1;
4763c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		}
4773c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
4783c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		addattr_nest_end(n, start);
4793c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	}
4803c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
4816b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	if (present[TCA_NETEM_RATE] &&
4826b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	    addattr_l(n, 1024, TCA_NETEM_RATE, &rate, sizeof(rate)) < 0)
4836b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		return -1;
4846b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer
485a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	if (dist_data) {
486c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger		if (addattr_l(n, MAX_DIST * sizeof(dist_data[0]),
487c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			      TCA_NETEM_DELAY_DIST,
488c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger			      dist_data, dist_size * sizeof(dist_data[0])) < 0)
489a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			return -1;
490c1b81cb5fe92aa938e52071c89e1c8812f6d75e3Stephen Hemminger		free(dist_data);
4912e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	}
4921a1d22a72284acf43f7aff5210db018076e66194void *) NLMSG_TAIL(n) - (void *) tail;	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
493b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	return 0;
494309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger}
495309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
496309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemmingerstatic int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
497309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{
4982e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	const struct tc_netem_corr *cor = NULL;
499ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	const struct tc_netem_reorder *reorder = NULL;
500a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	const struct tc_netem_corrupt *corrupt = NULL;
5013c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	const struct tc_netem_gimodel *gimodel = NULL;
5023c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	const struct tc_netem_gemodel *gemodel = NULL;
5032e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	struct tc_netem_qopt qopt;
5046b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	const struct tc_netem_rate *rate = NULL;
5052e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	int len = RTA_PAYLOAD(opt) - sizeof(qopt);
506309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger	SPRINT_BUF(b1);
507309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
508309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger	if (opt == NULL)
509309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		return 0;
510309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
5112e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (len < 0) {
5122e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		fprintf(stderr, "options size error\n");
513309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger		return -1;
514b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
5152e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	memcpy(&qopt, RTA_DATA(opt), sizeof(qopt));
5162e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger
5172e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (len > 0) {
5181d2d1cb52255b01a764aa59cd17876cf87685f34net[shemminger]!shemminger		struct rtattr *tb[TCA_NETEM_MAX+1];
5192e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		parse_rtattr(tb, TCA_NETEM_MAX, RTA_DATA(opt) + sizeof(qopt),
5202e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			     len);
521ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
5222e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		if (tb[TCA_NETEM_CORR]) {
5232e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (RTA_PAYLOAD(tb[TCA_NETEM_CORR]) < sizeof(*cor))
5242e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				return -1;
5252e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			cor = RTA_DATA(tb[TCA_NETEM_CORR]);
5262e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		}
527ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		if (tb[TCA_NETEM_REORDER]) {
528ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			if (RTA_PAYLOAD(tb[TCA_NETEM_REORDER]) < sizeof(*reorder))
529ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				return -1;
530ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			reorder = RTA_DATA(tb[TCA_NETEM_REORDER]);
531ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		}
532a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger		if (tb[TCA_NETEM_CORRUPT]) {
533a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			if (RTA_PAYLOAD(tb[TCA_NETEM_CORRUPT]) < sizeof(*corrupt))
534a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				return -1;
535e9bc3c40d0c96fff2236b404dc93de511ac1a301shemminger			corrupt = RTA_DATA(tb[TCA_NETEM_CORRUPT]);
536a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger		}
5373c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		if (tb[TCA_NETEM_LOSS]) {
5383c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			struct rtattr *lb[NETEM_LOSS_MAX + 1];
5393c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
5403c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			parse_rtattr_nested(lb, NETEM_LOSS_MAX, tb[TCA_NETEM_LOSS]);
5413c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (lb[NETEM_LOSS_GI])
5423c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				gemodel = RTA_DATA(lb[NETEM_LOSS_GI]);
5433c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			if (lb[NETEM_LOSS_GE])
5443c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger				gemodel = RTA_DATA(lb[NETEM_LOSS_GE]);
5453c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		}
5466b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		if (tb[TCA_NETEM_RATE]) {
5476b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			if (RTA_PAYLOAD(tb[TCA_NETEM_RATE]) < sizeof(*rate))
5486b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer				return -1;
5496b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			rate = RTA_DATA(tb[TCA_NETEM_RATE]);
5506b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		}
5512e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	}
552309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
5532e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	fprintf(f, "limit %d", qopt.limit);
55431fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger
5552e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (qopt.latency) {
5562e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		fprintf(f, " delay %s", sprint_ticks(qopt.latency, b1));
557b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
5582e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		if (qopt.jitter) {
5592e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			fprintf(f, "  %s", sprint_ticks(qopt.jitter, b1));
5602e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			if (cor && cor->delay_corr)
5612e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger				fprintf(f, " %s", sprint_percent(cor->delay_corr, b1));
562b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		}
563b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
564b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
5652e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (qopt.loss) {
5662e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		fprintf(f, " loss %s", sprint_percent(qopt.loss, b1));
5672e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		if (cor && cor->loss_corr)
5682e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			fprintf(f, " %s", sprint_percent(cor->loss_corr, b1));
569b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
570b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
5713c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (gimodel) {
5723c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " loss state p13 %s", sprint_percent(gimodel->p13, b1));
5733c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " p31 %s", sprint_percent(gimodel->p31, b1));
5743c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " p32 %s", sprint_percent(gimodel->p32, b1));
5753c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " p23 %s", sprint_percent(gimodel->p23, b1));
5763c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " p14 %s", sprint_percent(gimodel->p14, b1));
5773c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	}
5783c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
5793c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	if (gemodel) {
5803c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, "loss gemodel p %s",
5813c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger			sprint_percent(gemodel->p, b1));
5823c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " r %s", sprint_percent(gemodel->r, b1));
5833c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " 1-h %s", sprint_percent(gemodel->h, b1));
5843c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger		fprintf(f, " 1-k %s", sprint_percent(gemodel->k1, b1));
5853c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger	}
5863c7950af598beab378a291ee0540da438978a4b2Stephen Hemminger
5872e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (qopt.duplicate) {
588b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger		fprintf(f, " duplicate %s",
5892e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			sprint_percent(qopt.duplicate, b1));
5902e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		if (cor && cor->dup_corr)
5912e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger			fprintf(f, " %s", sprint_percent(cor->dup_corr, b1));
592b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger	}
593ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
594ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	if (reorder && reorder->probability) {
595ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger		fprintf(f, " reorder %s",
596ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger			sprint_percent(reorder->probability, b1));
597ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger		if (reorder->correlation)
598ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger			fprintf(f, " %s",
599ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger				sprint_percent(reorder->correlation, b1));
600ea8fc1047d2b88ae1d123e3f79dbffbc2a3fa70cshemminger	}
601b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
602a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	if (corrupt && corrupt->probability) {
603ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger		fprintf(f, " corrupt %s",
604a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger			sprint_percent(corrupt->probability, b1));
605a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger		if (corrupt->correlation)
606ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger			fprintf(f, " %s",
607a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger				sprint_percent(corrupt->correlation, b1));
608a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger	}
609a31a5d5904dd35d6a5839e66845f236e3284bb45shemminger
6106b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	if (rate && rate->rate) {
6116b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		fprintf(f, " rate %s", sprint_rate(rate->rate, b1));
6126b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		if (rate->packet_overhead)
6136b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			fprintf(f, " packetoverhead %d", rate->packet_overhead);
6146b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		if (rate->cell_size)
6156b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			fprintf(f, " cellsize %u", rate->cell_size);
6166b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer		if (rate->cell_overhead)
6176b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer			fprintf(f, " celloverhead %d", rate->cell_overhead);
6186b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer	}
6196b8dc4deea219d6c4392707bb647cc49cdc46da7Hagen Paul Pfeifer
6202e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger	if (qopt.gap)
6212e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger		fprintf(f, " gap %lu", (unsigned long)qopt.gap);
622309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
623309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger	return 0;
624309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger}
625309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger
62695812b56a5a66e7e9a21744cfe8bc0bb9791ea98net[shemminger]!kaberstruct qdisc_util netem_qdisc_util = {
62731fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger	.id	   	= "netem",
62831fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger	.parse_qopt	= netem_parse_opt,
62931fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger	.print_qopt	= netem_print_opt,
630309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger};
631b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger
632