diff --git a/Makefile b/Makefile index a82e657..d34b1fa 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,14 @@ TARGETS = netem mark.so -OBJS = main.o probe.o emulate.o timing.o hist.o utils.o ts.o tc.o tcp.o +OBJS = main.o probe.o emulate.o timing.o hist.o utils.o ts.o tc.o tcp.o dist.o CC = gcc CFLAGS = -g -lrt -std=c99 -Wall + CFLAGS += -I/usr/local/include/libnl3 CFLAGS += -I/usr/include/libnl3 +CFLAGS += -I./libnl/include LDLIBS = -lnl-3 -lnl-route-3 -lm @@ -22,9 +24,5 @@ mark.so: mark.c clean: rm -f $(TARGETS) rm -f *.o *~ - make -C libnl clean - -libnl: - make -C libnl .PHONY: all clean libnl diff --git a/dist.c b/dist.c index 0bf6e34..27cf428 100644 --- a/dist.c +++ b/dist.c @@ -9,6 +9,14 @@ * @license GPLv3 *********************************************************************************/ +#include +#include +#include + +#include +#include +#include + /** * Set the delay distribution. Latency/jitter must be set before applying. * @arg qdisc Netem qdisc. @@ -100,21 +108,25 @@ static short * inverttable(int *table, int inversesize, int tablesize, int cumul short *inverse; double findex, fvalue; - inverse = (short *)malloc(inversesize*sizeof(short)); - for (i=0; i < inversesize; ++i) { + inverse = (short *) malloc(inversesize * sizeof(short)); + for (i=0; i < inversesize; ++i) inverse[i] = MINSHORT; - } + for (i=0; i < tablesize; ++i) { findex = ((double)i/(double)DISTTABLEGRANULARITY) - DISTTABLEDOMAIN; fvalue = (double)table[i]/(double)cumulative; inverseindex = (int)rint(fvalue*inversesize); inversevalue = (int)rint(findex*TABLEFACTOR); - if (inversevalue <= MINSHORT) inversevalue = MINSHORT+1; - if (inversevalue > MAXSHORT) inversevalue = MAXSHORT; + + if (inversevalue <= MINSHORT) + inversevalue = MINSHORT+1; + if (inversevalue > MAXSHORT) + inversevalue = MAXSHORT; + inverse[inverseindex] = inversevalue; } - return inverse; + return inverse; } /* Run simple linear interpolation over the table to fill in missing entries */ @@ -123,19 +135,45 @@ static void interpolatetable(short *table, int limit) int i, j, last, lasti = -1; last = MINSHORT; + for (i=0; i < limit; ++i) { if (table[i] == MINSHORT) { - for (j=i; j < limit; ++j) + for (j=i; j < limit; ++j) { if (table[j] != MINSHORT) break; - if (j < limit) { - table[i] = last + (i-lasti)*(table[j]-last)/(j-lasti); - } else { - table[i] = last + (i-lasti)*(MAXSHORT-last)/(limit-lasti); } - } else { + + if (j < limit) + table[i] = last + (i-lasti)*(table[j]-last)/(j-lasti); + else + table[i] = last + (i-lasti)*(MAXSHORT-last)/(limit-lasti); + } + else { last = table[i]; lasti = i; } } +} + +int dist_generate(int argc, char *argv[]) +{ + return 0; +} + +int dist_load(int argc, char *argv[]) +{ + return 0; +} + +int dist(int argc, char *argv[]) +{ + char *subcmd = argv[0]; + + if (argc != 1) + error(-1, 0, "Missing sub-command"); + + if (!strcmp(subcmd, "generate")) + return dist_generate(argc-1, argv+1); + else if (!strcmp(subcmd, "load")) + return dist_load(argc-1, argv+1); } \ No newline at end of file diff --git a/main.c b/main.c index 57f2145..32c4d8d 100644 --- a/main.c +++ b/main.c @@ -44,28 +44,31 @@ void quit(int sig, siginfo_t *si, void *ptr) int main(int argc, char *argv[]) { if (argc < 2) { - printf("usage: %s CMD [OPTIONS]\n", argv[0]); - printf(" CMD can be one of:\n"); - printf(" probe IP PORT\n"); - printf(" emulate\n"); - printf("\n"); - printf(" OPTIONS:\n"); - printf(" -m --mark N apply emulation only to packet buffers with mark N\n"); - printf(" -M --mask N an optional mask for the fw mark\n"); - printf(" -i --interval N update the emulation parameters every N seconds\n"); - printf(" -r --rate rate limit used for measurements and updates of network emulation\n"); - printf(" -l --limit how many probes should we sent\n"); - printf(" -d --dev network interface\n"); - - printf("\n"); - printf("netem util %s (built on %s %s)\n", - VERSION, __DATE__, __TIME__); - printf(" Copyright 2015, Steffen Vogel \n"); + printf( "usage: %s CMD [OPTIONS]\n" + " CMD can be one of:\n\n" + " probe IP PORT Start TCP SYN+ACK RTT probes and write measurements data to STDOUT\n" + " live Read measurement data from STDIN and configure Kernel (tc-netem(8)) on-the-fly.\n" + " This mode only uses the mean and standard deviation of of the previous samples\n" + " to configure the netem qdisc. This can be used to interactively replicate a network link.\n" + "\n" + " dist generate Read measurement data from STDIN and write distribution file to STDOUT (see /usr/lib/tc/*.dist)\n" + " dist load Read measurement data from STDIN and configure Kernel (tc-netem(8))\n" + " These modes generate an inverse cumulated probability function (CDF) from the previously\n" + " recorded measurements. This iCDF can either be used by tc(8) or 'netem table'\n" + "\n" + " OPTIONS:\n\n" + " -m --mark N apply emulation only to packet buffers with mark N\n" + " -M --mask N an optional mask for the fw mark\n" + " -i --interval N update the emulation parameters every N seconds\n" + " -r --rate rate limit used for measurements and updates of network emulation\n" + " -l --limit how many probes should we sent\n" + " -d --dev network interface\n" + "\n" + "netem util %s (built on %s %s)\n" + " Copyright 2015, Steffen Vogel \n", argv[0], VERSION, __DATE__, __TIME__); exit(EXIT_FAILURE); - } - - char *cmd = argv[1]; + } /* Setup signals */ struct sigaction sa_quit = { @@ -121,11 +124,15 @@ check: if (optarg == endptr) error(-1, 0, "Failed to parse parse option argument '-%c %s'", c, optarg); } + + char *cmd = argv[1]; - if (!strcmp(cmd, "probe")) + if (!strcmp(cmd, "probe")) return probe(argc-optind-1, argv+optind+1); - else if (!strcmp(cmd, "emulate")) + else if (!strcmp(cmd, "live")) return emulate(argc-optind-1, argv+optind+1); + else if (!strcmp(cmd, "dist")) + return dist(argc-optind-1, argv+optind+1); else error(-1, 0, "Unknown command: %s", cmd);