From 9942b71089aa0c71d67d876dbb9355891d222574 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Wed, 27 Nov 2019 12:42:21 +0100 Subject: [PATCH] network: tc introduce sfq - Stochastic Fairness Queueing Stochastic Fairness Queueing is a classless queueing discipline. SFQ does not shape traffic but only schedules the transmission of packets, based on 'flows'. The goal is to ensure fairness so that each flow is able to send data in turn, thus preventing any single flow from drowning out the rest. --- man/systemd.network.xml | 7 ++ src/network/meson.build | 2 + src/network/networkd-network-gperf.gperf | 19 ++-- src/network/tc/qdisc.c | 10 +++ src/network/tc/qdisc.h | 3 + src/network/tc/sfq.c | 87 +++++++++++++++++++ src/network/tc/sfq.h | 17 ++++ .../fuzz-network-parser/directives.network | 1 + 8 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 src/network/tc/sfq.c create mode 100644 src/network/tc/sfq.h diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 20723bfbfa..a2ac24059a 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2395,6 +2395,13 @@ + + StochasticFairnessQueueingPerturbPeriodSec= + + Specifies the interval in seconds for queue algorithm perturbation. Defaults to unset. + + + diff --git a/src/network/meson.build b/src/network/meson.build index 3633694577..e2324a01b3 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -109,6 +109,8 @@ sources = files(''' tc/netem.h tc/qdisc.c tc/qdisc.h + tc/sfq.c + tc/sfq.h tc/tbf.c tc/tbf.h tc/tc-util.c diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 32c6afc49e..1bfd76ec73 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -244,15 +244,16 @@ CAN.BitRate, config_parse_si_size, CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point) CAN.RestartSec, config_parse_sec, 0, offsetof(Network, can_restart_us) CAN.TripleSampling, config_parse_tristate, 0, offsetof(Network, can_triple_sampling) -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_rate, 0, 0 -TrafficControlQueueingDiscipline.NetworkEmulatorDuplicateRate, config_parse_tc_network_emulator_rate, 0, 0 -TrafficControlQueueingDiscipline.NetworkEmulatorPacketLimit, config_parse_tc_network_emulator_packet_limit, 0, 0 -TrafficControlQueueingDiscipline.TokenBufferFilterRate, config_parse_tc_token_buffer_filter_size, 0, 0 -TrafficControlQueueingDiscipline.TokenBufferFilterBurst, config_parse_tc_token_buffer_filter_size, 0, 0 -TrafficControlQueueingDiscipline.TokenBufferFilterLatencySec, config_parse_tc_token_buffer_filter_latency, 0, 0 +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_rate, 0, 0 +TrafficControlQueueingDiscipline.NetworkEmulatorDuplicateRate, config_parse_tc_network_emulator_rate, 0, 0 +TrafficControlQueueingDiscipline.NetworkEmulatorPacketLimit, config_parse_tc_network_emulator_packet_limit, 0, 0 +TrafficControlQueueingDiscipline.TokenBufferFilterRate, config_parse_tc_token_buffer_filter_size, 0, 0 +TrafficControlQueueingDiscipline.TokenBufferFilterBurst, config_parse_tc_token_buffer_filter_size, 0, 0 +TrafficControlQueueingDiscipline.TokenBufferFilterLatencySec, config_parse_tc_token_buffer_filter_latency, 0, 0 +TrafficControlQueueingDiscipline.StochasticFairnessQueueingPerturbPeriodSec, config_parse_tc_stochastic_fairness_queueing_perturb_period, 0, 0 /* backwards compatibility: do not add new entries to this section */ Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index e8703399a7..717a0cfd38 100644 --- a/src/network/tc/qdisc.c +++ b/src/network/tc/qdisc.c @@ -161,6 +161,16 @@ int qdisc_configure(Link *link, QDisc *qdisc) { return r; } + if (qdisc->has_stochastic_fairness_queueing) { + r = free_and_strdup(&tca_kind, "sfq"); + if (r < 0) + return log_oom(); + + r = stochastic_fairness_queueing_fill_message(link, &qdisc->sfq, req); + if (r < 0) + return r; + } + if (tca_kind) { r = sd_netlink_message_append_string(req, TCA_KIND, tca_kind); if (r < 0) diff --git a/src/network/tc/qdisc.h b/src/network/tc/qdisc.h index 4810b87600..1d06dc53f4 100644 --- a/src/network/tc/qdisc.h +++ b/src/network/tc/qdisc.h @@ -7,6 +7,7 @@ #include "networkd-link.h" #include "networkd-network.h" #include "networkd-util.h" +#include "sfq.h" #include "tbf.h" typedef struct QDisc { @@ -22,9 +23,11 @@ typedef struct QDisc { bool has_network_emulator:1; bool has_token_buffer_filter:1; + bool has_stochastic_fairness_queueing:1; NetworkEmulator ne; TokenBufferFilter tbf; + StochasticFairnessQueueing sfq; } QDisc; void qdisc_free(QDisc *qdisc); diff --git a/src/network/tc/sfq.c b/src/network/tc/sfq.c new file mode 100644 index 0000000000..393b0e12e1 --- /dev/null +++ b/src/network/tc/sfq.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * Copyright © 2019 VMware, Inc. */ + +#include + +#include "alloc-util.h" +#include "conf-parser.h" +#include "netlink-util.h" +#include "parse-util.h" +#include "qdisc.h" +#include "sfq.h" +#include "string-util.h" + +int stochastic_fairness_queueing_new(StochasticFairnessQueueing **ret) { + StochasticFairnessQueueing *sfq = NULL; + + sfq = new0(StochasticFairnessQueueing, 1); + if (!sfq) + return -ENOMEM; + + *ret = TAKE_PTR(sfq); + + return 0; +} + +int stochastic_fairness_queueing_fill_message(Link *link, const StochasticFairnessQueueing *sfq, sd_netlink_message *req) { + struct tc_sfq_qopt_v1 opt = {}; + int r; + + assert(link); + assert(sfq); + assert(req); + + opt.v0.perturb_period = sfq->perturb_period / USEC_PER_SEC; + + r = sd_netlink_message_append_data(req, TCA_OPTIONS, &opt, sizeof(struct tc_sfq_qopt_v1)); + if (r < 0) + return log_link_error_errno(link, r, "Could not append TCA_OPTIONS attribute: %m"); + + return 0; +} + +int config_parse_tc_stochastic_fairness_queueing_perturb_period( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL; + Network *network = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = qdisc_new_static(network, filename, section_line, &qdisc); + if (r < 0) + return r; + + if (isempty(rvalue)) { + qdisc->sfq.perturb_period = 0; + + qdisc = NULL; + return 0; + } + + r = parse_sec(rvalue, &qdisc->sfq.perturb_period); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse '%s=', ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + qdisc->has_stochastic_fairness_queueing = true; + qdisc = NULL; + + return 0; +} diff --git a/src/network/tc/sfq.h b/src/network/tc/sfq.h new file mode 100644 index 0000000000..8c00e0e713 --- /dev/null +++ b/src/network/tc/sfq.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * Copyright © 2019 VMware, Inc. */ +#pragma once + +#include "sd-netlink.h" + +#include "conf-parser.h" +#include "networkd-link.h" + +typedef struct StochasticFairnessQueueing { + usec_t perturb_period; +} StochasticFairnessQueueing; + +int stochastic_fairness_queueing_new(StochasticFairnessQueueing **ret); +int stochastic_fairness_queueing_fill_message(Link *link, const StochasticFairnessQueueing *sfq, sd_netlink_message *req); + +CONFIG_PARSER_PROTOTYPE(config_parse_tc_stochastic_fairness_queueing_perturb_period); diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 1cdbc07a24..2a6f111d83 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -273,3 +273,4 @@ NetworkEmulatorPacketLimit= TokenBufferFilterRate= TokenBufferFilterBurst= TokenBufferFilterLatencySec= +StochasticFairnessQueueingPerturbPeriodSec= -- 2.25.1