1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-10 01:17:44 +03:00

Merge pull request #21226 from yuwata/network-tc-cake

network: add several CAKE settings
This commit is contained in:
Yu Watanabe 2021-11-09 14:18:41 +09:00 committed by GitHub
commit e5a7570188
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 820 additions and 33 deletions

View File

@ -1150,7 +1150,7 @@ Table=1234</programlisting></para>
<varlistentry>
<term><varname>Label=</varname></term>
<listitem>
<para>The label for the prefix, an unsigned integer in the range 04294967294.
<para>The label for the prefix, an unsigned integer in the range 04294967294.
0xffffffff is reserved. This setting is mandatory.</para>
</listitem>
</varlistentry>
@ -1552,7 +1552,7 @@ Table=1234</programlisting></para>
<term><varname>TCPAdvertisedMaximumSegmentSize=</varname></term>
<listitem>
<para>Specifies the Path MSS (in bytes) hints given on TCP layer. The usual suffixes K, M, G, are
supported and are understood to the base of 1024. An unsigned integer in the range 14294967294.
supported and are understood to the base of 1024. An unsigned integer in the range 14294967294.
When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
@ -2049,7 +2049,7 @@ Table=1234</programlisting></para>
<para>Takes an IPv6 address with prefix length in the same format as the
<varname>Address=</varname> in the [Network] section. The DHCPv6 client will include a prefix
hint in the DHCPv6 solicitation sent to the server. The prefix length must be in the range
1128. Defaults to unset.</para>
1128. Defaults to unset.</para>
</listitem>
</varlistentry>
@ -3111,7 +3111,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<varlistentry>
<term><varname>Termination=</varname></term>
<listitem>
<para>Takes a boolean or a termination resistor value in ohm in the range 065535. When
<para>Takes a boolean or a termination resistor value in ohm in the range 065535. When
<literal>yes</literal>, the termination resistor is set to 120 ohm. When
<literal>no</literal> or <literal>0</literal> is set, the termination resistor is disabled.
When unset, the kernel's default will be used.</para>
@ -3225,7 +3225,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<term><varname>PacketLimit=</varname></term>
<listitem>
<para>Specifies the maximum number of packets the qdisc may hold queued at a time.
An unsigned integer in the range 04294967294. Defaults to 1000.</para>
An unsigned integer in the range 04294967294. Defaults to 1000.</para>
</listitem>
</varlistentry>
@ -3374,7 +3374,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<term><varname>PacketLimit=</varname></term>
<listitem>
<para>Specifies the hard limit on the queue size in number of packets. When this limit is reached,
incoming packets are dropped. An unsigned integer in the range 04294967294. Defaults to unset and
incoming packets are dropped. An unsigned integer in the range 04294967294. Defaults to unset and
kernel's default is used.</para>
</listitem>
</varlistentry>
@ -3436,7 +3436,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<para>Specifies the hard limit on the number of packets in the FIFO queue. The size limit prevents
overflow in case the kernel is unable to dequeue packets as quickly as it receives them. When this
limit is reached, incoming packets are dropped. An unsigned integer in the range
04294967294. Defaults to unset and kernel's default is used.</para>
04294967294. Defaults to unset and kernel's default is used.</para>
</listitem>
</varlistentry>
</variablelist>
@ -3479,14 +3479,6 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<xi:include href="tc.xml" xpointer="qdisc-parent" />
<xi:include href="tc.xml" xpointer="qdisc-handle" />
<varlistentry>
<term><varname>OverheadBytes=</varname></term>
<listitem>
<para>Specifies that bytes to be addeded to the size of each packet. Bytes may be negative. Takes
an integer in the range from -64 to 256. Defaults to unset and kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Bandwidth=</varname></term>
<listitem>
@ -3495,6 +3487,230 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
unset and kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>AutoRateIngress=</varname></term>
<listitem>
<para>Takes a boolean value. Enables automatic capacity estimation based on traffic arriving
at this qdisc. This is most likely to be useful with cellular links, which tend to change
quality randomly. If this setting is enabled, the <varname>Bandwidth=</varname> setting is
used as an initial estimate. Defaults to unset, and the kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>OverheadBytes=</varname></term>
<listitem>
<para>Specifies that bytes to be addeded to the size of each packet. Bytes may be negative.
Takes an integer in the range -64…256. Defaults to unset and kernel's default is used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>MPUBytes=</varname></term>
<listitem>
<para>Rounds each packet (including overhead) up to the specified bytes. Takes an integer in
the range 1…256. Defaults to unset and kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>CompensationMode=</varname></term>
<listitem>
<para>Takes one of <literal>none</literal>, <literal>atm</literal>, or <literal>ptm</literal>.
Specifies the compensation mode for overhead calculation. When <literal>none</literal>, no
compensation is taken into account. When <literal>atm</literal>, enables the compensation for
ATM cell framing, which is normally found on ADSL links. When <literal>ptm</literal>, enables
the compensation for PTM encoding, which is normally found on VDSL2 links and uses a 64b/65b
encoding scheme. Defaults to unset and the kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>UseRawPacketSize=</varname></term>
<listitem>
<para>Takes a boolean value. When true, the packet size reported by the Linux kernel will be
used, instead of the underlying IP packet size. Defaults to unset, and the kernel's default
is used.</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>
<varlistentry>
<term><varname>NAT=</varname></term>
<listitem>
<para>Takes a boolean value. When true, CAKE performs a NAT lookup before applying
flow-isolation rules, to determine the true addresses and port numbers of the packet, to
improve fairness between hosts inside the NAT. This has no practical effect when
<varname>FlowIsolationMode=</varname> is <literal>none</literal> or <literal>flows</literal>,
or if NAT is performed on a different host. Defaults to unset, and the kernel's default is
used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>PriorityQueueingPreset=</varname></term>
<listitem>
<para>CAKE divides traffic into <literal>tins</literal>, and each tin has its own independent
set of flow-isolation queues, bandwidth threshold, and priority. This specifies the preset of
tin profiles. The available values are:</para>
<variablelist>
<varlistentry>
<term><option>besteffort</option></term>
<listitem><para>
Disables priority queueing by placing all traffic in one tin.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>precedence</option></term>
<listitem><para>
Enables priority queueing based on the legacy interpretation of TOS
<literal>Precedence</literal> field. Use of this preset on the modern Internet is
firmly discouraged.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>diffserv8</option></term>
<listitem><para>
Enables priority queueing based on the Differentiated Service
(<literal>DiffServ</literal>) field with eight tins: Background Traffic, High
Throughput, Best Effort, Video Streaming, Low Latency Transactions, Interactive Shell,
Minimum Latency, and Network Control.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>diffserv4</option></term>
<listitem><para>
Enables priority queueing based on the Differentiated Service
(<literal>DiffServ</literal>) field with four tins: Background Traffic, Best Effort,
Streaming Media, and Latency Sensitive.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>diffserv3</option></term>
<listitem><para>
Enables priority queueing based on the Differentiated Service
(<literal>DiffServ</literal>) field with three tins: Background Traffic, Best Effort,
and Latency Sensitive.
</para></listitem>
</varlistentry>
</variablelist>
<para>Defaults to unset, and the kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FirewallMark=</varname></term>
<listitem>
<para>Takes an integer in the range 1…4294967295. When specified, firewall-mark-based
overriding of CAKE's tin selection is enabled. Defaults to unset, and the kernel's default is
used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Wash=</varname></term>
<listitem>
<para>Takes a boolean value. When true, CAKE clears the DSCP fields, except for ECN bits, of
any packet passing through CAKE. Defaults to unset, and the kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>SplitGSO=</varname></term>
<listitem>
<para>Takes a boolean value. When true, CAKE will split General Segmentation Offload (GSO)
super-packets into their on-the-wire components and dequeue them individually. Defaults to
unset, and the kernel's default is used.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
@ -3511,7 +3727,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<term><varname>PacketLimit=</varname></term>
<listitem>
<para>Specifies the hard limit on the queue size in number of packets. When this limit is reached,
incoming packets are dropped. An unsigned integer in the range 04294967294. Defaults to unset and
incoming packets are dropped. An unsigned integer in the range 04294967294. Defaults to unset and
kernel's default is used.</para>
</listitem>
</varlistentry>
@ -3595,7 +3811,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<varlistentry>
<term><varname>Bands=</varname></term>
<listitem>
<para>Specifies the number of bands. An unsigned integer in the range 116. This value has to be at
<para>Specifies the number of bands. An unsigned integer in the range 116. This value has to be at
least large enough to cover the strict bands specified through the <varname>StrictBands=</varname>
and bandwidth-sharing bands specified in <varname>QuantumBytes=</varname>.</para>
</listitem>
@ -3605,7 +3821,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<term><varname>StrictBands=</varname></term>
<listitem>
<para>Specifies the number of bands that should be created in strict mode. An unsigned integer in
the range 116.</para>
the range 116.</para>
</listitem>
</varlistentry>
@ -3977,7 +4193,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<term><varname>PacketLimit=</varname></term>
<listitem>
<para>Specifies the hard limit on the queue size in number of packets. When this limit is reached,
incoming packets are dropped. An unsigned integer in the range 04294967294. Defaults to unset and
incoming packets are dropped. An unsigned integer in the range 04294967294. Defaults to unset and
kernel's default is used.</para>
</listitem>
</varlistentry>
@ -4034,8 +4250,8 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<varlistentry>
<term><varname>VLAN=</varname></term>
<listitem>
<para>The VLAN ID allowed on the port. This can be either a single ID or a range M-N. VLAN IDs are valid
from 1 to 4094.</para>
<para>The VLAN ID allowed on the port. This can be either a single ID or a range M-N. Takes
an integer in the range 1…4094.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -1028,9 +1028,23 @@ static const NLType rtnl_nexthop_types[] = {
DEFINE_TYPE_SYSTEM(rtnl_nexthop);
static const NLType rtnl_tca_option_data_cake_types[] = {
[TCA_CAKE_BASE_RATE64] = { .type = NETLINK_TYPE_U64 },
[TCA_CAKE_OVERHEAD] = { .type = NETLINK_TYPE_S32 },
[TCA_CAKE_MPU] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_BASE_RATE64] = { .type = NETLINK_TYPE_U64 },
[TCA_CAKE_DIFFSERV_MODE] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_ATM] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_FLOW_MODE] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_OVERHEAD] = { .type = NETLINK_TYPE_S32 },
[TCA_CAKE_RTT] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_TARGET] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_AUTORATE] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_MEMORY] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_NAT] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_RAW] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_WASH] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_MPU] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_INGRESS] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_ACK_FILTER] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_SPLIT_GSO] = { .type = NETLINK_TYPE_U32 },
[TCA_CAKE_FWMARK] = { .type = NETLINK_TYPE_U32 },
};
static const NLType rtnl_tca_option_data_codel_types[] = {

View File

@ -388,7 +388,17 @@ BFIFO.LimitBytes, config_parse_bfifo_size,
CAKE.Parent, config_parse_qdisc_parent, QDISC_KIND_CAKE, 0
CAKE.Handle, config_parse_qdisc_handle, QDISC_KIND_CAKE, 0
CAKE.Bandwidth, config_parse_cake_bandwidth, QDISC_KIND_CAKE, 0
CAKE.AutoRateIngress, config_parse_cake_tristate, QDISC_KIND_CAKE, 0
CAKE.OverheadBytes, config_parse_cake_overhead, QDISC_KIND_CAKE, 0
CAKE.MPUBytes, config_parse_cake_mpu, QDISC_KIND_CAKE, 0
CAKE.CompensationMode, config_parse_cake_compensation_mode, QDISC_KIND_CAKE, 0
CAKE.UseRawPacketSize, config_parse_cake_tristate, QDISC_KIND_CAKE, 0
CAKE.FlowIsolationMode, config_parse_cake_flow_isolation_mode, QDISC_KIND_CAKE, 0
CAKE.NAT, config_parse_cake_tristate, QDISC_KIND_CAKE, 0
CAKE.PriorityQueueingPreset, config_parse_cake_priority_queueing_preset, QDISC_KIND_CAKE, 0
CAKE.FirewallMark, config_parse_cake_fwmark, QDISC_KIND_CAKE, 0
CAKE.Wash, config_parse_cake_tristate, QDISC_KIND_CAKE, 0
CAKE.SplitGSO, config_parse_cake_tristate, 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

View File

@ -9,8 +9,28 @@
#include "netlink-util.h"
#include "parse-util.h"
#include "qdisc.h"
#include "string-table.h"
#include "string-util.h"
static int cake_init(QDisc *qdisc) {
CommonApplicationsKeptEnhanced *c;
assert(qdisc);
c = CAKE(qdisc);
c->autorate = -1;
c->compensation_mode = _CAKE_COMPENSATION_MODE_INVALID;
c->raw = -1;
c->flow_isolation_mode = _CAKE_FLOW_ISOLATION_MODE_INVALID;
c->nat = -1;
c->preset = _CAKE_PRESET_INVALID;
c->wash = -1;
c->split_gso = -1;
return 0;
}
static int cake_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
CommonApplicationsKeptEnhanced *c;
int r;
@ -31,9 +51,72 @@ 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_BASE_RATE64 attribute: %m");
}
r = sd_netlink_message_append_s32(req, TCA_CAKE_OVERHEAD, c->overhead);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_OVERHEAD attribute: %m");
if (c->autorate >= 0) {
r = sd_netlink_message_append_u32(req, TCA_CAKE_AUTORATE, c->autorate);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_AUTORATE attribute: %m");
}
if (c->overhead_set) {
r = sd_netlink_message_append_s32(req, TCA_CAKE_OVERHEAD, c->overhead);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_OVERHEAD attribute: %m");
}
if (c->mpu > 0) {
r = sd_netlink_message_append_u32(req, TCA_CAKE_MPU, c->mpu);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_MPU attribute: %m");
}
if (c->compensation_mode >= 0) {
r = sd_netlink_message_append_u32(req, TCA_CAKE_ATM, c->compensation_mode);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_ATM attribute: %m");
}
if (c->raw > 0) {
/* TCA_CAKE_RAW attribute is mostly a flag, not boolean. */
r = sd_netlink_message_append_u32(req, TCA_CAKE_RAW, 0);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_RAW 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");
}
if (c->nat >= 0) {
r = sd_netlink_message_append_u32(req, TCA_CAKE_NAT, c->nat);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_NAT attribute: %m");
}
if (c->preset >= 0) {
r = sd_netlink_message_append_u32(req, TCA_CAKE_DIFFSERV_MODE, c->preset);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_DIFFSERV_MODE attribute: %m");
}
if (c->fwmark > 0) {
r = sd_netlink_message_append_u32(req, TCA_CAKE_FWMARK, c->fwmark);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_FWMARK attribute: %m");
}
if (c->wash >= 0) {
r = sd_netlink_message_append_u32(req, TCA_CAKE_WASH, c->wash);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_WASH attribute: %m");
}
if (c->split_gso >= 0) {
r = sd_netlink_message_append_u32(req, TCA_CAKE_SPLIT_GSO, c->wash);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_CAKE_SPLIT_GSO attribute: %m");
}
r = sd_netlink_message_close_container(req);
if (r < 0)
@ -132,7 +215,7 @@ int config_parse_cake_overhead(
c = CAKE(qdisc);
if (isempty(rvalue)) {
c->overhead = 0;
c->overhead_set = false;
TAKE_PTR(qdisc);
return 0;
}
@ -152,6 +235,380 @@ int config_parse_cake_overhead(
}
c->overhead = v;
c->overhead_set = true;
TAKE_PTR(qdisc);
return 0;
}
int config_parse_cake_mpu(
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;
uint32_t v;
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->mpu = 0;
TAKE_PTR(qdisc);
return 0;
}
r = safe_atou32(rvalue, &v);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (v <= 0 || v > 256) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
c->mpu = v;
TAKE_PTR(qdisc);
return 0;
}
int config_parse_cake_tristate(
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;
int *dest, 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 (streq(lvalue, "AutoRateIngress"))
dest = &c->autorate;
else if (streq(lvalue, "UseRawPacketSize"))
dest = &c->raw;
else if (streq(lvalue, "NAT"))
dest = &c->nat;
else if (streq(lvalue, "Wash"))
dest = &c->wash;
else if (streq(lvalue, "SplitGSO"))
dest = &c->split_gso;
else
assert_not_reached();
if (isempty(rvalue)) {
*dest = -1;
TAKE_PTR(qdisc);
return 0;
}
r = parse_boolean(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
*dest = r;
TAKE_PTR(qdisc);
return 0;
}
static const char * const cake_compensation_mode_table[_CAKE_COMPENSATION_MODE_MAX] = {
[CAKE_COMPENSATION_MODE_NONE] = "none",
[CAKE_COMPENSATION_MODE_ATM] = "atm",
[CAKE_COMPENSATION_MODE_PTM] = "ptm",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(cake_compensation_mode, CakeCompensationMode);
int config_parse_cake_compensation_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;
CakeCompensationMode 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->compensation_mode = _CAKE_COMPENSATION_MODE_INVALID;
TAKE_PTR(qdisc);
return 0;
}
mode = cake_compensation_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->compensation_mode = mode;
TAKE_PTR(qdisc);
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;
}
static const char * const cake_priority_queueing_preset_table[_CAKE_PRESET_MAX] = {
[CAKE_PRESET_DIFFSERV3] = "diffserv3",
[CAKE_PRESET_DIFFSERV4] = "diffserv4",
[CAKE_PRESET_DIFFSERV8] = "diffserv8",
[CAKE_PRESET_BESTEFFORT] = "besteffort",
[CAKE_PRESET_PRECEDENCE] = "precedence",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(cake_priority_queueing_preset, CakePriorityQueueingPreset);
int config_parse_cake_priority_queueing_preset(
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;
CakePriorityQueueingPreset preset;
Network *network = data;
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->preset = _CAKE_PRESET_INVALID;
TAKE_PTR(qdisc);
return 0;
}
preset = cake_priority_queueing_preset_from_string(rvalue);
if (preset < 0) {
log_syntax(unit, LOG_WARNING, filename, line, preset,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
c->preset = preset;
TAKE_PTR(qdisc);
return 0;
}
int config_parse_cake_fwmark(
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;
uint32_t fwmark;
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->fwmark = 0;
TAKE_PTR(qdisc);
return 0;
}
r = safe_atou32(rvalue, &fwmark);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (fwmark <= 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
c->fwmark = fwmark;
TAKE_PTR(qdisc);
return 0;
}
@ -159,5 +616,6 @@ int config_parse_cake_overhead(
const QDiscVTable cake_vtable = {
.object_size = sizeof(CommonApplicationsKeptEnhanced),
.tca_kind = "cake",
.init = cake_init,
.fill_message = cake_fill_message,
};

View File

@ -2,15 +2,68 @@
* Copyright © 2020 VMware, Inc. */
#pragma once
#include <linux/pkt_sched.h>
#include "conf-parser.h"
#include "qdisc.h"
typedef enum CakeCompensationMode {
CAKE_COMPENSATION_MODE_NONE = CAKE_ATM_NONE,
CAKE_COMPENSATION_MODE_ATM = CAKE_ATM_ATM,
CAKE_COMPENSATION_MODE_PTM = CAKE_ATM_PTM,
_CAKE_COMPENSATION_MODE_MAX,
_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 enum CakePriorityQueueingPreset {
CAKE_PRESET_DIFFSERV3 = CAKE_DIFFSERV_DIFFSERV3,
CAKE_PRESET_DIFFSERV4 = CAKE_DIFFSERV_DIFFSERV4,
CAKE_PRESET_DIFFSERV8 = CAKE_DIFFSERV_DIFFSERV8,
CAKE_PRESET_BESTEFFORT = CAKE_DIFFSERV_BESTEFFORT,
CAKE_PRESET_PRECEDENCE = CAKE_DIFFSERV_PRECEDENCE,
_CAKE_PRESET_MAX,
_CAKE_PRESET_INVALID = -EINVAL,
} CakePriorityQueueingPreset;
typedef struct CommonApplicationsKeptEnhanced {
QDisc meta;
int overhead;
/* Shaper parameters */
int autorate;
uint64_t bandwidth;
/* Overhead compensation parameters */
bool overhead_set;
int overhead;
uint32_t mpu;
CakeCompensationMode compensation_mode;
int raw;
/* Flow isolation parameters */
CakeFlowIsolationMode flow_isolation_mode;
int nat;
/* Priority queue parameters */
CakePriorityQueueingPreset preset;
uint32_t fwmark;
/* Other parameters */
int wash;
int split_gso;
} CommonApplicationsKeptEnhanced;
DEFINE_QDISC_CAST(CAKE, CommonApplicationsKeptEnhanced);
@ -18,3 +71,9 @@ extern const QDiscVTable cake_vtable;
CONFIG_PARSER_PROTOTYPE(config_parse_cake_bandwidth);
CONFIG_PARSER_PROTOTYPE(config_parse_cake_overhead);
CONFIG_PARSER_PROTOTYPE(config_parse_cake_mpu);
CONFIG_PARSER_PROTOTYPE(config_parse_cake_tristate);
CONFIG_PARSER_PROTOTYPE(config_parse_cake_compensation_mode);
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);

View File

@ -470,7 +470,17 @@ ECN=
Parent=
Handle=
Bandwidth=
AutoRateIngress=
OverheadBytes=
MPUBytes=
CompensationMode=
UseRawPacketSize=
FlowIsolationMode=
NAT=
PriorityQueueingPreset=
FirewallMark=
Wash=
SplitGSO=
[TrafficControlQueueingDiscipline]
Parent=
NetworkEmulatorDelaySec=

View File

@ -9,5 +9,15 @@ Address=10.1.2.3/16
[CAKE]
Parent=root
Handle=3a
OverheadBytes=128
Bandwidth=500M
AutoRateIngress=yes
OverheadBytes=128
MPUBytes=20
CompensationMode=atm
UseRawPacketSize=yes
FlowIsolationMode=dual-dst-host
NAT=yes
PriorityQueueingPreset=diffserv8
FirewallMark=0xff00
Wash=yes
SplitGSO=yes

View File

@ -3262,9 +3262,19 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
output = check_output('tc qdisc show dev dummy98')
print(output)
self.assertRegex(output, 'qdisc cake 3a: root')
self.assertRegex(output, 'bandwidth 500Mbit')
self.assertRegex(output, 'overhead 128')
self.assertIn('qdisc cake 3a: root', output)
self.assertIn('bandwidth 500Mbit', output)
self.assertIn('autorate-ingress', output)
self.assertIn('diffserv8', output)
self.assertIn('dual-dsthost', output)
self.assertIn(' nat', output)
self.assertIn(' wash', output)
self.assertIn(' split-gso', output)
self.assertIn(' raw', output)
self.assertIn(' atm', output)
self.assertIn('overhead 128', output)
self.assertIn('mpu 20', output)
self.assertIn('fwmark 0xff00', output)
@expectedFailureIfPIEIsNotAvailable()
def test_qdisc_pie(self):