network: tc: introduce cake

CAKE (Common Applications Kept Enhanced)

Please see http://man7.org/linux/man-pages/man8/tc-cake.8.html
This commit is contained in:
Susant Sahani 2020-03-02 15:54:17 +09:00 committed by Yu Watanabe
parent aa550d2a51
commit ad8352f4ff
11 changed files with 246 additions and 0 deletions

View File

@ -2562,7 +2562,49 @@
incoming packets are dropped. An unsigned integer ranges 0 to 4294967294. Defaults to unset and kernel's default is used.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>[CAKE] Section Options</title>
<para>The <literal>[CAKE]</literal> section manages the queueing discipline (qdisc) of
Common Applications Kept Enhanced (CAKE).</para>
<variablelist class='network-directives'>
<varlistentry>
<term><varname>Parent=</varname></term>
<listitem>
<para>Specifies the parent Queueing Discipline (qdisc). Takes one of <literal>root</literal>,
<literal>clsact</literal>, <literal>ingress</literal> or a class id. The class id takes the
major and minor number in hexadecimal ranges 1 to ffff separated with a colon
(<literal>major:minor</literal>). Defaults to <literal>root</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Handle=</varname></term>
<listitem>
<para>Specifies the major number of unique identifier of the qdisc, known as the handle.
Takes a number in hexadecimal ranges 1 to ffff. Defaults to unset.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Overhead=</varname></term>
<listitem>
<para>Specifies that bytes to be addeded to the size of each packet. Bytes may be negative.
Takes an integer ranges -64 to 256. Defaults to unset and kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Bandwidth=</varname></term>
<listitem>
<para>Specifies the shaper bandwidth. When suffixed with K, M, or G, the specified size is
parsed as Kilobits, Megabits, or Gigabits, respectively, to the base of 1000. Defaults to
unset and kernel's default is used.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -745,6 +745,12 @@ static const NLTypeSystem rtnl_nexthop_type_system = {
.types = rtnl_nexthop_types,
};
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 },
};
static const NLType rtnl_tca_option_data_codel_types[] = {
[TCA_CODEL_TARGET] = { .type = NETLINK_TYPE_U32 },
[TCA_CODEL_LIMIT] = { .type = NETLINK_TYPE_U32 },
@ -808,6 +814,7 @@ static const NLType rtnl_tca_option_data_tbf_types[] = {
};
static const char* const nl_union_tca_option_data_table[] = {
[NL_UNION_TCA_OPTION_DATA_CAKE] = "cake",
[NL_UNION_TCA_OPTION_DATA_CODEL] = "codel",
[NL_UNION_TCA_OPTION_DATA_FQ] = "fq",
[NL_UNION_TCA_OPTION_DATA_FQ_CODEL] = "fq_codel",
@ -820,6 +827,8 @@ static const char* const nl_union_tca_option_data_table[] = {
DEFINE_STRING_TABLE_LOOKUP(nl_union_tca_option_data, NLUnionTCAOptionData);
static const NLTypeSystem rtnl_tca_option_data_type_systems[] = {
[NL_UNION_TCA_OPTION_DATA_CAKE] = { .count = ELEMENTSOF(rtnl_tca_option_data_cake_types),
.types = rtnl_tca_option_data_cake_types },
[NL_UNION_TCA_OPTION_DATA_CODEL] = { .count = ELEMENTSOF(rtnl_tca_option_data_codel_types),
.types = rtnl_tca_option_data_codel_types },
[NL_UNION_TCA_OPTION_DATA_FQ] = { .count = ELEMENTSOF(rtnl_tca_option_data_fq_types),

View File

@ -96,6 +96,7 @@ const char *nl_union_link_info_data_to_string(NLUnionLinkInfoData p) _const_;
NLUnionLinkInfoData nl_union_link_info_data_from_string(const char *p) _pure_;
typedef enum NLUnionTCAOptionData {
NL_UNION_TCA_OPTION_DATA_CAKE,
NL_UNION_TCA_OPTION_DATA_CODEL,
NL_UNION_TCA_OPTION_DATA_FQ,
NL_UNION_TCA_OPTION_DATA_FQ_CODEL,

View File

@ -107,6 +107,8 @@ sources = files('''
networkd-util.h
networkd-wifi.c
networkd-wifi.h
tc/cake.c
tc/cake.h
tc/codel.c
tc/codel.h
tc/fifo.c

View File

@ -254,6 +254,10 @@ CAN.RestartSec, config_parse_sec,
CAN.TripleSampling, config_parse_tristate, 0, offsetof(Network, can_triple_sampling)
QDisc.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0
QDisc.Handle, config_parse_qdisc_handle, _QDISC_KIND_INVALID, 0
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.Overhead, config_parse_cake_overhead, 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

@ -484,6 +484,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
"TrafficControlQueueingDiscipline\0"
"CAN\0"
"QDisc\0"
"CAKE\0"
"ControlledDelay\0"
"PFIFO\0"
"FairQueueing\0"

159
src/network/tc/cake.c Normal file
View File

@ -0,0 +1,159 @@
/* SPDX-License-Identifier: LGPL-2.1+
* Copyright © 2020 VMware, Inc. */
#include <linux/pkt_sched.h>
#include "alloc-util.h"
#include "cake.h"
#include "conf-parser.h"
#include "netlink-util.h"
#include "parse-util.h"
#include "qdisc.h"
#include "string-util.h"
static int cake_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
CommonApplicationsKeptEnhanced *c;
int r;
assert(link);
assert(qdisc);
assert(req);
c = CAKE(qdisc);
r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "cake");
if (r < 0)
return log_link_error_errno(link, r, "Could not open container TCA_OPTIONS: %m");
if (c->bandwidth > 0) {
r = sd_netlink_message_append_u64(req, TCA_CAKE_BASE_RATE64, c->bandwidth);
if (r < 0)
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");
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_cake_bandwidth(
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;
uint64_t k;
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)
return log_syntax(unit, LOG_ERR, filename, line, r,
"More than one kind of queueing discipline, ignoring assignment: %m");
c = CAKE(qdisc);
if (isempty(rvalue)) {
c->bandwidth = 0;
qdisc = NULL;
return 0;
}
r = parse_size(rvalue, 1000, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
c->bandwidth = k/8;
qdisc = NULL;
return 0;
}
int config_parse_cake_overhead(
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;
int32_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)
return log_syntax(unit, LOG_ERR, filename, line, r,
"More than one kind of queueing discipline, ignoring assignment: %m");
c = CAKE(qdisc);
if (isempty(rvalue)) {
c->overhead = 0;
qdisc = NULL;
return 0;
}
r = safe_atoi32(rvalue, &v);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse 'Overhead=', ignoring assignment: %s",
rvalue);
return 0;
}
if (v < -64 || v > 256) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid 'Overhead=', ignoring assignment: %s",
rvalue);
return 0;
}
c->overhead = v;
qdisc = NULL;
return 0;
}
const QDiscVTable cake_vtable = {
.object_size = sizeof(CommonApplicationsKeptEnhanced),
.tca_kind = "cake",
.fill_message = cake_fill_message,
};

20
src/network/tc/cake.h Normal file
View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: LGPL-2.1+
* Copyright © 2020 VMware, Inc. */
#pragma once
#include "conf-parser.h"
#include "qdisc.h"
typedef struct CommonApplicationsKeptEnhanced {
QDisc meta;
int overhead;
uint64_t bandwidth;
} CommonApplicationsKeptEnhanced;
DEFINE_QDISC_CAST(CAKE, CommonApplicationsKeptEnhanced);
extern const QDiscVTable cake_vtable;
CONFIG_PARSER_PROTOTYPE(config_parse_cake_bandwidth);
CONFIG_PARSER_PROTOTYPE(config_parse_cake_overhead);

View File

@ -16,6 +16,7 @@
#include "tc-util.h"
const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX] = {
[QDISC_KIND_CAKE] = &cake_vtable,
[QDISC_KIND_CODEL] = &codel_vtable,
[QDISC_KIND_FQ] = &fq_vtable,
[QDISC_KIND_FQ_CODEL] = &fq_codel_vtable,

View File

@ -9,6 +9,7 @@
#include "tc.h"
typedef enum QDiscKind {
QDISC_KIND_CAKE,
QDISC_KIND_CODEL,
QDISC_KIND_FQ,
QDISC_KIND_FQ_CODEL,
@ -77,6 +78,7 @@ DEFINE_TC_CAST(QDISC, QDisc);
CONFIG_PARSER_PROTOTYPE(config_parse_qdisc_parent);
CONFIG_PARSER_PROTOTYPE(config_parse_qdisc_handle);
#include "cake.h"
#include "codel.h"
#include "fifo.h"
#include "fq-codel.h"

View File

@ -326,6 +326,11 @@ TargetSec=
IntervalSec=
CEThresholdSec=
ECN=
[CAKE]
Parent=
Handle=
Bandwidth=
Overhead=
[TrafficControlQueueingDiscipline]
Parent=
NetworkEmulatorDelaySec=