Skip to content

Commit 4d7ddaf

Browse files
committed
network: tc: introduce [QuickFairQueueingClass] section
1 parent b12aaee commit 4d7ddaf

File tree

8 files changed

+215
-0
lines changed

8 files changed

+215
-0
lines changed

man/systemd.network.xml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3263,6 +3263,34 @@
32633263
</variablelist>
32643264
</refsect1>
32653265

3266+
<refsect1>
3267+
<title>[QuickFairQueueingClass] Section Options</title>
3268+
<para>The <literal>[QuickFairQueueingClass]</literal> section manages the traffic control class of
3269+
Quick Fair Queueing (qfq).</para>
3270+
3271+
<variablelist class='network-directives'>
3272+
<xi:include href="tc.xml" xpointer="tclass-parent" />
3273+
<xi:include href="tc.xml" xpointer="tclass-classid" />
3274+
3275+
<varlistentry>
3276+
<term><varname>Weight=</varname></term>
3277+
<listitem>
3278+
<para>Specifies the weight of the class. Takse an integer in the range 1..1023. Defaults to
3279+
unset in which case the kernel default is used.</para>
3280+
</listitem>
3281+
</varlistentry>
3282+
3283+
<varlistentry>
3284+
<term><varname>MaxPacketSize=</varname></term>
3285+
<listitem>
3286+
<para>Specifies the maximum packet size in bytes for the class. When suffixed with K, M, or G, the specified
3287+
size is parsed as Kilobytes, Megabytes, or Gigabytes, respectively, to the base of 1000. When unset,
3288+
the kernel default is used.</para>
3289+
</listitem>
3290+
</varlistentry>
3291+
</variablelist>
3292+
</refsect1>
3293+
32663294
<refsect1>
32673295
<title>[BridgeVLAN] Section Options</title>
32683296
<para>The <literal>[BridgeVLAN]</literal> section manages the VLAN ID configuration of a bridge port and accepts

src/network/networkd-network-gperf.gperf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ PFIFOHeadDrop.Handle, config_parse_qdisc_handle,
314314
PFIFOHeadDrop.PacketLimit, config_parse_pfifo_size, QDISC_KIND_PFIFO_HEAD_DROP, 0
315315
QuickFairQueueing.Parent, config_parse_qdisc_parent, QDISC_KIND_QFQ, 0
316316
QuickFairQueueing.Handle, config_parse_qdisc_handle, QDISC_KIND_QFQ, 0
317+
QuickFairQueueingClass.Parent, config_parse_tclass_parent, TCLASS_KIND_QFQ, 0
318+
QuickFairQueueingClass.ClassId, config_parse_tclass_classid, TCLASS_KIND_QFQ, 0
319+
QuickFairQueueingClass.Weight, config_parse_quick_fair_queueing_weight, TCLASS_KIND_QFQ, 0
320+
QuickFairQueueingClass.MaxPacketSize, config_parse_quick_fair_queueing_max_packet, TCLASS_KIND_QFQ, 0
317321
FairQueueing.Parent, config_parse_qdisc_parent, QDISC_KIND_FQ, 0
318322
FairQueueing.Handle, config_parse_qdisc_handle, QDISC_KIND_FQ, 0
319323
FairQueueing.PacketLimit, config_parse_fair_queueing_u32, QDISC_KIND_FQ, 0

src/network/networkd-network.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
520520
"PFIFOHeadDrop\0"
521521
"PIE\0"
522522
"QuickFairQueueing\0"
523+
"QuickFairQueueingClass\0"
523524
"StochasticFairBlue\0"
524525
"StochasticFairnessQueueing\0"
525526
"TokenBucketFilter\0"

src/network/tc/qfq.c

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,170 @@
11
/* SPDX-License-Identifier: LGPL-2.1+
22
* Copyright © 2020 VMware, Inc. */
33

