Merge pull request #14337 from yuwata/network-tc-fq-more

network: tc: introduce more FQ settings
This commit is contained in:
Yu Watanabe 2019-12-17 23:30:10 +09:00 committed by GitHub
commit 6e5df4036f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 434 additions and 10 deletions

View File

@ -2515,6 +2515,76 @@
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingFlowLimit=</varname></term>
<listitem>
<para>Specifies the hard limit on the maximum number of packets queued per flow. Defaults to
unset and kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingQuantum=</varname></term>
<listitem>
<para>Specifies the credit per dequeue RR round, i.e. the amount of bytes a flow is allowed
to dequeue at once. When suffixed with K, M, or G, the specified size is parsed as Kilobytes,
Megabytes, or Gigabytes, respectively, to the base of 1024. Defaults to unset and kernel's
default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingInitialQuantum=</varname></term>
<listitem>
<para>Specifies the initial sending rate credit, i.e. the amount of bytes a new flow is
allowed to dequeue initially. When suffixed with K, M, or G, the specified size is parsed as
Kilobytes, Megabytes, or Gigabytes, respectively, to the base of 1024. Defaults to unset and
kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingMaximumRate=</varname></term>
<listitem>
<para>Specifies the maximum sending rate of a flow. When suffixed with K, M, or G, the
specified size is parsed as Kilobytes, Megabytes, or Gigabytes, respectively, to the base of
1000. Defaults to unset and kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingBuckets=</varname></term>
<listitem>
<para>Specifies the size of the hash table used for flow lookups. Defaults to unset and
kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingOrphanMask=</varname></term>
<listitem>
<para>Takes an unsigned integer. For packets not owned by a socket, fq is able to mask a part
of hash and reduce number of buckets associated with the traffic. Defaults to unset and
kernel's default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingPacing=</varname></term>
<listitem>
<para>Takes a boolean, and enables or disables flow pacing. Defaults to unset and kernel's
default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FairQueueTrafficPolicingCEThresholdSec=</varname></term>
<listitem>
<para>Takes a timespan. This sets a threshold above which all packets are marked with ECN
Congestion Experienced (CE). Defaults to unset and kernel's default is used.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -756,6 +756,7 @@ static const NLType rtnl_tca_option_data_fq_types[] = {
[TCA_FQ_FLOW_REFILL_DELAY] = { .type = NETLINK_TYPE_U32 },
[TCA_FQ_LOW_RATE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
[TCA_FQ_CE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
[TCA_FQ_ORPHAN_MASK] = { .type = NETLINK_TYPE_U32 },
};
static const NLType rtnl_tca_option_data_fq_codel_types[] = {

View File

@ -266,7 +266,15 @@ TrafficControlQueueingDiscipline.FairQueuingControlledDelayTargetSec, con
TrafficControlQueueingDiscipline.FairQueuingControlledDelayIntervalSec, config_parse_tc_fair_queuing_controlled_delay_usec, 0, 0
TrafficControlQueueingDiscipline.FairQueuingControlledDelayCEThresholdSec, config_parse_tc_fair_queuing_controlled_delay_usec, 0, 0
TrafficControlQueueingDiscipline.FairQueuingControlledDelayECN, config_parse_tc_fair_queuing_controlled_delay_bool, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingPacketLimit, config_parse_tc_fair_queue_traffic_policing_packet_limit, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingPacketLimit, config_parse_tc_fair_queue_traffic_policing_u32, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingFlowLimit, config_parse_tc_fair_queue_traffic_policing_u32, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingQuantum, config_parse_tc_fair_queue_traffic_policing_size, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingInitialQuantum, config_parse_tc_fair_queue_traffic_policing_size, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingMaximumRate, config_parse_tc_fair_queue_traffic_policing_max_rate, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingBuckets, config_parse_tc_fair_queue_traffic_policing_u32, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingOrphanMask, config_parse_tc_fair_queue_traffic_policing_u32, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingPacing, config_parse_tc_fair_queue_traffic_policing_bool, 0, 0
TrafficControlQueueingDiscipline.FairQueueTrafficPolicingCEThresholdSec, config_parse_tc_fair_queue_traffic_policing_usec, 0, 0
/* backwards compatibility: do not add new entries to this section */
Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)

View File

@ -9,6 +9,20 @@
#include "netlink-util.h"
#include "parse-util.h"
#include "string-util.h"
#include "util.h"
static int fair_queue_traffic_policing_init(QDisc *qdisc) {
FairQueueTrafficPolicing *fq;
assert(qdisc);
fq = FQ(qdisc);
fq->pacing = -1;
fq->ce_threshold_usec = USEC_INFINITY;
return 0;
}
static int fair_queue_traffic_policing_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
FairQueueTrafficPolicing *fq;
@ -24,9 +38,62 @@ static int fair_queue_traffic_policing_fill_message(Link *link, QDisc *qdisc, sd
if (r < 0)
return log_link_error_errno(link, r, "Could not open container TCA_OPTIONS: %m");
r = sd_netlink_message_append_u32(req, TCA_FQ_PLIMIT, fq->limit);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_PLIMIT attribute: %m");
if (fq->packet_limit > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_PLIMIT, fq->packet_limit);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_PLIMIT attribute: %m");
}
if (fq->flow_limit > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_FLOW_PLIMIT, fq->flow_limit);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_FLOW_PLIMIT attribute: %m");
}
if (fq->quantum > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_QUANTUM, fq->quantum);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_QUANTUM attribute: %m");
}
if (fq->initial_quantum > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_INITIAL_QUANTUM, fq->initial_quantum);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_INITIAL_QUANTUM attribute: %m");
}
if (fq->pacing >= 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_RATE_ENABLE, fq->pacing);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_RATE_ENABLE attribute: %m");
}
if (fq->max_rate > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_FLOW_MAX_RATE, fq->max_rate);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_FLOW_MAX_RATE attribute: %m");
}
if (fq->buckets > 0) {
uint32_t l;
l = log2u(fq->buckets);
r = sd_netlink_message_append_u32(req, TCA_FQ_BUCKETS_LOG, l);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_BUCKETS_LOG attribute: %m");
}
if (fq->orphan_mask > 0) {
r = sd_netlink_message_append_u32(req, TCA_FQ_ORPHAN_MASK, fq->orphan_mask);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_ORPHAN_MASK attribute: %m");
}
if (fq->ce_threshold_usec != USEC_INFINITY) {
r = sd_netlink_message_append_u32(req, TCA_FQ_CE_THRESHOLD, fq->ce_threshold_usec);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_FQ_CE_THRESHOLD attribute: %m");
}
r = sd_netlink_message_close_container(req);
if (r < 0)
@ -35,7 +102,137 @@ static int fair_queue_traffic_policing_fill_message(Link *link, QDisc *qdisc, sd
return 0;
}
int config_parse_tc_fair_queue_traffic_policing_packet_limit(
int config_parse_tc_fair_queue_traffic_policing_u32(
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;
FairQueueTrafficPolicing *fq;
Network *network = data;
uint32_t *p;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = qdisc_new_static(QDISC_KIND_FQ, 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");
fq = FQ(qdisc);
if (streq(lvalue, "FairQueueTrafficPolicingPacketLimit"))
p = &fq->packet_limit;
else if (streq(lvalue, "FairQueueTrafficPolicingFlowLimit"))
p = &fq->flow_limit;
else if (streq(lvalue, "FairQueueTrafficPolicingBuckets"))
p = &fq->buckets;
else if (streq(lvalue, "FairQueueTrafficPolicingOrphanMask"))
p = &fq->orphan_mask;
else
assert_not_reached("Invalid lvalue");
if (isempty(rvalue)) {
*p = 0;
qdisc = NULL;
return 0;
}
r = safe_atou32(rvalue, p);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
qdisc = NULL;
return 0;
}
int config_parse_tc_fair_queue_traffic_policing_size(
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;
FairQueueTrafficPolicing *fq;
Network *network = data;
uint64_t sz;
uint32_t *p;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = qdisc_new_static(QDISC_KIND_FQ, 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");
fq = FQ(qdisc);
if (streq(lvalue, "FairQueueTrafficPolicingQuantum"))
p = &fq->quantum;
else if (streq(lvalue, "FairQueueTrafficPolicingInitialQuantum"))
p = &fq->initial_quantum;
else
assert_not_reached("Invalid lvalue");
if (isempty(rvalue)) {
*p = 0;
qdisc = NULL;
return 0;
}
r = parse_size(rvalue, 1024, &sz);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (sz > UINT32_MAX) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Specified '%s=' is too large, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
*p = sz;
qdisc = NULL;
return 0;
}
int config_parse_tc_fair_queue_traffic_policing_bool(
const char *unit,
const char *filename,
unsigned line,
@ -67,13 +264,13 @@ int config_parse_tc_fair_queue_traffic_policing_packet_limit(
fq = FQ(qdisc);
if (isempty(rvalue)) {
fq->limit = 0;
fq->pacing = -1;
qdisc = NULL;
return 0;
}
r = safe_atou32(rvalue, &fq->limit);
r = parse_boolean(rvalue);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
@ -81,12 +278,132 @@ int config_parse_tc_fair_queue_traffic_policing_packet_limit(
return 0;
}
fq->pacing = r;
qdisc = NULL;
return 0;
}
int config_parse_tc_fair_queue_traffic_policing_usec(
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;
FairQueueTrafficPolicing *fq;
Network *network = data;
usec_t sec;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = qdisc_new_static(QDISC_KIND_FQ, 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");
fq = FQ(qdisc);
if (isempty(rvalue)) {
fq->ce_threshold_usec = USEC_INFINITY;
qdisc = NULL;
return 0;
}
r = parse_sec(rvalue, &sec);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (sec > UINT32_MAX) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Specified '%s=' is too large, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
fq->ce_threshold_usec = sec;
qdisc = NULL;
return 0;
}
int config_parse_tc_fair_queue_traffic_policing_max_rate(
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;
FairQueueTrafficPolicing *fq;
Network *network = data;
uint64_t sz;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = qdisc_new_static(QDISC_KIND_FQ, 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");
fq = FQ(qdisc);
if (isempty(rvalue)) {
fq->max_rate = 0;
qdisc = NULL;
return 0;
}
r = parse_size(rvalue, 1000, &sz);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (sz / 8 > UINT32_MAX) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Specified '%s=' is too large, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
fq->max_rate = sz / 8;
qdisc = NULL;
return 0;
}
const QDiscVTable fq_vtable = {
.init = fair_queue_traffic_policing_init,
.object_size = sizeof(FairQueueTrafficPolicing),
.tca_kind = "fq",
.fill_message = fair_queue_traffic_policing_fill_message,

View File

@ -8,10 +8,22 @@
typedef struct FairQueueTrafficPolicing {
QDisc meta;
uint32_t limit;
uint32_t packet_limit;
uint32_t flow_limit;
uint32_t quantum;
uint32_t initial_quantum;
uint32_t max_rate;
uint32_t buckets;
uint32_t orphan_mask;
int pacing;
usec_t ce_threshold_usec;
} FairQueueTrafficPolicing;
DEFINE_QDISC_CAST(FQ, FairQueueTrafficPolicing);
extern const QDiscVTable fq_vtable;
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_packet_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_u32);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_size);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_bool);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_usec);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queue_traffic_policing_max_rate);

View File

@ -287,3 +287,11 @@ FairQueuingControlledDelayIntervalSec=
FairQueuingControlledDelayCEThresholdSec=
FairQueuingControlledDelayECN=
FairQueueTrafficPolicingPacketLimit=
FairQueueTrafficPolicingFlowLimit=
FairQueueTrafficPolicingQuantum=
FairQueueTrafficPolicingInitialQuantum=
FairQueueTrafficPolicingMaximumRate=
FairQueueTrafficPolicingBuckets=
FairQueueTrafficPolicingOrphanMask=
FairQueueTrafficPolicingPacing=
FairQueueTrafficPolicingCEThresholdSec=

View File

@ -8,3 +8,11 @@ Address=10.1.2.3/16
[TrafficControlQueueingDiscipline]
Parent=root
FairQueueTrafficPolicingPacketLimit=1000
FairQueueTrafficPolicingFlowLimit=200
FairQueueTrafficPolicingQuantum=1500
FairQueueTrafficPolicingInitialQuantum=13000
FairQueueTrafficPolicingMaximumRate=1M
FairQueueTrafficPolicingBuckets=512
FairQueueTrafficPolicingOrphanMask=511
FairQueueTrafficPolicingPacing=yes
FairQueueTrafficPolicingCEThresholdSec=100ms

View File

@ -2165,7 +2165,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
output = check_output('tc qdisc show dev dummy98')
print(output)
self.assertRegex(output, 'qdisc fq')
self.assertRegex(output, 'limit 1000p')
self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511 quantum 1500 initial_quantum 13000 maxrate 1Mbit')
class NetworkdStateFileTests(unittest.TestCase, Utilities):
links = [