]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: tc: introduce [QuickFairQueueingClass] section
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 3 Jun 2020 06:07:45 +0000 (15:07 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 3 Jun 2020 08:25:44 +0000 (17:25 +0900)
man/systemd.network.xml
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/tc/qfq.c
src/network/tc/qfq.h
src/network/tc/tclass.c
src/network/tc/tclass.h
test/fuzz/fuzz-network-parser/directives.network

index 472172094d4203feebede9265c0837a6699588e7..a4ca67a27f79204e1e6867792441f3477013ca5a 100644 (file)
     </variablelist>
   </refsect1>
 
+  <refsect1>
+    <title>[QuickFairQueueingClass] Section Options</title>
+    <para>The <literal>[QuickFairQueueingClass]</literal> section manages the traffic control class of
+    Quick Fair Queueing (qfq).</para>
+
+    <variablelist class='network-directives'>
+      <xi:include href="tc.xml" xpointer="tclass-parent" />
+      <xi:include href="tc.xml" xpointer="tclass-classid" />
+
+      <varlistentry>
+        <term><varname>Weight=</varname></term>
+        <listitem>
+          <para>Specifies the weight of the class. Takse an integer in the range 1..1023. Defaults to
+          unset in which case the kernel default is used.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>MaxPacketSize=</varname></term>
+        <listitem>
+          <para>Specifies the maximum packet size in bytes for the class. When suffixed with K, M, or G, the specified
+          size is parsed as Kilobytes, Megabytes, or Gigabytes, respectively, to the base of 1000. When unset,
+          the kernel default is used.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
   <refsect1>
     <title>[BridgeVLAN] Section Options</title>
       <para>The <literal>[BridgeVLAN]</literal> section manages the VLAN ID configuration of a bridge port and accepts
index a27a02ca244081bc9e94c34a7be1febd529f2f13..39188906648f68e03cc632e6074150b0b993ed3b 100644 (file)
@@ -314,6 +314,10 @@ PFIFOHeadDrop.Handle,                        config_parse_qdisc_handle,
 PFIFOHeadDrop.PacketLimit,                   config_parse_pfifo_size,                                  QDISC_KIND_PFIFO_HEAD_DROP,    0
 QuickFairQueueing.Parent,                    config_parse_qdisc_parent,                                QDISC_KIND_QFQ,                0
 QuickFairQueueing.Handle,                    config_parse_qdisc_handle,                                QDISC_KIND_QFQ,                0
+QuickFairQueueingClass.Parent,               config_parse_tclass_parent,                               TCLASS_KIND_QFQ,               0
+QuickFairQueueingClass.ClassId,              config_parse_tclass_classid,                              TCLASS_KIND_QFQ,               0
+QuickFairQueueingClass.Weight,               config_parse_quick_fair_queueing_weight,                  TCLASS_KIND_QFQ,               0
+QuickFairQueueingClass.MaxPacketSize,        config_parse_quick_fair_queueing_max_packet,              TCLASS_KIND_QFQ,               0
 FairQueueing.Parent,                         config_parse_qdisc_parent,                                QDISC_KIND_FQ,                 0
 FairQueueing.Handle,                         config_parse_qdisc_handle,                                QDISC_KIND_FQ,                 0
 FairQueueing.PacketLimit,                    config_parse_fair_queueing_u32,                           QDISC_KIND_FQ,                 0
index fc8581c983d45bdc3b985fe5b77df4496262e603..b657b2401c2a68e7a12d302baaafb76aa25d8490 100644 (file)
@@ -520,6 +520,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                         "PFIFOHeadDrop\0"
                         "PIE\0"
                         "QuickFairQueueing\0"
+                        "QuickFairQueueingClass\0"
                         "StochasticFairBlue\0"
                         "StochasticFairnessQueueing\0"
                         "TokenBucketFilter\0"
index 8084cda8012bffb013bbec9eae6c42908fb3139c..71d5b15e81c75089d1182cbf28f796b84b54ada0 100644 (file)
 /* SPDX-License-Identifier: LGPL-2.1+
  * Copyright © 2020 VMware, Inc. */
 
+#include <linux/pkt_sched.h>
+
+#include "parse-util.h"
 #include "qdisc.h"
 #include "qfq.h"
+#include "string-util.h"
+
+#define QFQ_MAX_WEIGHT       (1 << 10)
+#define QFQ_MIN_MAX_PACKET   512
+#define QFQ_MAX_MAX_PACKET   (1 << 16)
 
 const QDiscVTable qfq_vtable = {
         .object_size = sizeof(QuickFairQueueing),
         .tca_kind = "qfq",
 };
+
+static int quick_fair_queueing_class_fill_message(Link *link, TClass *tclass, sd_netlink_message *req) {
+        QuickFairQueueingClass *qfq;
+        int r;
+
+        assert(link);
+        assert(tclass);
+        assert(req);
+
+        qfq = TCLASS_TO_QFQ(tclass);
+
+        r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "qfq");
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not open container TCA_OPTIONS: %m");
+
+        if (qfq->weight > 0) {
+                r = sd_netlink_message_append_u32(req, TCA_QFQ_WEIGHT, qfq->weight);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append TCA_QFQ_WEIGHT attribute: %m");
+        }
+
+        if (qfq->max_packet > 0) {
+                r = sd_netlink_message_append_u32(req, TCA_QFQ_LMAX, qfq->max_packet);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append TCA_QFQ_LMAX attribute: %m");
+        }
+
+        r = sd_netlink_message_close_container(req);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not close container TCA_OPTIONS: %m");
+        return 0;
+}
+
+int config_parse_quick_fair_queueing_weight(
+                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_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
+        QuickFairQueueingClass *qfq;
+        Network *network = data;
+        uint32_t v;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = tclass_new_static(TCLASS_KIND_QFQ, network, filename, section_line, &tclass);
+        if (r < 0)
+                return log_syntax(unit, LOG_ERR, filename, line, r,
+                                  "Failed to create traffic control class, ignoring assignment: %m");
+
+        qfq = TCLASS_TO_QFQ(tclass);
+
+        if (isempty(rvalue)) {
+                qfq->weight = 0;
+                tclass = NULL;
+                return 0;
+        }
+
+        r = safe_atou32(rvalue, &v);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse '%s=', ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        if (v == 0 || v > QFQ_MAX_WEIGHT) {
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "Invalid '%s=', ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        qfq->weight = v;
+        tclass = NULL;
+
+        return 0;
+}
+
+int config_parse_quick_fair_queueing_max_packet(
+                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_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
+        QuickFairQueueingClass *qfq;
+        Network *network = data;
+        uint64_t v;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = tclass_new_static(TCLASS_KIND_QFQ, network, filename, section_line, &tclass);
+        if (r < 0)
+                return log_syntax(unit, LOG_ERR, filename, line, r,
+                                  "Failed to create traffic control class, ignoring assignment: %m");
+
+        qfq = TCLASS_TO_QFQ(tclass);
+
+        if (isempty(rvalue)) {
+                qfq->max_packet = 0;
+                tclass = NULL;
+                return 0;
+        }
+
+        r = parse_size(rvalue, 1000, &v);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse '%s=', ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        if (v < QFQ_MIN_MAX_PACKET || v > QFQ_MAX_MAX_PACKET) {
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "Invalid '%s=', ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        qfq->max_packet = (uint32_t) v;
+        tclass = NULL;
+
+        return 0;
+}
+
+const TClassVTable qfq_tclass_vtable = {
+        .object_size = sizeof(QuickFairQueueingClass),
+        .tca_kind = "qfq",
+        .fill_message = quick_fair_queueing_class_fill_message,
+};
index aa1bad219b47210a93e63378a8dfcf68b021b020..10bab3e642d7e55a8fee3f66554a7f168e5630d4 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright © 2020 VMware, Inc. */
 #pragma once
 
+#include "conf-parser.h"
 #include "qdisc.h"
 
 typedef struct QuickFairQueueing {
@@ -10,3 +11,16 @@ typedef struct QuickFairQueueing {
 
 DEFINE_QDISC_CAST(QFQ, QuickFairQueueing);
 extern const QDiscVTable qfq_vtable;
+
+typedef struct QuickFairQueueingClass {
+        TClass meta;
+
+        uint32_t weight;
+        uint32_t max_packet;
+} QuickFairQueueingClass;
+
+DEFINE_TCLASS_CAST(QFQ, QuickFairQueueingClass);
+extern const TClassVTable qfq_tclass_vtable;
+
+CONFIG_PARSER_PROTOTYPE(config_parse_quick_fair_queueing_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_quick_fair_queueing_max_packet);
index 219ffa2ea6f7dd962fbb088d8add3df5d94c50a2..4f75e1b42dcdb740d15eaaf13f91934369a78b76 100644 (file)
@@ -18,6 +18,7 @@
 const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX] = {
         [TCLASS_KIND_DRR] = &drr_tclass_vtable,
         [TCLASS_KIND_HTB] = &htb_tclass_vtable,
+        [TCLASS_KIND_QFQ] = &qfq_tclass_vtable,
 };
 
 static int tclass_new(TClassKind kind, TClass **ret) {
index 217dbfe001725ef3ec9b3085b156b3e4d995b14f..dc6886ac3febe61b81cf943b3df855f99ff821d8 100644 (file)
@@ -11,6 +11,7 @@
 typedef enum TClassKind {
         TCLASS_KIND_DRR,
         TCLASS_KIND_HTB,
+        TCLASS_KIND_QFQ,
         _TCLASS_KIND_MAX,
         _TCLASS_KIND_INVALID = -1,
 } TClassKind;
@@ -67,3 +68,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_tclass_classid);
 
 #include "drr.h"
 #include "htb.h"
+#include "qfq.h"
index f5c6d472962f152ab9af26c4d89b7a220045992d..7cade0e9edc297132c4ff42de6da06f76d338d6a 100644 (file)
@@ -414,6 +414,11 @@ PacketLimit=
 [QuickFairQueueing]
 Parent=
 Handle=
+[QuickFairQueueingClass]
+Parent=
+ClassId=
+Weight=
+MaxPacketSize=
 [DeficitRoundRobinScheduler]
 Parent=
 Handle=