4+
#include <linux/pkt_sched.h>
5+
6+
#include "parse-util.h"
47
#include "qdisc.h"
58
#include "qfq.h"
9+
#include "string-util.h"
10+
11+
#define QFQ_MAX_WEIGHT (1 << 10)
12+
#define QFQ_MIN_MAX_PACKET 512
13+
#define QFQ_MAX_MAX_PACKET (1 << 16)
614

715
const QDiscVTable qfq_vtable = {
816
.object_size = sizeof(QuickFairQueueing),
917
.tca_kind = "qfq",
1018
};
19+
20+
static int quick_fair_queueing_class_fill_message(Link *link, TClass *tclass, sd_netlink_message *req) {
21+
QuickFairQueueingClass *qfq;
22+
int r;
23+
24+
assert(link);
25+
assert(tclass);
26+
assert(req);
27+
28+
qfq = TCLASS_TO_QFQ(tclass);
29+
30+
r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "qfq");
31+
if (r < 0)
32+
return log_link_error_errno(link, r, "Could not open container TCA_OPTIONS: %m");
33+
34+
if (qfq->weight > 0) {
35+
r = sd_netlink_message_append_u32(req, TCA_QFQ_WEIGHT, qfq->weight);
36+
if (r < 0)
37+
return log_link_error_errno(link, r, "Could not append TCA_QFQ_WEIGHT attribute: %m");
38+
}
39+
40+
if (qfq->max_packet > 0) {
41+
r = sd_netlink_message_append_u32(req, TCA_QFQ_LMAX, qfq->max_packet);
42+
if (r < 0)
43+
return log_link_error_errno(link, r, "Could not append TCA_QFQ_LMAX attribute: %m");
44+
}
45+
46+
r = sd_netlink_message_close_container(req);
47+
if (r < 0)
48+
return log_link_error_errno(link, r, "Could not close container TCA_OPTIONS: %m");
49+
return 0;
50+
}
51+
52+
int config_parse_quick_fair_queueing_weight(
53+
const char *unit,
54+
const char *filename,
55+
unsigned line,
56+
const char *section,
57+
unsigned section_line,
58+
const char *lvalue,
59+
int ltype,
60+
const char *rvalue,
61+
void *data,
62+
void *userdata) {
63+
64+
_cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
65+
QuickFairQueueingClass *qfq;
66+
Network *network = data;
67+
uint32_t v;
68+
int r;
69+
70+
assert(filename);
71+
assert(lvalue);
72+
assert(rvalue);
73+
assert(data);
74+
75+
r = tclass_new_static(TCLASS_KIND_QFQ, network, filename, section_line, &tclass);
76+
if (r < 0)
77+
return log_syntax(unit, LOG_ERR, filename, line, r,
78+
"Failed to create traffic control class, ignoring assignment: %m");
79+
80+
qfq = TCLASS_TO_QFQ(tclass);
81+
82+
if (isempty(rvalue)) {
83+
qfq->weight = 0;
84+
tclass = NULL;
85+
return 0;
86+
}
87+
88+
r = safe_atou32(rvalue, &v);
89+
if (r < 0) {
90+
log_syntax(unit, LOG_ERR, filename, line, r,
91+
"Failed to parse '%s=', ignoring assignment: %s",
92+
lvalue, rvalue);
93+
return 0;
94+
}
95+
96+
if (v == 0 || v > QFQ_MAX_WEIGHT) {
97+
log_syntax(unit, LOG_ERR, filename, line, 0,
98+
"Invalid '%s=', ignoring assignment: %s",
99+
lvalue, rvalue);
100+
return 0;
101+
}
102+
103+
qfq->weight = v;
104+
tclass = NULL;
105+
106+
return 0;
107+
}
108+
109+
int config_parse_quick_fair_queueing_max_packet(
110+
const char *unit,
111+
const char *filename,
112+
unsigned line,
113+
const char *section,
114+
unsigned section_line,
115+
const char *lvalue,
116+
int ltype,
117+
const char *rvalue,
118+
void *data,
119+
void *userdata) {
120+
121+
_cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
122+
QuickFairQueueingClass *qfq;
123+
Network *network = data;
124+
uint64_t v;
125+
int r;
126+
127+
assert(filename);
128+
assert(lvalue);
129+
assert(rvalue);
130+
assert(data);
131+
132+
r = tclass_new_static(TCLASS_KIND_QFQ, network, filename, section_line, &tclass);
133+
if (r < 0)
134+
return log_syntax(unit, LOG_ERR, filename, line, r,
135+
"Failed to create traffic control class, ignoring assignment: %m");
136+
137+
qfq = TCLASS_TO_QFQ(tclass);
138+
139+
if (isempty(rvalue)) {
140+
qfq->max_packet = 0;
141+
tclass = NULL;
142+
return 0;
143+
}
144+
145+
r = parse_size(rvalue, 1000, &v);
146+
if (r < 0) {
147+
log_syntax(unit, LOG_ERR, filename, line, r,
148+
"Failed to parse '%s=', ignoring assignment: %s",
149+
lvalue, rvalue);
150+
return 0;
151+
}
152+
153+
if (v < QFQ_MIN_MAX_PACKET || v > QFQ_MAX_MAX_PACKET) {
154+
log_syntax(unit, LOG_ERR, filename, line, 0,
155+
"Invalid '%s=', ignoring assignment: %s",
156+
lvalue, rvalue);
157+
return 0;
158+
}
159+
160+
qfq->max_packet = (uint32_t) v;
161+
tclass = NULL;
162+
163+
return 0;
164+
}
165+
166+
const TClassVTable qfq_tclass_vtable = {
167+
.object_size = sizeof(QuickFairQueueingClass),
168+
.tca_kind = "qfq",
169+
.fill_message = quick_fair_queueing_class_fill_message,
170+
};

