]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: tc introduce sfq - Stochastic Fairness Queueing
authorSusant Sahani <ssahani@vmware.com>
Wed, 27 Nov 2019 11:42:21 +0000 (12:42 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 4 Dec 2019 11:58:17 +0000 (20:58 +0900)
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
src/network/meson.build
src/network/networkd-network-gperf.gperf
src/network/tc/qdisc.c
src/network/tc/qdisc.h
src/network/tc/sfq.c [new file with mode: 0644]
src/network/tc/sfq.h [new file with mode: 0644]
test/fuzz/fuzz-network-parser/directives.network

index 20723bfbfa8d3523b72df0a347339caeae4f3ff6..a2ac24059a9dcc5eb9faf94c27be0735971de769 100644 (file)
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>StochasticFairnessQueueingPerturbPeriodSec=</varname></term>
+        <listitem>
+          <para>Specifies the interval in seconds for queue algorithm perturbation. Defaults to unset.</para>
+        </listitem>
+      </varlistentry>
+
     </variablelist>
   </refsect1>
 
index 3633694577097b60691dafc874029eb922614c2a..e2324a01b38006bc110e89645b767ce65ffb9bdc 100644 (file)
@@ -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
index 32c6afc49e9c931940157a5be84e55c3c73d7a4a..1bfd76ec735d4918fdc5e816e881007f4111cd06 100644 (file)
@@ -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)
index e8703399a76d0c49c726dac57f3c200928a7d869..717a0cfd38b5de12f36f938355867fc0bea3699c 100644 (file)
@@ -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)
index 4810b876006c631167f4d11d1a53afab722e1544..1d06dc53f443ff210976b90989304ddc4701b6c0 100644 (file)
@@ -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 (file)
index 0000000..393b0e1
--- /dev/null
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: LGPL-2.1+
+ * Copyright © 2019 VMware, Inc. */
+
+#include <linux/pkt_sched.h>
+
+#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 (file)
index 0000000..8c00e0e
--- /dev/null
@@ -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);
index 1cdbc07a242654f8e81f038122719c31ed82d964..2a6f111d83b65b2da47c3ef7239d1287ffb69eaa 100644 (file)
@@ -273,3 +273,4 @@ NetworkEmulatorPacketLimit=
 TokenBufferFilterRate=
 TokenBufferFilterBurst=
 TokenBufferFilterLatencySec=
+StochasticFairnessQueueingPerturbPeriodSec=