fixed compiler warnings
This commit is contained in:
parent
c4ea08d937
commit
793acedaac
4 changed files with 89 additions and 85 deletions
42
dist.c
42
dist.c
|
@ -5,12 +5,14 @@
|
|||
* - https://github.com/thom311/libnl/blob/master/lib/route/qdisc/netem.c
|
||||
*
|
||||
* @author Steffen Vogel <post@steffenvogel.de>
|
||||
* @copyright 2014-2015, Steffen Vogel
|
||||
* @copyright 2014-2015, Steffen Vogel
|
||||
* @license GPLv3
|
||||
*********************************************************************************/
|
||||
|
||||
#define _POSIX_C_SOURCE 1
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <error.h>
|
||||
|
@ -38,20 +40,20 @@ int rtnl_netem_set_delay_distribution_data(struct rtnl_qdisc *qdisc, short *data
|
|||
|
||||
if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
|
||||
BUG();
|
||||
|
||||
|
||||
if (len > MAXDIST)
|
||||
return -NLE_INVAL;
|
||||
|
||||
netem->qnm_dist.dist_data = (int16_t *) calloc(len, sizeof(int16_t));
|
||||
|
||||
size_t i;
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < len; i++)
|
||||
netem->qnm_dist.dist_data[i] = data[i];
|
||||
|
||||
|
||||
netem->qnm_dist.dist_size = len;
|
||||
netem->qnm_mask |= SCH_NETEM_ATTR_DIST;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static short * dist_make(FILE *fp, double *mu, double *sigma, double *rho)
|
||||
|
@ -70,14 +72,14 @@ static short * dist_make(FILE *fp, double *mu, double *sigma, double *rho)
|
|||
|
||||
fprintf(stderr, "Read %d values, mu %10.4f, sigma %10.4f, rho %10.4f\n",
|
||||
limit, *mu, *sigma, *rho);
|
||||
|
||||
|
||||
table = makedist(x, limit, *mu, *sigma);
|
||||
free((void *) x);
|
||||
|
||||
cumulativedist(table, DISTTABLESIZE, &total);
|
||||
inverse = inverttable(table, TABLESIZE, DISTTABLESIZE, total);
|
||||
interpolatetable(inverse, TABLESIZE);
|
||||
|
||||
|
||||
return inverse;
|
||||
}
|
||||
|
||||
|
@ -117,11 +119,11 @@ static int dist_load(int argc, char *argv[])
|
|||
short *inverse = dist_make(fp, &mu, &sigma, &rho);
|
||||
if (!inverse)
|
||||
error(-1, 0, "Failed to generate distribution");
|
||||
|
||||
|
||||
int ret;
|
||||
|
||||
struct nl_sock *sock;
|
||||
|
||||
|
||||
struct rtnl_link *link;
|
||||
struct rtnl_tc *qdisc_prio = NULL;
|
||||
struct rtnl_tc *qdisc_netem = NULL;
|
||||
|
@ -130,33 +132,33 @@ static int dist_load(int argc, char *argv[])
|
|||
/* Create connection to netlink */
|
||||
sock = nl_socket_alloc();
|
||||
nl_connect(sock, NETLINK_ROUTE);
|
||||
|
||||
|
||||
/* Get interface */
|
||||
link = tc_get_link(sock, cfg.dev);
|
||||
if (!link)
|
||||
error(-1, 0, "Interface does not exist: %s", cfg.dev);
|
||||
|
||||
|
||||
/* Reset TC subsystem */
|
||||
ret = tc_reset(sock, link);
|
||||
if (ret && ret != -NLE_OBJ_NOTFOUND)
|
||||
error(-1, 0, "Failed to reset TC: %s", nl_geterror(ret));
|
||||
|
||||
|
||||
/* Setup TC subsystem */
|
||||
if ((ret = tc_prio(sock, link, &qdisc_prio)))
|
||||
error(-1, 0, "Failed to setup TC: prio qdisc: %s", nl_geterror(ret));
|
||||
|
||||
if ((ret = tc_classifier(sock, link, &cls_fw, cfg.mark, cfg.mask)))
|
||||
error(-1, 0, "Failed to setup TC: fw filter: %s", nl_geterror(ret));
|
||||
|
||||
|
||||
if ((ret = tc_netem(sock, link, &qdisc_netem)))
|
||||
error(-1, 0, "Failed to setup TC: netem qdisc: %s", nl_geterror(ret));
|
||||
|
||||
|
||||
/* We will use the default normal distribution for now */
|
||||
if (rtnl_netem_set_delay_distribution_data((struct rtnl_qdisc *) qdisc_netem, inverse, TABLESIZE))
|
||||
error(-1, 0, "Failed to set netem delay distrubtion: %s", nl_geterror(ret));
|
||||
|
||||
|
||||
rtnl_netem_set_delay((struct rtnl_qdisc *) qdisc_netem, mu);
|
||||
rtnl_netem_set_jitter((struct rtnl_qdisc *) qdisc_netem, sigma);
|
||||
rtnl_netem_set_jitter((struct rtnl_qdisc *) qdisc_netem, sigma);
|
||||
|
||||
nl_close(sock);
|
||||
nl_socket_free(sock);
|
||||
|
@ -170,11 +172,11 @@ int dist(int argc, char *argv[])
|
|||
|
||||
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);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
62
probe.c
62
probe.c
|
@ -1,12 +1,12 @@
|
|||
/** Probing for RTT, Loss, Duplication, Corruption.
|
||||
*
|
||||
* @author Steffen Vogel <post@steffenvogel.de>
|
||||
* @copyright 2014-2015, Steffen Vogel
|
||||
* @copyright 2014-2015, Steffen Vogel
|
||||
* @license GPLv3
|
||||
*********************************************************************************/
|
||||
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#define _BSD_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -40,7 +40,7 @@
|
|||
int probe_tcp(int sd, unsigned short dport, struct timespec *ts)
|
||||
{
|
||||
struct timespec ts_syn, ts_ack;
|
||||
|
||||
|
||||
struct iphdr ihdr;
|
||||
struct tcphdr thdr;
|
||||
struct msghdr msgh;
|
||||
|
@ -55,38 +55,38 @@ int probe_tcp(int sd, unsigned short dport, struct timespec *ts)
|
|||
memset(&ihdr, 0, sizeof(ihdr));
|
||||
memset(&thdr, 0, sizeof(thdr));
|
||||
memset(&msgh, 0, sizeof(msgh));
|
||||
|
||||
|
||||
/* Randomize sequence number and source port */
|
||||
unsigned int seq = (unsigned) rand();
|
||||
unsigned short sport = (rand() + 1024) & 0xFFFF;
|
||||
|
||||
|
||||
thdr.syn = 1;
|
||||
thdr.seq = htonl(seq);
|
||||
thdr.source = htons(sport);
|
||||
thdr.source = htons(sport);
|
||||
thdr.dest = htons(dport);
|
||||
thdr.doff = 5;
|
||||
thdr.check = tcp_csum((unsigned short *) &thdr, sizeof(thdr));
|
||||
|
||||
|
||||
msgh.msg_iov = &iov[1]; // only send TCP header
|
||||
msgh.msg_iovlen = 1;
|
||||
|
||||
|
||||
if (ts_sendmsg(sd, &msgh, 0, &ts_syn) < 0)
|
||||
error(-1, errno, "Failed to send SYN packet");
|
||||
|
||||
|
||||
/* Receiving ACK */
|
||||
memset(&ihdr, 0, sizeof(ihdr));
|
||||
memset(&thdr, 0, sizeof(thdr));
|
||||
|
||||
msgh.msg_iov = &iov[0]; // receive IP + TCP header
|
||||
msgh.msg_iovlen = 2;
|
||||
|
||||
|
||||
retry: len = ts_recvmsg(sd, &msgh, 0, &ts_ack);
|
||||
if (len < 0)
|
||||
error(-1, 0, "Failed to receive ACK / RST packet");
|
||||
|
||||
//printf("TCP: len=%u, syn=%u, ack=%u, rst=%u, seq=%u, ack_seq=%u, src=%u, dst=%u\n",
|
||||
// len, thdr.syn, thdr.ack, thdr.rst, ntohl(thdr.seq), ntohl(thdr.ack_seq), ntohs(thdr.source), ntohs(thdr.dest));
|
||||
|
||||
|
||||
/* Check response */
|
||||
if (thdr.source != htons(dport) || thdr.dest != htons(sport)) {
|
||||
printf("Skipping invalid ports\n");
|
||||
|
@ -100,40 +100,40 @@ retry: len = ts_recvmsg(sd, &msgh, 0, &ts_ack);
|
|||
printf("Skipping invalid seq\n");
|
||||
goto retry;
|
||||
}
|
||||
|
||||
|
||||
*ts = time_diff(&ts_syn, &ts_ack);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probe(int argc, char *argv[])
|
||||
{
|
||||
int run = 0, tfd;
|
||||
|
||||
|
||||
/* Parse address */
|
||||
struct nl_addr *addr;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
|
||||
/* Parse args */
|
||||
if (argc != 2)
|
||||
error(-1, 0, "usage: netem probe IP PORT");
|
||||
|
||||
|
||||
if (nl_addr_parse(argv[0], AF_UNSPEC, &addr))
|
||||
error(-1, 0, "Failed to parse address: %s", argv[0]);
|
||||
|
||||
|
||||
unsigned short dport = atoi(argv[1]);
|
||||
if (!dport)
|
||||
error(-1, 0, "Failed to parse port: %s", argv[1]);
|
||||
|
||||
|
||||
socklen_t sinlen = sizeof(sin);
|
||||
if (nl_addr_fill_sockaddr(addr, (struct sockaddr *) &sin, &sinlen))
|
||||
error(-1, 0, "Failed to fill sockaddr");
|
||||
|
||||
|
||||
/* Create RAW socket */
|
||||
int sd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
|
||||
if (sd < 0)
|
||||
error(-1, errno, "Failed to create socket");
|
||||
|
||||
|
||||
/* Bind socket to destination */
|
||||
if (connect(sd, (struct sockaddr *) &sin, sizeof(sin)))
|
||||
error(-1, 0, "Failed to connect socket");
|
||||
|
@ -143,27 +143,27 @@ int probe(int argc, char *argv[])
|
|||
fprintf(stderr, "Failed to enable timestamping: %s\n", strerror(errno));
|
||||
if (ts_enable_sd(sd))
|
||||
fprintf(stderr, "Failed to set SO_TIMESTAMPING: %s\n", strerror(errno));
|
||||
|
||||
|
||||
/* Prepare payload */
|
||||
struct timespec ts;
|
||||
|
||||
|
||||
/* Prepare statistics */
|
||||
struct hist hist;
|
||||
hist_create(&hist, 0, 0, 1);
|
||||
|
||||
|
||||
/* Start timer */
|
||||
if ((tfd = timerfd_init(cfg.rate)) < 0)
|
||||
error(-1, errno, "Failed to initilize timer");
|
||||
|
||||
do {
|
||||
|
||||
do {
|
||||
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));
|
||||
|
||||
|
||||
/* Warmup: adjust histogram after rough estimation of RTT */
|
||||
if (run == 20) {
|
||||
double span = hist.highest - hist.lowest;
|
||||
|
@ -179,20 +179,20 @@ int probe(int argc, char *argv[])
|
|||
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
printf("%f %f %f\n", rtt, hist_mean(&hist), hist_stddev(&hist));
|
||||
fflush(stdout);
|
||||
|
||||
run += timerfd_wait(tfd);
|
||||
} while (cfg.limit && run < cfg.limit);
|
||||
|
||||
|
||||
hist_print(&hist, stderr);
|
||||
hist_destroy(&hist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
64
tc.c
64
tc.c
|
@ -1,12 +1,14 @@
|
|||
/** Trafic Controller (TC) related functions
|
||||
*
|
||||
* @author Steffen Vogel <post@steffenvogel.de>
|
||||
* @copyright 2014-2015, Steffen Vogel
|
||||
* @copyright 2014-2015, Steffen Vogel
|
||||
* @license GPLv3
|
||||
*********************************************************************************/
|
||||
|
||||
#define _POSIX_C_SOURCE 1
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netlink/route/qdisc/netem.h>
|
||||
#include <netlink/route/qdisc/prio.h>
|
||||
|
@ -41,7 +43,7 @@ int tc_prio(struct nl_sock *sock, struct rtnl_link *link, struct rtnl_tc **tc)
|
|||
rtnl_tc_set_link(TC_CAST(q), link);
|
||||
rtnl_tc_set_parent(TC_CAST(q), TC_H_ROOT);
|
||||
rtnl_tc_set_handle(TC_CAST(q), TC_HANDLE(1, 0));
|
||||
rtnl_tc_set_kind(TC_CAST(q), "prio");
|
||||
rtnl_tc_set_kind(TC_CAST(q), "prio");
|
||||
|
||||
rtnl_qdisc_prio_set_bands(q, 3+1);
|
||||
rtnl_qdisc_prio_set_priomap(q, map, 7);
|
||||
|
@ -49,14 +51,14 @@ int tc_prio(struct nl_sock *sock, struct rtnl_link *link, struct rtnl_tc **tc)
|
|||
int ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE);
|
||||
|
||||
*tc = TC_CAST(q);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tc_netem(struct nl_sock *sock, struct rtnl_link *link, struct rtnl_tc **tc)
|
||||
{
|
||||
struct rtnl_qdisc *q;
|
||||
|
||||
|
||||
if (*tc == NULL) {
|
||||
q = rtnl_qdisc_alloc();
|
||||
|
||||
|
@ -71,7 +73,7 @@ int tc_netem(struct nl_sock *sock, struct rtnl_link *link, struct rtnl_tc **tc)
|
|||
int ret = rtnl_qdisc_add(sock, q, NLM_F_CREATE);
|
||||
|
||||
*tc = TC_CAST(q);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -81,17 +83,17 @@ int tc_classifier(struct nl_sock *sock, struct rtnl_link *link, struct rtnl_tc *
|
|||
|
||||
rtnl_tc_set_link(TC_CAST(c), link);
|
||||
rtnl_tc_set_handle(TC_CAST(c), mark);
|
||||
rtnl_tc_set_kind(TC_CAST(c), "fw");
|
||||
rtnl_tc_set_kind(TC_CAST(c), "fw");
|
||||
|
||||
rtnl_cls_set_protocol(c, ETH_P_ALL);
|
||||
|
||||
|
||||
rtnl_fw_set_classid(c, TC_HANDLE(1, 1));
|
||||
rtnl_fw_set_mask(c, mask);
|
||||
|
||||
int ret = rtnl_cls_add(sock, c, NLM_F_CREATE);
|
||||
|
||||
*tc = TC_CAST(c);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -102,81 +104,81 @@ int tc_reset(struct nl_sock *sock, struct rtnl_link *link)
|
|||
/* Restore default qdisc by deleting the root qdisc (see tc-pfifo_fast(8)) */
|
||||
rtnl_tc_set_link(TC_CAST(q), link);
|
||||
rtnl_tc_set_parent(TC_CAST(q), TC_H_ROOT);
|
||||
|
||||
int ret = rtnl_qdisc_delete(sock, q);
|
||||
|
||||
int ret = rtnl_qdisc_delete(sock, q);
|
||||
rtnl_qdisc_put(q);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tc_get_stats(struct nl_sock *sock, struct rtnl_tc *tc, struct tc_stats *stats)
|
||||
{
|
||||
uint64_t *counters = (uint64_t *) stats;
|
||||
|
||||
|
||||
struct nl_cache *cache;
|
||||
|
||||
|
||||
rtnl_qdisc_alloc_cache(sock, &cache);
|
||||
|
||||
|
||||
for (int i = 0; i <= RTNL_TC_STATS_MAX; i++)
|
||||
counters[i] = rtnl_tc_get_stat(tc, i);
|
||||
|
||||
|
||||
nl_cache_free(cache);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tc_print_stats(struct tc_statistics *stats)
|
||||
void tc_print_stats(struct tc_statistics *stats)
|
||||
{
|
||||
printf("packets %u bytes %u\n", stats->packets, stats->bytes);
|
||||
printf("packets %lu bytes %lu\n", stats->packets, stats->bytes);
|
||||
}
|
||||
|
||||
int tc_print_netem(struct rtnl_tc *tc)
|
||||
{
|
||||
struct rtnl_qdisc *ne = (struct rtnl_qdisc *) tc;
|
||||
|
||||
|
||||
if (rtnl_netem_get_limit(ne) > 0)
|
||||
printf("limit %upkts", rtnl_netem_get_limit(ne));
|
||||
|
||||
if (rtnl_netem_get_delay(ne) > 0) {
|
||||
printf("delay %fms ", rtnl_netem_get_delay(ne) / 1000.0);
|
||||
|
||||
|
||||
if (rtnl_netem_get_jitter(ne) > 0) {
|
||||
printf("jitter %fms ", rtnl_netem_get_jitter(ne) / 1000.0);
|
||||
|
||||
|
||||
if (rtnl_netem_get_delay_correlation(ne) > 0)
|
||||
printf("%u%% ", rtnl_netem_get_delay_correlation(ne));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (rtnl_netem_get_loss(ne) > 0) {
|
||||
printf("loss %u%% ", rtnl_netem_get_loss(ne));
|
||||
|
||||
|
||||
if (rtnl_netem_get_loss_correlation(ne) > 0)
|
||||
printf("%u%% ", rtnl_netem_get_loss_correlation(ne));
|
||||
}
|
||||
|
||||
|
||||
if (rtnl_netem_get_reorder_probability(ne) > 0) {
|
||||
printf(" reorder%u%% ", rtnl_netem_get_reorder_probability(ne));
|
||||
|
||||
|
||||
if (rtnl_netem_get_reorder_correlation(ne) > 0)
|
||||
printf("%u%% ", rtnl_netem_get_reorder_correlation(ne));
|
||||
}
|
||||
|
||||
|
||||
if (rtnl_netem_get_corruption_probability(ne) > 0) {
|
||||
printf("corruption %u%% ", rtnl_netem_get_corruption_probability(ne));
|
||||
|
||||
|
||||
if (rtnl_netem_get_corruption_correlation(ne) > 0)
|
||||
printf("%u%% ", rtnl_netem_get_corruption_correlation(ne));
|
||||
}
|
||||
|
||||
|
||||
if (rtnl_netem_get_duplicate(ne) > 0) {
|
||||
printf("duplication %u%% ", rtnl_netem_get_duplicate(ne));
|
||||
|
||||
|
||||
if (rtnl_netem_get_duplicate_correlation(ne) > 0)
|
||||
printf("%u%% ", rtnl_netem_get_duplicate_correlation(ne));
|
||||
}
|
||||
|
||||
|
||||
printf("\n");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
6
tc.h
6
tc.h
|
@ -1,7 +1,7 @@
|
|||
/** Trafic Controller (TC) related functions
|
||||
*
|
||||
* @author Steffen Vogel <post@steffenvogel.de>
|
||||
* @copyright 2014-2015, Steffen Vogel
|
||||
* @copyright 2014-2015, Steffen Vogel
|
||||
* @license GPLv3
|
||||
*********************************************************************************/
|
||||
|
||||
|
@ -21,7 +21,7 @@ struct tc_statistics {
|
|||
uint64_t backlog; // Current backlog length.
|
||||
uint64_t drops; // Total number of packets dropped.
|
||||
uint64_t requeues; // Total number of requeues.
|
||||
uint64_t overlimits; // Total number of overlimits.
|
||||
uint64_t overlimits; // Total number of overlimits.
|
||||
};
|
||||
|
||||
struct rtnl_link * tc_get_link(struct nl_sock *sock, const char *dev);
|
||||
|
@ -36,7 +36,7 @@ int tc_reset(struct nl_sock *sock, struct rtnl_link *link);
|
|||
|
||||
int tc_get_stats(struct nl_sock *sock, struct rtnl_tc *tc, struct tc_stats *stats);
|
||||
|
||||
int tc_print_stats(struct tc_statistics *stats);
|
||||
void tc_print_stats(struct tc_statistics *stats);
|
||||
|
||||
int tc_print_netem(struct rtnl_tc *tc);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue