q_netem.c revision 1a1d22a72284acf43f7aff5210db018076e66194
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 * 9309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger * Authors: Stephen Hemminger <shemminger@osdl.org> 10309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger * 11309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger */ 12309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 13309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <stdio.h> 14309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <stdlib.h> 15309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <unistd.h> 16309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <syslog.h> 17309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <fcntl.h> 18309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <sys/socket.h> 19309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <netinet/in.h> 20309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <arpa/inet.h> 21309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include <string.h> 22b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger#include <errno.h> 23309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 24309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include "utils.h" 25309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#include "tc_util.h" 26b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger#include "tc_common.h" 27309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 28309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemmingerstatic void explain(void) 29309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{ 30ffb79d06915fe3b1ee5d2e4e37c1db67c3c06cdfosdl.net!shemminger fprintf(stderr, 31b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger"Usage: ... netem [ limit PACKETS ] \n" \ 32b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger" [ delay TIME [ JITTER [CORRELATION]]]\n" \ 33b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger" [ drop PERCENT [CORRELATION]] \n" \ 34b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger" [ duplicate PERCENT [CORRELATION]]\n" \ 35b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger" [ distribution {uniform|normal|pareto|paretonormal} ]\n" \ 36b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger" [ gap PACKETS ]\n"); 37309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger} 38309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 39309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemmingerstatic void explain1(const char *arg) 40309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{ 41309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger fprintf(stderr, "Illegal \"%s\"\n", arg); 42309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger} 43309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 44309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger#define usage() return(-1) 45309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 462e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger/* 472e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger * Simplistic file parser for distrbution data. 482e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger * Format is: 492e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger * # comment line(s) 502e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger * data0 data1 512e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger */ 522e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger#define MAXDIST 65536 532e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemmingerstatic int get_distribution(const char *type, __s16 *data) 54b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger{ 55b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger FILE *f; 56b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger int n; 572e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger long x; 582e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger size_t len; 592e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger char *line; 602e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger char name[128]; 61b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 622e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger snprintf(name, sizeof(name), "/usr/lib/tc/%s.dist", type); 632e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if ((f = fopen(name, "r")) == NULL) { 64b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger fprintf(stderr, "No distribution data for %s (%s: %s)\n", 652e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger type, name, strerror(errno)); 66b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return -1; 67b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 68b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 69b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger n = 0; 702e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger while (getline(&line, &len, f) != -1) { 712e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger char *p, *endp; 722e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (*line == '\n' || *line == '#') 73b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger continue; 74b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 752e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger for (p = line; ; p = endp) { 762e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger x = strtol(p, &endp, 0); 772e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (endp == p) 782e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger break; 792e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger 802e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (n >= MAXDIST) { 812e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger fprintf(stderr, "%s: too much data\n", 822e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger name); 832e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger n = -1; 842e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger goto error; 852e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger } 86b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger data[n++] = x; 87b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 88b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 892e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger error: 902e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger free(line); 91b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger fclose(f); 92b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return n; 93b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger} 94b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 95b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemmingerstatic int isnumber(const char *arg) 96b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger{ 97b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger char *p; 98b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger (void) strtod(arg, &p); 99b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return (p != arg); 100b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger} 101b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 102b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger#define NEXT_IS_NUMBER() (NEXT_ARG_OK() && isnumber(argv[1])) 103b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 104b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger/* Adjust for the fact that psched_ticks aren't always usecs 105b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger (based on kernel PSCHED_CLOCK configuration */ 106b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemmingerstatic int get_ticks(__u32 *ticks, const char *str) 107b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger{ 108b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger unsigned t; 109b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 110b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger if(get_usecs(&t, str)) 111b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return -1; 112b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 113b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger *ticks = tc_core_usec2tick(t); 114b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return 0; 115b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger} 116b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 117b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemmingerstatic char *sprint_ticks(__u32 ticks, char *buf) 118b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger{ 119b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return sprint_usecs(tc_core_tick2usec(ticks), buf); 120b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger} 121b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 122b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 123309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemmingerstatic int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv, 124309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger struct nlmsghdr *n) 125309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{ 1262e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger size_t dist_size = 0; 1272e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger struct rtattr *tail; 1282e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger struct tc_netem_qopt opt; 1292e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger struct tc_netem_corr cor; 1302e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger __s16 dist_data[MAXDIST]; 131309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 1322e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger memset(&opt, 0, sizeof(opt)); 1332e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger opt.limit = 1000; 1342e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger memset(&cor, 0, sizeof(cor)); 135309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 136309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger while (argc > 0) { 137309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger if (matches(*argv, "limit") == 0) { 138309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger NEXT_ARG(); 1392e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (get_size(&opt.limit, *argv)) { 140309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger explain1("limit"); 141309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return -1; 142309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger } 143b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } else if (matches(*argv, "latency") == 0 || 144b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger matches(*argv, "delay") == 0) { 145309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger NEXT_ARG(); 1462e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (get_ticks(&opt.latency, *argv)) { 147309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger explain1("latency"); 148309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return -1; 149309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger } 150b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 151b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger if (NEXT_IS_NUMBER()) { 152b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger NEXT_ARG(); 1532e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (get_ticks(&opt.jitter, *argv)) { 154b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger explain1("latency"); 155b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return -1; 156b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 157b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 158b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger if (NEXT_IS_NUMBER()) { 159b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger NEXT_ARG(); 1602e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (get_percent(&cor.delay_corr, 161b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger *argv)) { 162b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger explain1("latency"); 163b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return -1; 164b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 165b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 166b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 167b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } else if (matches(*argv, "loss") == 0 || 168b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger matches(*argv, "drop") == 0) { 169309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger NEXT_ARG(); 1702e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (get_percent(&opt.loss, *argv)) { 171309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger explain1("loss"); 172309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return -1; 173309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger } 174b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger if (NEXT_IS_NUMBER()) { 175b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger NEXT_ARG(); 1762e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (get_percent(&cor.loss_corr, *argv)) { 177b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger explain1("loss"); 178b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return -1; 179b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 180b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 181309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger } else if (matches(*argv, "gap") == 0) { 182309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger NEXT_ARG(); 1832e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (get_u32(&opt.gap, *argv, 0)) { 184309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger explain1("gap"); 185309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return -1; 186309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger } 187ffb79d06915fe3b1ee5d2e4e37c1db67c3c06cdfosdl.net!shemminger } else if (matches(*argv, "duplicate") == 0) { 188309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger NEXT_ARG(); 1892e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (get_percent(&opt.duplicate, *argv)) { 190ffb79d06915fe3b1ee5d2e4e37c1db67c3c06cdfosdl.net!shemminger explain1("duplicate"); 191309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return -1; 192309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger } 193b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger if (NEXT_IS_NUMBER()) { 194b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger NEXT_ARG(); 1952e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (get_percent(&cor.dup_corr, *argv)) { 196b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger explain1("duplicate"); 197b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return -1; 198b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 199b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 200b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } else if (matches(*argv, "distribution") == 0) { 201309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger NEXT_ARG(); 2022e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger dist_size = get_distribution(*argv, dist_data); 2032e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (dist_size < 0) 204309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return -1; 205309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger } else if (strcmp(*argv, "help") == 0) { 206309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger explain(); 207309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return -1; 208309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger } else { 209309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger fprintf(stderr, "What is \"%s\"?\n", *argv); 210309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger explain(); 211309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return -1; 212309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger } 213309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger argc--; argv++; 214309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger } 215309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 2161a1d22a72284acf43f7aff5210db018076e66194n); tail = NLMSG_TAIL(n); 217025dc69a25f016c3035212517bae481dafbb2651osdl.net!shemminger 2182e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)); 2192e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger addattr_l(n, 1024, TCA_NETEM_CORR, &cor, sizeof(cor)); 2202e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger 2212e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (dist_size > 0) { 2222e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger addattr_l(n, 32768, TCA_NETEM_DELAY_DIST, 2232e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger dist_data, dist_size*sizeof(dist_data[0])); 2242e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger } 2251a1d22a72284acf43f7aff5210db018076e66194void *) NLMSG_TAIL(n) - (void *) tail; tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; 226b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger return 0; 227309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger} 228309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 229309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemmingerstatic int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) 230309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger{ 2312e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger const struct tc_netem_corr *cor = NULL; 2322e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger struct tc_netem_qopt qopt; 2332e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger int len = RTA_PAYLOAD(opt) - sizeof(qopt); 234309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger SPRINT_BUF(b1); 235309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 236309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger if (opt == NULL) 237309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return 0; 238309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 2392e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (len < 0) { 2402e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger fprintf(stderr, "options size error\n"); 241309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return -1; 242b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 2432e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger memcpy(&qopt, RTA_DATA(opt), sizeof(qopt)); 2442e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger 2452e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (len > 0) { 2462e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger struct rtattr *tb[TCA_NETEM_MAX]; 2472e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger parse_rtattr(tb, TCA_NETEM_MAX, RTA_DATA(opt) + sizeof(qopt), 2482e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger len); 2492e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger 2502e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (tb[TCA_NETEM_CORR]) { 2512e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (RTA_PAYLOAD(tb[TCA_NETEM_CORR]) < sizeof(*cor)) 2522e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger return -1; 2532e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger cor = RTA_DATA(tb[TCA_NETEM_CORR]); 2542e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger } 2552e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger } 256309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 2572e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger fprintf(f, "limit %d", qopt.limit); 25831fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger 2592e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (qopt.latency) { 2602e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger fprintf(f, " delay %s", sprint_ticks(qopt.latency, b1)); 261b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 2622e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (qopt.jitter) { 2632e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger fprintf(f, " %s", sprint_ticks(qopt.jitter, b1)); 2642e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (cor && cor->delay_corr) 2652e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger fprintf(f, " %s", sprint_percent(cor->delay_corr, b1)); 266b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 267b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 268b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 2692e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (qopt.loss) { 2702e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger fprintf(f, " loss %s", sprint_percent(qopt.loss, b1)); 2712e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (cor && cor->loss_corr) 2722e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger fprintf(f, " %s", sprint_percent(cor->loss_corr, b1)); 273b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 274b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 2752e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (qopt.duplicate) { 276b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger fprintf(f, " duplicate %s", 2772e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger sprint_percent(qopt.duplicate, b1)); 2782e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (cor && cor->dup_corr) 2792e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger fprintf(f, " %s", sprint_percent(cor->dup_corr, b1)); 280b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger } 281b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 2822e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger if (qopt.gap) 2832e21655e39099e6a9645483bdeeebbd9e24e2345osdl.net!shemminger fprintf(f, " gap %lu", (unsigned long)qopt.gap); 284309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 285309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger return 0; 286309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger} 287309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger 28895812b56a5a66e7e9a21744cfe8bc0bb9791ea98net[shemminger]!kaberstruct qdisc_util netem_qdisc_util = { 28931fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger .id = "netem", 29031fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger .parse_qopt = netem_parse_opt, 29131fa60e00f6299328c4ae13a543c2e764b9379b7osdl.net!shemminger .print_qopt = netem_print_opt, 292309a4c90a5d4f648653de32807cd4146763913e9osdl.net!shemminger}; 293b7be3d0cd2bd699c1bdaef960e7c7bf3ad5036d3osdl.net!shemminger 294