1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

added parser for netem settings and several functions to apply them

git-svn-id: https://zerberus.eonerc.rwth-aachen.de:8443/svn/s2ss/trunk@79 8ec27952-4edc-4aab-86aa-e87bb2611832
This commit is contained in:
Steffen Vogel 2014-06-25 01:53:48 +00:00
parent b8faadfe59
commit bd60c4424b
6 changed files with 219 additions and 13 deletions

View file

@ -19,7 +19,18 @@ nodes = {
id = 2,
type = "rtds",
local = "127.0.0.1:10202",
remote = "127.0.0.1:10203"
remote = "127.0.0.1:10203",
# Network emulation for single nodes
netem = {
limit = 99999, # Limit network emulation to a certain amount of packets
delay = 100000, # Additional latency in uS
jitter = 30000, # Jitter in uS
distribution = "normal",# Distribution of delay (uniform, normal, pareto, paretonormal)
loss = 10 # Loss in percentage
duplicate = 10, # Duplication in percentage
corrupt = 10, # Corruption in percentage
}
}
};
@ -29,16 +40,5 @@ paths = (
reverse = true, # Setup a path in the reverse direction too
in = "acs", # Name of the node we listen to (see above)
out = "sintef", # Name of the node we send to
# TODO: Some 'netem' settings might arrive here in the future...
# netem = {
# delay = (10, 10, # Time, jitter in milliseconds
# 10, # Correlation in percentage
# "normal") # Distribution: uniform, normal, pareto or paretonormal
# loss = (10, 25), # Loss in percentage
# duplicate = (10, 25), # Duplication in percentage
# corrupt = (10, 25), # Corruption in percentage
# reorder = (10, 25) # Reorder in percentage
# }
}
);

View file

@ -14,6 +14,8 @@ struct node;
struct path;
struct interface;
struct netem;
/** Global configuration */
struct settings {
/** Name of this node */
@ -79,9 +81,15 @@ int config_parse_path(config_setting_t *cfg,
*/
int config_parse_node(config_setting_t *cfg,
struct node **nodes, struct interface **interfaces);
/** Parse network emulator (netem) settings
*
* @param cfg A libconfig object containing the settings
* @param em A pointer to the settings
* @return
* - 0 on success
* - otherwise an error occured
*/
int config_parse_netem(config_setting_t *cfg, struct netem *em);
#endif /* _CFG_H_ */

View file

@ -18,6 +18,8 @@
#include <netinet/in.h>
#include <libconfig.h>
#include "tc.h"
/** The type of a node.
*
* This type is used to determine the message format of the remote node
@ -58,6 +60,9 @@ struct node
/** The egress interface */
struct interface *interface;
/** Network emulator settings */
struct netem *netem;
/** Socket mark for netem, routing and filtering */
int mark;

80
include/tc.h Normal file
View file

@ -0,0 +1,80 @@
/**
* Setup interface queuing desciplines for network emulation
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014, Institute for Automation of Complex Power Systems, EONERC
*/
#ifndef _TC_H_
#define _TC_H_
#include <stdint.h>
/* Some helper for TC handles */
typedef uint32_t tc_hdl_t;
#define TC_HDL(maj, min) ((maj & 0xFFFF) << 16 | (min & 0xFFFF))
#define TC_HDL_MAJ(h) ((h >> 16) & 0xFFFF)
#define TC_HDL_MIN(h) ((h >> 0) & 0xFFFF)
#define TC_HDL_ROOT (0xFFFFFFFFU)
/* Bitfield for valid fields in struct netem */
#define TC_NETEM_LIMIT (1 << 0)
#define TC_NETEM_DELAY (1 << 1)
#define TC_NETEM_JITTER (1 << 2)
#define TC_NETEM_DISTR (1 << 3)
#define TC_NETEM_LOSS (1 << 4)
#define TC_NETEM_CORRUPT (1 << 5)
#define TC_NETEM_DUPL (1 << 6)
struct interface;
struct netem {
/** Which fields of this struct contain valid data (TC_NETEM_*). */
char valid;
/** Delay distribution: uniform, normal, pareto, paretonormal */
const char *distribution;
/** Fifo limit (packets) */
int limit;
/** Added delay (uS) */
int delay;
/** Delay jitter (uS) */
int jitter;
/** Random loss probability (%) */
int loss;
/** Packet corruption probability (%) */
int corrupt;
/** Packet duplication probability (%) */
int duplicate;
};
/** Remove all queuing disciplines and filters
*
* @param i The interface
*/
int tc_reset(struct interface *i);
/** Create a prio queueing discipline
*
* @param i The interface
* @param parent
* @param handle
* @param bands
* @return
* - 0 on success
* - otherwise an error occured
*/
int tc_prio(struct interface *i, tc_hdl_t handle, int bands);
/** Add a new network emulator discipline
*
* @param i The interface
* @param parent Make this
*/
int tc_netem(struct interface *i, tc_hdl_t parent, struct netem *em);
/** Add a new fwmark filter */
int tc_mark(struct interface *i, tc_hdl_t flowid, int mark);
#endif /* _TC_H_ */

View file

@ -13,6 +13,7 @@
#include <pwd.h>
#include "if.h"
#include "tc.h"
#include "cfg.h"
#include "node.h"
#include "path.h"
@ -147,7 +148,7 @@ int config_parse_path(config_setting_t *cfg,
path_rev->in = path->out; /* Swap in/out */
path_rev->out = path->in;
list_add(*paths, path_rev);
}
}
@ -202,6 +203,13 @@ int config_parse_node(config_setting_t *cfg,
if (resolve_addr(remote_str, &node->remote, 0))
cerror(cfg, "Failed to resolve remote address '%s' of node '%s'", remote_str, node->name);
/* Optional settings */
config_setting_t *cfg_netem = config_setting_get_member(cfg, "netem");
if (cfg_netem) {
node->netem = (struct netem *) malloc(sizeof(struct netem));
config_parse_netem(cfg_netem, node->netem);
}
/* Determine outgoing interface */
int index = if_getegress(&node->remote);
struct interface *i = if_lookup_index(index, *interfaces);
@ -225,3 +233,27 @@ int config_parse_node(config_setting_t *cfg,
return 0;
}
int config_parse_netem(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, "limit", &em->limit))
em->valid |= TC_NETEM_LIMIT;
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: check values
return 0;
}

81
src/tc.c Normal file
View file

@ -0,0 +1,81 @@
/**
* Traffic control: setup interface queuing desciplines
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014, Institute for Automation of Complex Power Systems, EONERC
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "utils.h"
#include "if.h"
#include "tc.h"
int tc_reset(struct interface *i)
{
char cmd[128];
snprintf(cmd, sizeof(cmd), "tc qdisc del dev %s root", i->name);
debug(6, "system: %s", cmd);
return system(cmd);
}
int tc_prio(struct interface *i, tc_hdl_t handle, int bands)
{
char cmd[128];
int len = 0;
len += snprintf(cmd+len, sizeof(cmd)-len,
"tc qdisc add dev %s root handle %u prio bands %u priomap",
i->name, TC_HDL_MAJ(handle), bands);
for (int i = 0; i < bands; i++)
len += snprintf(cmd+len, sizeof(cmd)-len, " 0");
debug(6, "system: %s", cmd);
return system(cmd);
}
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_LIMIT)
len += snprintf(cmd+len, sizeof(cmd)-len, " limit %u", em->limit);
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);
debug(6, "system: %s", cmd);
return system(cmd);
}
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));
debug(6, "system: %s", cmd);
return system(cmd);
}