]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: add more settings for CoDel
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 28 Dec 2019 13:07:24 +0000 (22:07 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 28 Dec 2019 13:25:12 +0000 (22:25 +0900)
man/systemd.network.xml
src/libsystemd/sd-netlink/netlink-types.c
src/network/networkd-network-gperf.gperf
src/network/tc/codel.c
src/network/tc/codel.h
test/fuzz/fuzz-network-parser/directives.network

index 0549c02968a41ed59ac650914d93dae12e514134..e7e166a9c7a1f4725f153bcf969068428be3882c 100644 (file)
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>ControlledDelayTargetSec=</varname></term>
+        <listitem>
+          <para>Takes a timespan. Specifies the acceptable minimum standing/persistent queue delay.
+          Defaults to unset and kernel's default is used.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>ControlledDelayIntervalSec=</varname></term>
+        <listitem>
+          <para>Takes a timespan. This is used to ensure that the measured minimum delay does not
+          become too stale. Defaults to unset and kernel's default is used.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>ControlledDelayECN=</varname></term>
+        <listitem>
+          <para>Takes a boolean. This can be used to mark packets instead of dropping them. Defaults to
+          unset and kernel's default is used.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>ControlledDelayCEThresholdSec=</varname></term>
+        <listitem>
+          <para>Takes a timespan. This sets a threshold above which all packets are marked with ECN
+          Congestion Experienced (CE). Defaults to unset and kernel's default is used.</para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>FairQueuingControlledDelayPacketLimit=</varname></term>
         <listitem>
index 14a7138fb808ca5c687cf1b0ddf239fc405118a1..e35127a4cd2ed97526cc3d1b5898dc722afa62dd 100644 (file)
@@ -746,7 +746,11 @@ static const NLTypeSystem rtnl_nexthop_type_system = {
 };
 
 static const NLType rtnl_tca_option_data_codel_types[] = {
-        [TCA_CODEL_LIMIT]            = { .type = NETLINK_TYPE_U32 },
+        [TCA_CODEL_TARGET]        = { .type = NETLINK_TYPE_U32 },
+        [TCA_CODEL_LIMIT]         = { .type = NETLINK_TYPE_U32 },
+        [TCA_CODEL_INTERVAL]      = { .type = NETLINK_TYPE_U32 },
+        [TCA_CODEL_ECN]           = { .type = NETLINK_TYPE_U32 },
+        [TCA_CODEL_CE_THRESHOLD]  = { .type = NETLINK_TYPE_U32 },
 };
 
 static const NLType rtnl_tca_option_data_fq_types[] = {
index 4912b5e8149816a348d45a8e7bf3dcd60484eeb9..06dca18cb76bd623d1984a67aa9c0986ad54d6be 100644 (file)
@@ -279,6 +279,10 @@ TrafficControlQueueingDiscipline.FairQueueTrafficPolicingOrphanMask,         con
 TrafficControlQueueingDiscipline.FairQueueTrafficPolicingPacing,             config_parse_tc_fair_queue_traffic_policing_bool,            0, 0
 TrafficControlQueueingDiscipline.FairQueueTrafficPolicingCEThresholdSec,     config_parse_tc_fair_queue_traffic_policing_usec,            0, 0
 TrafficControlQueueingDiscipline.ControlledDelayPacketLimit,                 config_parse_tc_controlled_delay_u32,                        0, 0
+TrafficControlQueueingDiscipline.ControlledDelayTargetSec,                   config_parse_tc_controlled_delay_usec,                       0, 0
+TrafficControlQueueingDiscipline.ControlledDelayIntervalSec,                 config_parse_tc_controlled_delay_usec,                       0, 0
+TrafficControlQueueingDiscipline.ControlledDelayCEThresholdSec,              config_parse_tc_controlled_delay_usec,                       0, 0
+TrafficControlQueueingDiscipline.ControlledDelayECN,                         config_parse_tc_controlled_delay_bool,                       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 20ac5db949cc72ec8cc61053048913c5b220c352..24b5720c41c4876955b861be9d80a4f2c290c472 100644 (file)
 #include "qdisc.h"
 #include "string-util.h"
 
+static int controlled_delay_init(QDisc *qdisc) {
+        ControlledDelay *cd;
+
+        assert(qdisc);
+
+        cd = CODEL(qdisc);
+
+        cd->ce_threshold_usec = USEC_INFINITY;
+        cd->ecn = -1;
+
+        return 0;
+}
+
 static int controlled_delay_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
         ControlledDelay *cd;
         int r;
@@ -30,6 +43,30 @@ static int controlled_delay_fill_message(Link *link, QDisc *qdisc, sd_netlink_me
                         return log_link_error_errno(link, r, "Could not append TCA_CODEL_LIMIT attribute: %m");
         }
 
+        if (cd->interval_usec > 0) {
+                r = sd_netlink_message_append_u32(req, TCA_CODEL_INTERVAL, cd->interval_usec);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append TCA_CODEL_INTERVAL attribute: %m");
+        }
+
+        if (cd->target_usec > 0) {
+                r = sd_netlink_message_append_u32(req, TCA_CODEL_TARGET, cd->target_usec);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append TCA_CODEL_TARGET attribute: %m");
+        }
+
+        if (cd->ecn >= 0) {
+                r = sd_netlink_message_append_u32(req, TCA_CODEL_ECN, cd->ecn);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append TCA_CODEL_ECN attribute: %m");
+        }
+
+        if (cd->ce_threshold_usec != USEC_INFINITY) {
+                r = sd_netlink_message_append_u32(req, TCA_CODEL_CE_THRESHOLD, cd->ce_threshold_usec);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append TCA_CODEL_CE_THRESHOLD 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");
@@ -88,8 +125,125 @@ int config_parse_tc_controlled_delay_u32(
         return 0;
 }
 
+int config_parse_tc_controlled_delay_usec(
+                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;
+        ControlledDelay *cd;
+        Network *network = data;
+        usec_t *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = qdisc_new_static(QDISC_KIND_CODEL, network, filename, section_line, &qdisc);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0)
+                return log_syntax(unit, LOG_ERR, filename, line, r,
+                                  "More than one kind of queueing discipline, ignoring assignment: %m");
+
+        cd = CODEL(qdisc);
+
+        if (streq(lvalue, "ControlledDelayTargetSec"))
+                p = &cd->target_usec;
+        else if (streq(lvalue, "ControlledDelayIntervalSec"))
+                p = &cd->interval_usec;
+        else if (streq(lvalue, "ControlledDelayCEThresholdSec"))
+                p = &cd->ce_threshold_usec;
+        else
+                assert_not_reached("Invalid lvalue");
+
+        if (isempty(rvalue)) {
+                if (streq(lvalue, "ControlledDelayCEThresholdSec"))
+                        *p = USEC_INFINITY;
+                else
+                        *p = 0;
+
+                qdisc = NULL;
+                return 0;
+        }
+
+        r = parse_sec(rvalue, p);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse '%s=', ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        qdisc = NULL;
+
+        return 0;
+}
+
+int config_parse_tc_controlled_delay_bool(
+                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;
+        ControlledDelay *cd;
+        Network *network = data;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = qdisc_new_static(QDISC_KIND_CODEL, network, filename, section_line, &qdisc);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0)
+                return log_syntax(unit, LOG_ERR, filename, line, r,
+                                  "More than one kind of queueing discipline, ignoring assignment: %m");
+
+        cd = CODEL(qdisc);
+
+        if (isempty(rvalue)) {
+                cd->ecn = -1;
+
+                qdisc = NULL;
+                return 0;
+        }
+
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse '%s=', ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        cd->ecn = r;
+        qdisc = NULL;
+
+        return 0;
+}
+
 const QDiscVTable codel_vtable = {
         .object_size = sizeof(ControlledDelay),
         .tca_kind = "codel",
+        .init = controlled_delay_init,
         .fill_message = controlled_delay_fill_message,
 };
index bd8158f0dfedf5359da1d1f46e2fa20871277f22..075423dec14f7ca5b8a2ed3cea245c901bfcbfa6 100644 (file)
@@ -10,10 +10,15 @@ typedef struct ControlledDelay {
         QDisc meta;
 
         uint32_t packet_limit;
-
+        usec_t interval_usec;
+        usec_t target_usec;
+        usec_t ce_threshold_usec;
+        int ecn;
 } ControlledDelay;
 
 DEFINE_QDISC_CAST(CODEL, ControlledDelay);
 extern const QDiscVTable codel_vtable;
 
 CONFIG_PARSER_PROTOTYPE(config_parse_tc_controlled_delay_u32);
+CONFIG_PARSER_PROTOTYPE(config_parse_tc_controlled_delay_usec);
+CONFIG_PARSER_PROTOTYPE(config_parse_tc_controlled_delay_bool);
index 6c306d6dd5dc4ecbe903571a6039da05347fb234..c8cb7d52f73c12c430c6e1e933cf6b320b0f15b6 100644 (file)
@@ -299,3 +299,7 @@ FairQueueTrafficPolicingOrphanMask=
 FairQueueTrafficPolicingPacing=
 FairQueueTrafficPolicingCEThresholdSec=
 ControlledDelayPacketLimit=
+ControlledDelayTargetSec=
+ControlledDelayIntervalSec=
+ControlledDelayCEThresholdSec=
+ControlledDelayECN=