src/network/tc/qfq.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright © 2020 VMware, Inc. */
33
#pragma once
44

5+
#include "conf-parser.h"
56
#include "qdisc.h"
67

78
typedef struct QuickFairQueueing {
@@ -10,3 +11,16 @@ typedef struct QuickFairQueueing {
1011

1112
DEFINE_QDISC_CAST(QFQ, QuickFairQueueing);
1213
extern const QDiscVTable qfq_vtable;
14+
15+
typedef struct QuickFairQueueingClass {
16+
TClass meta;
17+
18+
uint32_t weight;
19+
uint32_t max_packet;
20+
} QuickFairQueueingClass;
21+
22+
DEFINE_TCLASS_CAST(QFQ, QuickFairQueueingClass);
23+
extern const TClassVTable qfq_tclass_vtable;
24+
25+
CONFIG_PARSER_PROTOTYPE(config_parse_quick_fair_queueing_weight);
26+
CONFIG_PARSER_PROTOTYPE(config_parse_quick_fair_queueing_max_packet);

src/network/tc/tclass.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX] = {
1919
[TCLASS_KIND_DRR] = &drr_tclass_vtable,
2020
[TCLASS_KIND_HTB] = &htb_tclass_vtable,
21+
[TCLASS_KIND_QFQ] = &qfq_tclass_vtable,
2122
};
2223

2324
static int tclass_new(TClassKind kind, TClass **ret) {

src/network/tc/tclass.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
typedef enum TClassKind {
1212
TCLASS_KIND_DRR,
1313
TCLASS_KIND_HTB,
14+
TCLASS_KIND_QFQ,
1415
_TCLASS_KIND_MAX,
1516
_TCLASS_KIND_INVALID = -1,
1617
} TClassKind;
@@ -67,3 +68,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_tclass_classid);
6768

6869
#include "drr.h"
6970
#include "htb.h"
71+
#include "qfq.h"

test/fuzz/fuzz-network-parser/directives.network

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ PacketLimit=
414414
[QuickFairQueueing]
415415
Parent=
416416
Handle=
417+
[QuickFairQueueingClass]
418+
Parent=
419+
ClassId=
420+
Weight=
421+
MaxPacketSize=
417422
[DeficitRoundRobinScheduler]
418423
Parent=
419424
Handle=

0 commit comments

Comments
 (0)