2014-07-14 11:49:44 +00:00
|
|
|
/** Traffic control (tc): setup interface queuing desciplines.
|
2014-06-28 06:40:52 +00:00
|
|
|
*
|
|
|
|
* S2SS uses these functions to setup the network emulation feature.
|
2014-06-25 01:53:48 +00:00
|
|
|
*
|
|
|
|
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
2015-06-02 21:53:04 +02:00
|
|
|
* @copyright 2014-2015, Institute for Automation of Complex Power Systems, EONERC
|
|
|
|
* This file is part of S2SS. All Rights Reserved. Proprietary and confidential.
|
|
|
|
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
|
|
|
*********************************************************************************/
|
2014-06-25 01:53:48 +00:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include "utils.h"
|
|
|
|
#include "if.h"
|
|
|
|
#include "tc.h"
|
|
|
|
|
2015-03-31 13:48:41 +02:00
|
|
|
int tc_parse(config_setting_t *cfg, struct netem *em)
|
|
|
|
{
|
|
|
|
em->valid = 0;
|
|
|
|
|
|
|
|
if (config_setting_lookup_string(cfg, "distribution", &em->distribution))
|
|
|
|
em->valid |= TC_NETEM_DISTR;
|
|
|
|
if (config_setting_lookup_int(cfg, "delay", &em->delay))
|
|
|
|
em->valid |= TC_NETEM_DELAY;
|
|
|
|
if (config_setting_lookup_int(cfg, "jitter", &em->jitter))
|
|
|
|
em->valid |= TC_NETEM_JITTER;
|
|
|
|
if (config_setting_lookup_int(cfg, "loss", &em->loss))
|
|
|
|
em->valid |= TC_NETEM_LOSS;
|
|
|
|
if (config_setting_lookup_int(cfg, "duplicate", &em->duplicate))
|
|
|
|
em->valid |= TC_NETEM_DUPL;
|
|
|
|
if (config_setting_lookup_int(cfg, "corrupt", &em->corrupt))
|
|
|
|
em->valid |= TC_NETEM_CORRUPT;
|
|
|
|
|
|
|
|
/** @todo Validate netem config values */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-25 01:53:48 +00:00
|
|
|
int tc_reset(struct interface *i)
|
|
|
|
{
|
|
|
|
char cmd[128];
|
|
|
|
snprintf(cmd, sizeof(cmd), "tc qdisc del dev %s root", i->name);
|
|
|
|
|
2014-07-04 09:47:29 +00:00
|
|
|
debug(6, "Reset traffic control for interface '%s'", i->name);
|
|
|
|
|
2014-12-05 12:40:33 +01:00
|
|
|
return system2(cmd);
|
2014-06-25 01:53:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int tc_prio(struct interface *i, tc_hdl_t handle, int bands)
|
|
|
|
{
|
|
|
|
char cmd[128];
|
|
|
|
int len = 0;
|
2014-06-25 17:50:28 +00:00
|
|
|
int priomap[] = { 1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 };
|
2014-06-25 01:53:48 +00:00
|
|
|
|
|
|
|
len += snprintf(cmd+len, sizeof(cmd)-len,
|
|
|
|
"tc qdisc add dev %s root handle %u prio bands %u priomap",
|
2014-06-25 17:50:28 +00:00
|
|
|
i->name, TC_HDL_MAJ(handle), bands + 3);
|
2014-06-25 01:53:48 +00:00
|
|
|
|
2014-06-25 17:50:28 +00:00
|
|
|
for (int i = 0; i < 16; i++)
|
|
|
|
len += snprintf(cmd+len, sizeof(cmd)-len, " %u", priomap[i] + bands);
|
2014-06-25 01:53:48 +00:00
|
|
|
|
2014-07-04 09:47:29 +00:00
|
|
|
debug(6, "Replace master qdisc for interface '%s'", i->name);
|
|
|
|
|
2014-12-05 12:40:33 +01:00
|
|
|
return system2(cmd);
|
2014-06-25 01:53:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int tc_netem(struct interface *i, tc_hdl_t parent, struct netem *em)
|
|
|
|
{
|
|
|
|
int len = 0;
|
|
|
|
char cmd[256];
|
|
|
|
len += snprintf(cmd+len, sizeof(cmd)-len,
|
|
|
|
"tc qdisc add dev %s parent %u:%u netem",
|
|
|
|
i->name, TC_HDL_MAJ(parent), TC_HDL_MIN(parent));
|
|
|
|
|
|
|
|
if (em->valid & TC_NETEM_DELAY) {
|
|
|
|
len += snprintf(cmd+len, sizeof(cmd)-len, " delay %u", em->delay);
|
|
|
|
|
|
|
|
if (em->valid & TC_NETEM_JITTER)
|
|
|
|
len += snprintf(cmd+len, sizeof(cmd)-len, " %u", em->jitter);
|
|
|
|
if (em->valid & TC_NETEM_DISTR)
|
|
|
|
len += snprintf(cmd+len, sizeof(cmd)-len, " distribution %s", em->distribution);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (em->valid & TC_NETEM_LOSS)
|
|
|
|
len += snprintf(cmd+len, sizeof(cmd)-len, " loss random %u", em->loss);
|
|
|
|
if (em->valid & TC_NETEM_DUPL)
|
|
|
|
len += snprintf(cmd+len, sizeof(cmd)-len, " duplicate %u", em->duplicate);
|
|
|
|
if (em->valid & TC_NETEM_CORRUPT)
|
|
|
|
len += snprintf(cmd+len, sizeof(cmd)-len, " corrupt %u", em->corrupt);
|
|
|
|
|
2014-07-04 09:47:29 +00:00
|
|
|
debug(6, "Setup netem qdisc for interface '%s'", i->name);
|
|
|
|
|
2014-12-05 12:40:33 +01:00
|
|
|
return system2(cmd);
|
2014-06-25 01:53:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int tc_mark(struct interface *i, tc_hdl_t flowid, int mark)
|
|
|
|
{
|
|
|
|
char cmd[128];
|
|
|
|
snprintf(cmd, sizeof(cmd),
|
|
|
|
"tc filter add dev %s protocol ip handle %u fw flowid %u:%u",
|
|
|
|
i->name, mark, TC_HDL_MAJ(flowid), TC_HDL_MIN(flowid));
|
|
|
|
|
2014-09-09 08:58:41 +00:00
|
|
|
debug(7, "Add traffic filter to interface '%s': fwmark %u => flowid %u:%u",
|
|
|
|
i->name, mark, TC_HDL_MAJ(flowid), TC_HDL_MIN(flowid));
|
2014-07-04 09:47:29 +00:00
|
|
|
|
2014-12-05 12:40:33 +01:00
|
|
|
return system2(cmd);
|
2014-06-25 01:53:48 +00:00
|
|
|
|
|
|
|
}
|