added timers
This commit is contained in:
parent
8bb1700ffd
commit
5e30762904
2 changed files with 93 additions and 18 deletions
67
emulate.c
67
emulate.c
|
@ -5,10 +5,19 @@
|
|||
* @license GPLv3
|
||||
*********************************************************************************/
|
||||
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <netlink/route/qdisc/netem.h>
|
||||
#include <netlink/route/tc.h>
|
||||
|
||||
#include "tc.h"
|
||||
#include "config.h"
|
||||
#include "timing.h"
|
||||
|
||||
int emulate(int argc, char *argv[])
|
||||
{
|
||||
|
@ -25,8 +34,8 @@ int emulate(int argc, char *argv[])
|
|||
struct rtnl_tc *cls_fw = NULL;
|
||||
|
||||
struct tc_netem netem = {
|
||||
.delay = 1000000,
|
||||
.limit = cfg.limit
|
||||
.limit = cfg.limit,
|
||||
.delay = 100000
|
||||
};
|
||||
|
||||
/* Create connection to netlink */
|
||||
|
@ -48,24 +57,60 @@ int emulate(int argc, char *argv[])
|
|||
if (ret)
|
||||
error(-1, 0, "Failed to setup TC: prio qdisc: %s", nl_geterror(ret));
|
||||
|
||||
ret = tc_netem(sock, link, &qdisc_netem, &netem);
|
||||
if (ret)
|
||||
error(-1, 0, "Failed to setup TC: netem qdisc: %s", nl_geterror(ret));
|
||||
|
||||
ret = tc_classifier(sock, link, &cls_fw, cfg.mark, cfg.mask);
|
||||
if (ret)
|
||||
error(-1, 0, "Failed to setup TC: fw filter: %s", nl_geterror(ret));
|
||||
|
||||
int run = 0;
|
||||
while (cfg.limit && run < cfg.limit) {
|
||||
rtnl_tc_dump_stats(qdisc_netem, &dp_param);
|
||||
sleep(1);
|
||||
ret = tc_netem(sock, link, &qdisc_netem, &netem);
|
||||
if (ret)
|
||||
error(-1, 0, "Failed to setup TC: netem qdisc: %s", nl_geterror(ret));
|
||||
|
||||
/* We will use the default normal distribution for now */
|
||||
rtnl_netem_set_delay_distribution(qdisc_netem, "normal");
|
||||
|
||||
/* Start timer */
|
||||
struct itimerspec its = {
|
||||
.it_interval = time_from_double(1 / cfg.rate),
|
||||
.it_value = { 1, 0 }
|
||||
};
|
||||
|
||||
int tfd = timerfd_create(CLOCK_REALTIME, 0);
|
||||
if (tfd < 0)
|
||||
error(-1, errno, "Failed to create timer");
|
||||
|
||||
if (timerfd_settime(tfd, 0, &its, NULL))
|
||||
error(-1, errno, "Failed to start timer");
|
||||
|
||||
char *line = NULL;
|
||||
size_t linelen = 0;
|
||||
|
||||
unsigned run = 0;
|
||||
while (!cfg.limit || run < cfg.limit) {
|
||||
float rtt, mu, sigma;
|
||||
|
||||
netem.delay += 10000;
|
||||
/* Show queuing discipline statistics */
|
||||
rtnl_tc_dump_stats(qdisc_netem, &dp_param);
|
||||
|
||||
/* Parse new data */
|
||||
if (feof(stdin) || getline(&line, &linelen, stdin) == -1)
|
||||
error(-1, errno, "Failed to read data from stdin");
|
||||
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
|
||||
if (sscanf(line, "%f %f %f ", &rtt, &mu, &sigma) != 3)
|
||||
error(-1, 0, "Invalid data format");
|
||||
|
||||
/* Update the netem config according to the measurements */
|
||||
/* TODO: Add more characteristics */
|
||||
netem.delay = (mu / 2) * 1e6;
|
||||
netem.jitter = sigma * 1e6;
|
||||
|
||||
ret = tc_netem(sock, link, &qdisc_netem, &netem);
|
||||
if (ret)
|
||||
error(-1, 0, "Failed to update TC: netem qdisc: %s", nl_geterror(ret));
|
||||
|
||||
timerfd_wait(tfd);
|
||||
run++;
|
||||
}
|
||||
|
||||
|
|
44
probe.c
44
probe.c
|
@ -20,6 +20,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/timerfd.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
|
@ -148,25 +149,54 @@ int probe(int argc, char *argv[])
|
|||
struct hist hist;
|
||||
hist_create(&hist, 0, 0, 1);
|
||||
|
||||
while (hist.total < cfg.limit) {
|
||||
probe_tcp(sd, &ts);
|
||||
/* Start timer */
|
||||
struct itimerspec its = {
|
||||
.it_interval = time_from_double(1 / cfg.rate),
|
||||
.it_value = { 1, 0 }
|
||||
};
|
||||
|
||||
int tfd = timerfd_create(CLOCK_REALTIME, 0);
|
||||
if (tfd < 0)
|
||||
error(-1, errno, "Failed to create timer");
|
||||
|
||||
if (timerfd_settime(tfd, 0, &its, NULL))
|
||||
error(-1, errno, "Failed to start timer");
|
||||
|
||||
unsigned run = 0;
|
||||
while (cfg.limit && run < cfg.limit) {
|
||||
probe_tcp(sd, dport, &ts);
|
||||
|
||||
double rtt = time_to_double(&ts);
|
||||
hist_put(&hist, rtt);
|
||||
|
||||
printf("n=%u, rtt=%f, min=%f, max=%f, avg=%f, stddev=%f\n",
|
||||
hist.total, rtt, hist.lowest, hist.highest, hist_mean(&hist), hist_stddev(&hist));
|
||||
//printf("n=%u, rtt=%f, min=%f, max=%f, avg=%f, stddev=%f\n",
|
||||
// hist.total, rtt, hist.lowest, hist.highest, hist_mean(&hist), hist_stddev(&hist));
|
||||
|
||||
/* Warmup: adjust histogram after rough estimation of RTT */
|
||||
if (hist.total == 20 && hist.high == 0) {
|
||||
if (run == 20) {
|
||||
double span = hist.highest - hist.lowest;
|
||||
hist_destroy(&hist);
|
||||
hist_create(&hist, MAX(0, hist.lowest - span * 0.1), hist.highest + span * 0.2, 1e-3);
|
||||
hist_create(&hist, MAX(0, hist.lowest - span * 0.1), hist.highest + span * 0.2, span / 20);
|
||||
printf("Created new histogram: high=%f, low=%f, buckets=%u\n",
|
||||
hist.high, hist.low, hist.length);
|
||||
|
||||
/* Print header for output */
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm = localtime(&t);
|
||||
char addrs[32], date[32];
|
||||
|
||||
nl_addr2str(addr, addrs, sizeof(addrs));
|
||||
strftime(date, sizeof(date), "%a, %d %b %Y %T %z", tm);
|
||||
|
||||
printf("# Probing: %s on port %u\n", addrs, dport);
|
||||
printf("# Started: %s\n", date);
|
||||
printf("# RTT mu sigma (units in S)\n");
|
||||
}
|
||||
//else if (run > 20)
|
||||
printf("%f %f %f\n", rtt, hist_mean(&hist), hist_stddev(&hist));
|
||||
|
||||
//usleep(250 * 1e3); // 250 ms
|
||||
timerfd_wait(tfd);
|
||||
run++;
|
||||
}
|
||||
|
||||
hist_print(&hist);
|
||||
|
|
Loading…
Add table
Reference in a new issue