]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: tc-cake: add support to specify ACK filter
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 17 Nov 2022 09:27:57 +0000 (18:27 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 18 Nov 2022 22:08:22 +0000 (07:08 +0900)
man/systemd.network.xml
src/network/networkd-network-gperf.gperf
src/network/tc/cake.c
src/network/tc/cake.h

index 3b33159c04cb4710b1c0484d2a995ae443e513db..6a7ab696a38e1df86ddbb9581fb115af1daa1ea3 100644 (file)
@@ -4036,6 +4036,17 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>AckFilter=</varname></term>
+        <listitem>
+          <para>Takes a boolean value, or special value <literal>aggressive</literal>. If enabled, ACKs in
+          each flow are queued and redundant ACKs to the upstream are dropped. If yes, the filter will always
+          keep at least two redundant ACKs in the queue, while in <literal>aggressive</literal> mode, it will
+          filter down to a single ACK. This may improve download throughput on links with very asymmetrical
+          rate limits. Defaults to unset, and the kernel's default will be used.</para>
+        </listitem>
+      </varlistentry>
+
     </variablelist>
   </refsect1>
 
index 00255b46a677b50842814e34f99155808a02758a..762eef5b915332b2ad5be386a44a348a66caddcc 100644 (file)
@@ -421,6 +421,7 @@ CAKE.FirewallMark,                           config_parse_cake_fwmark,
 CAKE.Wash,                                   config_parse_cake_tristate,                               QDISC_KIND_CAKE,               0
 CAKE.SplitGSO,                               config_parse_cake_tristate,                               QDISC_KIND_CAKE,               0
 CAKE.RTTSec,                                 config_parse_cake_rtt,                                    QDISC_KIND_CAKE,               0
+CAKE.AckFilter,                              config_parse_cake_ack_filter,                             QDISC_KIND_CAKE,               0
 ControlledDelay.Parent,                      config_parse_qdisc_parent,                                QDISC_KIND_CODEL,              0
 ControlledDelay.Handle,                      config_parse_qdisc_handle,                                QDISC_KIND_CODEL,              0
 ControlledDelay.PacketLimit,                 config_parse_controlled_delay_u32,                        QDISC_KIND_CODEL,              0
index c056ec9e0485c1711dcbbe815204309bc24ae18f..a22a11cce3be61b7dfd2436ac418fc71cc5fe5f8 100644 (file)
@@ -27,6 +27,7 @@ static int cake_init(QDisc *qdisc) {
         c->preset = _CAKE_PRESET_INVALID;
         c->wash = -1;
         c->split_gso = -1;
+        c->ack_filter = _CAKE_ACK_FILTER_INVALID;
 
         return 0;
 }
@@ -124,6 +125,12 @@ static int cake_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req)
                         return r;
         }
 
+        if (c->ack_filter >= 0) {
+                r = sd_netlink_message_append_u32(req, TCA_CAKE_ACK_FILTER, c->ack_filter);
+                if (r < 0)
+                        return r;
+        }
+
         r = sd_netlink_message_close_container(req);
         if (r < 0)
                 return r;
@@ -669,6 +676,66 @@ int config_parse_cake_rtt(
         return 0;
 }
 
+static const char * const cake_ack_filter_table[_CAKE_ACK_FILTER_MAX] = {
+        [CAKE_ACK_FILTER_NO]         = "no",
+        [CAKE_ACK_FILTER_YES]        = "yes",
+        [CAKE_ACK_FILTER_AGGRESSIVE] = "aggressive",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(cake_ack_filter, CakeAckFilter, CAKE_ACK_FILTER_YES);
+
+int config_parse_cake_ack_filter(
+                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;
+        CommonApplicationsKeptEnhanced *c;
+        CakeAckFilter ack_filter;
+        Network *network = ASSERT_PTR(data);
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        r = qdisc_new_static(QDISC_KIND_CAKE, network, filename, section_line, &qdisc);
+        if (r == -ENOMEM)
+                return log_oom();
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "More than one kind of queueing discipline, ignoring assignment: %m");
+                return 0;
+        }
+
+        c = CAKE(qdisc);
+
+        if (isempty(rvalue)) {
+                c->ack_filter = _CAKE_ACK_FILTER_INVALID;
+                TAKE_PTR(qdisc);
+                return 0;
+        }
+
+        ack_filter = cake_ack_filter_from_string(rvalue);
+        if (ack_filter < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, ack_filter,
+                           "Failed to parse '%s=', ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        c->ack_filter = ack_filter;
+        TAKE_PTR(qdisc);
+        return 0;
+}
+
 const QDiscVTable cake_vtable = {
         .object_size = sizeof(CommonApplicationsKeptEnhanced),
         .tca_kind = "cake",
index 418d9744a35336930c99f54ec152eaf40fe864b5..5ca6dc6470fccd9cc47ab2921a82c4803363041a 100644 (file)
@@ -38,6 +38,14 @@ typedef enum CakePriorityQueueingPreset {
         _CAKE_PRESET_INVALID = -EINVAL,
 } CakePriorityQueueingPreset;
 
+typedef enum CakeAckFilter {
+        CAKE_ACK_FILTER_NO         = CAKE_ACK_NONE,
+        CAKE_ACK_FILTER_YES        = CAKE_ACK_FILTER,
+        CAKE_ACK_FILTER_AGGRESSIVE = CAKE_ACK_AGGRESSIVE,
+        _CAKE_ACK_FILTER_MAX,
+        _CAKE_ACK_FILTER_INVALID   = -EINVAL,
+} CakeAckFilter;
+
 typedef struct CommonApplicationsKeptEnhanced {
         QDisc meta;
 
@@ -64,6 +72,7 @@ typedef struct CommonApplicationsKeptEnhanced {
         int wash;
         int split_gso;
         usec_t rtt;
+        CakeAckFilter ack_filter;
 } CommonApplicationsKeptEnhanced;
 
 DEFINE_QDISC_CAST(CAKE, CommonApplicationsKeptEnhanced);
@@ -78,3 +87,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_cake_flow_isolation_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_cake_priority_queueing_preset);
 CONFIG_PARSER_PROTOTYPE(config_parse_cake_fwmark);
 CONFIG_PARSER_PROTOTYPE(config_parse_cake_rtt);
+CONFIG_PARSER_PROTOTYPE(config_parse_cake_ack_filter);