1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-08 08:58:27 +03:00

Merge pull request #25423 from yuwata/network-tc-cake-rtt-and-ack-filter

network: tc-cake: support controlling RTT and ACK filter
This commit is contained in:
Yu Watanabe 2022-11-19 15:35:49 +09:00 committed by GitHub
commit 26627c088b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 170 additions and 1 deletions

View File

@ -4026,6 +4026,27 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RTTSec=</varname></term>
<listitem>
<para>Specifies the RTT for the filter. Takes a timespan. Typical values are e.g. 100us for
extremely high-performance 10GigE+ networks like datacentre, 1ms for non-WiFi LAN connections,
100ms for typical internet connections. Defaults to unset, and the kernel's default will be used.
</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>

View File

@ -420,6 +420,8 @@ CAKE.PriorityQueueingPreset, config_parse_cake_priority_queueing
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
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

View 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;
}
@ -118,6 +119,18 @@ static int cake_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req)
return r;
}
if (c->rtt > 0) {
r = sd_netlink_message_append_u32(req, TCA_CAKE_RTT, c->rtt);
if (r < 0)
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;
@ -605,6 +618,124 @@ int config_parse_cake_fwmark(
return 0;
}
int config_parse_cake_rtt(
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 = ASSERT_PTR(data);
usec_t t;
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->rtt = 0;
TAKE_PTR(qdisc);
return 0;
}
r = parse_sec(rvalue, &t);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (t <= 0 || t > UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
c->rtt = t;
TAKE_PTR(qdisc);
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",

View 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;
@ -63,7 +71,8 @@ typedef struct CommonApplicationsKeptEnhanced {
/* Other parameters */
int wash;
int split_gso;
usec_t rtt;
CakeAckFilter ack_filter;
} CommonApplicationsKeptEnhanced;
DEFINE_QDISC_CAST(CAKE, CommonApplicationsKeptEnhanced);
@ -77,3 +86,5 @@ 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);
CONFIG_PARSER_PROTOTYPE(config_parse_cake_rtt);
CONFIG_PARSER_PROTOTYPE(config_parse_cake_ack_filter);

View File

@ -21,3 +21,5 @@ PriorityQueueingPreset=diffserv8
FirewallMark=0xff00
Wash=yes
SplitGSO=yes
RTTSec=1sec
AckFilter=aggressive

View File

@ -3485,6 +3485,8 @@ class NetworkdTCTests(unittest.TestCase, Utilities):
self.assertIn('overhead 128', output)
self.assertIn('mpu 20', output)
self.assertIn('fwmark 0xff00', output)
self.assertIn('rtt 1s', output)
self.assertIn('ack-filter-aggressive', output)
@expectedFailureIfModuleIsNotAvailable('sch_codel')
def test_qdisc_codel(self):