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