summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2019-11-01 11:44:10 +0900
committerGitHub <noreply@github.com>2019-11-01 11:44:10 +0900
commitaab64de2818ece365e3c89e8fed6cf80377be01c (patch)
tree0d12566db096ffa0022ec837ba5db2641807e229
parent0cc9e972ff7a90ad0640b14039d48136489694c0 (diff)
parent6edfb1f5406f45e8f3e933c695bad3d6749ed4e0 (diff)
downloadsystemd-aab64de2818ece365e3c89e8fed6cf80377be01c.tar.gz
Merge pull request #13888 from ssahani/qdisc
tc qdisc: netem add support to duplicate packets.
-rw-r--r--man/systemd.network.xml8
-rw-r--r--src/network/networkd-network-gperf.gperf3
-rw-r--r--src/network/tc/netem.c17
-rw-r--r--src/network/tc/netem.h3
-rw-r--r--src/network/tc/qdisc.c19
-rw-r--r--test/fuzz/fuzz-network-parser/directives.network1
6 files changed, 39 insertions, 12 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 @@
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>NetworkEmulatorDuplicateRate=</varname></term>
+ <listitem>
+ <para>Specifies that the chosen percent of packets is duplicated before queuing them.
+ Takes a percentage value, suffixed with "%". Defaults to unset.</para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
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/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");
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=