network: tc/cake: introduce FlowIsolationMode= setting
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 2 Nov 2021 20:48:15 +0000 (05:48 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 9 Nov 2021 01:58:44 +0000 (10:58 +0900)
man/systemd.network.xml
src/network/networkd-network-gperf.gperf
src/network/tc/cake.c
src/network/tc/cake.h
test/fuzz/fuzz-network-parser/directives.network

index 9a8d13d6c59a148a424c5f95f5d254d9b2e41130..c13b5fed4b5e0246b09f551e4f9ab4c2f3511a78 100644 (file)
@@ -3503,6 +3503,90 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>FlowIsolationMode=</varname></term>
+        <listitem>
+          <para>CAKE places packets from different flows into different queues, then packets from each
+          queue are delivered fairly. This specifies whether the fairness is based on source address,
+          destination address, individual flows, or any combination of those. The available values are:
+          </para>
+
+          <variablelist>
+            <varlistentry>
+              <term><option>none</option></term>
+              <listitem><para>
+                The flow isolation is disabled, and all traffic passes through a single queue.
+              </para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><option>src-host</option></term>
+              <listitem><para>
+                Flows are defined only by source address. Equivalnet to the <literal>srchost</literal>
+                option for <command>tc qdisc</command> command. See also
+                <citerefentry project='man-pages'><refentrytitle>tc-cake</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+              </para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><option>dst-host</option></term>
+              <listitem><para>
+                Flows are defined only by destination address. Equivalnet to the
+                <literal>srchost</literal> option for <command>tc qdisc</command> command. See also
+                <citerefentry project='man-pages'><refentrytitle>tc-cake</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+              </para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><option>hosts</option></term>
+              <listitem><para>
+                Flows are defined by source-destination host pairs. Equivalent to the same option for
+                <command>tc qdisc</command> command. See also
+                <citerefentry project='man-pages'><refentrytitle>tc-cake</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+              </para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><option>flows</option></term>
+              <listitem><para>
+                Flows are defined by the entire 5-tuple of source address, destination address,
+                transport protocol, source port and destination port. Equivalent to the same option for
+                <command>tc qdisc</command> command. See also
+                <citerefentry project='man-pages'><refentrytitle>tc-cake</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+              </para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><option>dual-src-host</option></term>
+              <listitem><para>
+                Flows are defined by the 5-tuple (see <literal>flows</literal> in the above), and
+                fairness is applied first over source addresses, then over individual flows. Equivalnet
+                to the <literal>dual-srchost</literal> option for <command>tc qdisc</command> command.
+                See also
+                <citerefentry project='man-pages'><refentrytitle>tc-cake</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+              </para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><option>dual-dst-host</option></term>
+              <listitem><para>
+                Flows are defined by the 5-tuple (see <literal>flows</literal> in the above), and
+                fairness is applied first over destination addresses, then over individual flows.
+                Equivalnet to the <literal>dual-dsthost</literal> option for
+                <command>tc qdisc</command> command. See also
+                <citerefentry project='man-pages'><refentrytitle>tc-cake</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+              </para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term><option>triple</option></term>
+              <listitem><para>
+                Flows are defined by the 5-tuple (see <literal>flows</literal>), and fairness is
+                applied over source and destination addresses, and also over individual flows.
+                Equivalnet to the <literal>triple-isolate</literal> option for
+                <command>tc qdisc</command> command. See also
+                <citerefentry project='man-pages'><refentrytitle>tc-cake</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+              </para></listitem>
+            </varlistentry>
+          </variablelist>
+
+          <para>Defaults to unset and the kernel's default is used.</para>
+        </listitem>
+      </varlistentry>
+
     </variablelist>
   </refsect1>
 
index 2d0e1f833fbd8d3df03547a5d5915c04b5ee6377..eaef3ec03fb7905e28858ab192a8f6aed1b3ebe0 100644 (file)
@@ -389,6 +389,7 @@ CAKE.Bandwidth,                              config_parse_cake_bandwidth,
 CAKE.AutoRateIngress,                        config_parse_cake_tristate,                               QDISC_KIND_CAKE,               0
 CAKE.OverheadBytes,                          config_parse_cake_overhead,                               QDISC_KIND_CAKE,               0
 CAKE.CompensationMode,                       config_parse_cake_compensation_mode,                      QDISC_KIND_CAKE,               0
+CAKE.FlowIsolationMode,                      config_parse_cake_flow_isolation_mode,                    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 fe007c00fdbf0c8dfa072c6bbff53df27e9d79af..39280ff6c8711e32358c6cc5b206e6626cc0f111 100644 (file)
@@ -21,6 +21,7 @@ static int cake_init(QDisc *qdisc) {
 
         c->autorate = -1;
         c->compensation_mode = _CAKE_COMPENSATION_MODE_INVALID;
+        c->flow_isolation_mode = _CAKE_FLOW_ISOLATION_MODE_INVALID;
 
         return 0;
 }
@@ -63,6 +64,12 @@ static int cake_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req)
                         return log_link_error_errno(link, r, "Could not append TCA_CAKE_ATM attribute: %m");
         }
 
