From b9c5aa3c65b5f223f79aaa0db549c0aaf2aeee25 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Wed, 30 Oct 2019 18:58:02 +0100 Subject: qdisc: netem add support to duplicate packets. using this option the chosen percent of packets is duplicated before queuing them --- man/systemd.network.xml | 8 ++++++++ src/network/networkd-network-gperf.gperf | 3 ++- src/network/tc/netem.c | 17 +++++++++++++---- src/network/tc/netem.h | 3 ++- test/fuzz/fuzz-network-parser/directives.network | 1 + 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 0d49bf9589..fb2f199ba8 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2351,6 +2351,14 @@ + + NetworkEmulatorDuplicateRate= + + Specifies that the chosen percent of packets is duplicated before queuing them. + Takes a percentage value, suffixed with "%". Defaults to unset. + + + diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 9f53385602..7fca93dccb 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -247,7 +247,8 @@ CAN.TripleSampling, config_parse_tristate, TrafficControlQueueingDiscipline.Parent, config_parse_tc_qdiscs_parent, 0, 0 TrafficControlQueueingDiscipline.NetworkEmulatorDelaySec, config_parse_tc_network_emulator_delay, 0, 0 TrafficControlQueueingDiscipline.NetworkEmulatorDelayJitterSec, config_parse_tc_network_emulator_delay, 0, 0 -TrafficControlQueueingDiscipline.NetworkEmulatorLossRate, config_parse_tc_network_emulator_loss_rate, 0, 0 +TrafficControlQueueingDiscipline.NetworkEmulatorLossRate, config_parse_tc_network_emulator_rate, 0, 0 +TrafficControlQueueingDiscipline.NetworkEmulatorDuplicateRate, config_parse_tc_network_emulator_rate, 0, 0 TrafficControlQueueingDiscipline.NetworkEmulatorPacketLimit, config_parse_tc_network_emulator_packet_limit, 0, 0 /* backwards compatibility: do not add new entries to this section */ Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) diff --git a/src/network/tc/netem.c b/src/network/tc/netem.c index e0e3e9a48e..053af3e7db 100644 --- a/src/network/tc/netem.c +++ b/src/network/tc/netem.c @@ -50,6 +50,9 @@ int network_emulator_fill_message(Link *link, QDiscs *qdisc, sd_netlink_message if (qdisc->ne.loss > 0) opt.loss = qdisc->ne.loss; + if (qdisc->ne.duplicate > 0) + opt.duplicate = qdisc->ne.duplicate; + if (qdisc->ne.delay != USEC_INFINITY) { r = tc_time_to_tick(qdisc->ne.delay, &opt.latency); if (r < 0) @@ -124,7 +127,7 @@ int config_parse_tc_network_emulator_delay( return 0; } -int config_parse_tc_network_emulator_loss_rate( +int config_parse_tc_network_emulator_rate( const char *unit, const char *filename, unsigned line, @@ -138,6 +141,7 @@ int config_parse_tc_network_emulator_loss_rate( _cleanup_(qdisc_free_or_set_invalidp) QDiscs *qdisc = NULL; Network *network = data; + uint32_t rate; int r; assert(filename); @@ -156,14 +160,19 @@ int config_parse_tc_network_emulator_loss_rate( return 0; } - r = parse_tc_percent(rvalue, &qdisc->ne.loss); + r = parse_tc_percent(rvalue, &rate); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse 'NetworkEmularorLossRate=', ignoring assignment: %s", - rvalue); + "Failed to parse '%s=', ignoring assignment: %s", + lvalue, rvalue); return 0; } + if (streq(lvalue, "NetworkEmulatorLossRate")) + qdisc->ne.loss = rate; + else if (streq(lvalue, "NetworkEmulatorDuplicateRate")) + qdisc->ne.duplicate = rate; + qdisc = NULL; return 0; } diff --git a/src/network/tc/netem.h b/src/network/tc/netem.h index 4bac44ca5a..43abf20af8 100644 --- a/src/network/tc/netem.h +++ b/src/network/tc/netem.h @@ -16,11 +16,12 @@ typedef struct NetworkEmulator { uint32_t limit; uint32_t loss; + uint32_t duplicate; } NetworkEmulator; int network_emulator_new(NetworkEmulator **ret); int network_emulator_fill_message(Link *link, QDiscs *qdisc, sd_netlink_message *req); CONFIG_PARSER_PROTOTYPE(config_parse_tc_network_emulator_delay); -CONFIG_PARSER_PROTOTYPE(config_parse_tc_network_emulator_loss_rate); +CONFIG_PARSER_PROTOTYPE(config_parse_tc_network_emulator_rate); CONFIG_PARSER_PROTOTYPE(config_parse_tc_network_emulator_packet_limit); diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 3469dd443e..a5f54610da 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -268,4 +268,5 @@ Parent= NetworkEmulatorDelaySec= NetworkEmulatorDelayJitterSec= NetworkEmulatorLossRate= +NetworkEmulatorDuplicateRate= NetworkEmulatorPacketLimit= -- cgit v1.2.1 From 6edfb1f5406f45e8f3e933c695bad3d6749ed4e0 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Wed, 30 Oct 2019 19:13:33 +0100 Subject: tc: qdisc remove some duplicate code --- src/network/tc/qdisc.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index ed4a11d265..7f4b2b53cb 100644 --- a/src/network/tc/qdisc.c +++ b/src/network/tc/qdisc.c @@ -116,6 +116,7 @@ static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int qdisc_configure(Link *link, QDiscs *qdisc) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_free_ char *tca_kind = NULL; int r; assert(link); @@ -132,25 +133,31 @@ int qdisc_configure(Link *link, QDiscs *qdisc) { return log_link_error_errno(link, r, "Could not create tcm_parent message: %m"); if (qdisc->parent == TC_H_CLSACT) { + tca_kind = strdup("clsact"); + if (!tca_kind) + return log_oom(); + r = sd_rtnl_message_set_qdisc_handle(req, TC_H_MAKE(TC_H_CLSACT, 0)); if (r < 0) return log_link_error_errno(link, r, "Could not set tcm_handle message: %m"); - - r = sd_netlink_message_append_string(req, TCA_KIND, "clsact"); - if (r < 0) - return log_link_error_errno(link, r, "Could not append TCA_KIND attribute: %m"); } if (qdisc->has_network_emulator) { - r = sd_netlink_message_append_string(req, TCA_KIND, "netem"); + r = free_and_strdup(&tca_kind, "netem"); if (r < 0) - return log_link_error_errno(link, r, "Could not append TCA_KIND attribute: %m"); + return log_oom(); r = network_emulator_fill_message(link, qdisc, req); if (r < 0) return r; } + if (tca_kind) { + r = sd_netlink_message_append_string(req, TCA_KIND, tca_kind); + if (r < 0) + return log_link_error_errno(link, r, "Could not append TCA_KIND attribute: %m"); + } + r = netlink_call_async(link->manager->rtnl, NULL, req, qdisc_handler, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); -- cgit v1.2.1