+        if (c->flow_isolation_mode >= 0) {
+                r = sd_netlink_message_append_u32(req, TCA_CAKE_FLOW_MODE, c->flow_isolation_mode);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append TCA_CAKE_FLOW_MODE 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");
@@ -303,6 +310,72 @@ int config_parse_cake_compensation_mode(
         return 0;
 }
 
+static const char * const cake_flow_isolation_mode_table[_CAKE_FLOW_ISOLATION_MODE_MAX] = {
+        [CAKE_FLOW_ISOLATION_MODE_NONE]     = "none",
+        [CAKE_FLOW_ISOLATION_MODE_SRC_IP]   = "src-host",
+        [CAKE_FLOW_ISOLATION_MODE_DST_IP]   = "dst-host",
+        [CAKE_FLOW_ISOLATION_MODE_HOSTS]    = "hosts",
+        [CAKE_FLOW_ISOLATION_MODE_FLOWS]    = "flows",
+        [CAKE_FLOW_ISOLATION_MODE_DUAL_SRC] = "dual-src-host",
+        [CAKE_FLOW_ISOLATION_MODE_DUAL_DST] = "dual-dst-host",
+        [CAKE_FLOW_ISOLATION_MODE_TRIPLE]   = "triple",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(cake_flow_isolation_mode, CakeFlowIsolationMode);
+
+int config_parse_cake_flow_isolation_mode(
+                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;
+        Network *network = data;
+        CakeFlowIsolationMode mode;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        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->flow_isolation_mode = _CAKE_FLOW_ISOLATION_MODE_INVALID;
+                TAKE_PTR(qdisc);
+                return 0;
+        }
+
+        mode = cake_flow_isolation_mode_from_string(rvalue);
+        if (mode < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, mode,
+                           "Failed to parse '%s=', ignoring assignment: %s",
+                           lvalue, rvalue);
+                return 0;
+        }
+
+        c->flow_isolation_mode = mode;
+        TAKE_PTR(qdisc);
+        return 0;
+}
+
 const QDiscVTable cake_vtable = {
         .object_size = sizeof(CommonApplicationsKeptEnhanced),
         .tca_kind = "cake",
index 549b4e3c808ffd2e0e63bfb4599859093c3fbb46..9272357df7fe9b033c1907cd153f49a4e2c3dcb5 100644 (file)
@@ -15,6 +15,19 @@ typedef enum CakeCompensationMode {
         _CAKE_COMPENSATION_MODE_INVALID = -EINVAL,
 } CakeCompensationMode;
 
+typedef enum CakeFlowIsolationMode {
+        CAKE_FLOW_ISOLATION_MODE_NONE     = CAKE_FLOW_NONE,
+        CAKE_FLOW_ISOLATION_MODE_SRC_IP   = CAKE_FLOW_SRC_IP,
+        CAKE_FLOW_ISOLATION_MODE_DST_IP   = CAKE_FLOW_DST_IP,
+        CAKE_FLOW_ISOLATION_MODE_HOSTS    = CAKE_FLOW_HOSTS,
+        CAKE_FLOW_ISOLATION_MODE_FLOWS    = CAKE_FLOW_FLOWS,
+        CAKE_FLOW_ISOLATION_MODE_DUAL_SRC = CAKE_FLOW_DUAL_SRC,
+        CAKE_FLOW_ISOLATION_MODE_DUAL_DST = CAKE_FLOW_DUAL_DST,
+        CAKE_FLOW_ISOLATION_MODE_TRIPLE   = CAKE_FLOW_TRIPLE,
+        _CAKE_FLOW_ISOLATION_MODE_MAX,
+        _CAKE_FLOW_ISOLATION_MODE_INVALID = -EINVAL,
+} CakeFlowIsolationMode;
+
 typedef struct CommonApplicationsKeptEnhanced {
         QDisc meta;
 
@@ -27,6 +40,9 @@ typedef struct CommonApplicationsKeptEnhanced {
         int overhead;
         CakeCompensationMode compensation_mode;
 
+        /* Flow isolation parameters */
+        CakeFlowIsolationMode flow_isolation_mode;
+
 } CommonApplicationsKeptEnhanced;
 
 DEFINE_QDISC_CAST(CAKE, CommonApplicationsKeptEnhanced);
@@ -36,3 +52,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_cake_bandwidth);
 CONFIG_PARSER_PROTOTYPE(config_parse_cake_overhead);
 CONFIG_PARSER_PROTOTYPE(config_parse_cake_tristate);
 CONFIG_PARSER_PROTOTYPE(config_parse_cake_compensation_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_cake_flow_isolation_mode);
index 79ca97c90b0c597ef32b6449e1ba0e50cd5dc6c7..b0db8d88d1ce3ed65322f6234ba1f2873fe52150 100644 (file)
@@ -471,6 +471,7 @@ Bandwidth=
 AutoRateIngress=
 OverheadBytes=
 CompensationMode=
+FlowIsolationMode=
 [TrafficControlQueueingDiscipline]
 Parent=
 NetworkEmulatorDelaySec=