diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2020-06-03 15:07:45 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2020-06-03 17:25:44 +0900 |
commit | 4d7ddaf97bb18cd3d75aaf7814e2ec267256ace2 (patch) | |
tree | 42aec745d699f96e7cefd6e821487ac7a71d4929 /src/network/tc | |
parent | b12aaee5ab59bd51e052e3442ed42bee3e0dab7d (diff) | |
download | systemd-4d7ddaf97bb18cd3d75aaf7814e2ec267256ace2.tar.gz |
network: tc: introduce [QuickFairQueueingClass] section
Diffstat (limited to 'src/network/tc')
-rw-r--r-- | src/network/tc/qfq.c | 160 | ||||
-rw-r--r-- | src/network/tc/qfq.h | 14 | ||||
-rw-r--r-- | src/network/tc/tclass.c | 1 | ||||
-rw-r--r-- | src/network/tc/tclass.h | 2 |
4 files changed, 177 insertions, 0 deletions
diff --git a/src/network/tc/qfq.c b/src/network/tc/qfq.c index 8084cda801..71d5b15e81 100644 --- a/src/network/tc/qfq.c +++ b/src/network/tc/qfq.c @@ -1,10 +1,170 @@ /* SPDX-License-Identifier: LGPL-2.1+ * Copyright © 2020 VMware, Inc. */ +#include <linux/pkt_sched.h> + +#include "parse-util.h" #include "qdisc.h" #include "qfq.h" +#include "string-util.h" + +#define QFQ_MAX_WEIGHT (1 << 10) +#define QFQ_MIN_MAX_PACKET 512 +#define QFQ_MAX_MAX_PACKET (1 << 16) const QDiscVTable qfq_vtable = { .object_size = sizeof(QuickFairQueueing), .tca_kind = "qfq", }; + +static int quick_fair_queueing_class_fill_message(Link *link, TClass *tclass, sd_netlink_message *req) { + QuickFairQueueingClass *qfq; + int r; + + assert(link); + assert(tclass); + assert(req); + + qfq = TCLASS_TO_QFQ(tclass); + + r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "qfq"); + if (r < 0) + return log_link_error_errno(link, r, "Could not open container TCA_OPTIONS: %m"); + + if (qfq->weight > 0) { + r = sd_netlink_message_append_u32(req, TCA_QFQ_WEIGHT, qfq->weight); + if (r < 0) + return log_link_error_errno(link, r, "Could not append TCA_QFQ_WEIGHT attribute: %m"); + } + + if (qfq->max_packet > 0) { + r = sd_netlink_message_append_u32(req, TCA_QFQ_LMAX, qfq->max_packet); + if (r < 0) + return log_link_error_errno(link, r, "Could not append TCA_QFQ_LMAX 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_quick_fair_queueing_weight( + 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_(tclass_free_or_set_invalidp) TClass *tclass = NULL; + QuickFairQueueingClass *qfq; + Network *network = data; + uint32_t v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = tclass_new_static(TCLASS_KIND_QFQ, network, filename, section_line, &tclass); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to create traffic control class, ignoring assignment: %m"); + + qfq = TCLASS_TO_QFQ(tclass); + + if (isempty(rvalue)) { + qfq->weight = 0; + tclass = NULL; + return 0; + } + + r = safe_atou32(rvalue, &v); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse '%s=', ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + if (v == 0 || v > QFQ_MAX_WEIGHT) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid '%s=', ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + qfq->weight = v; + tclass = NULL; + + return 0; +} + +int config_parse_quick_fair_queueing_max_packet( + 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_(tclass_free_or_set_invalidp) TClass *tclass = NULL; + QuickFairQueueingClass *qfq; + Network *network = data; + uint64_t v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = tclass_new_static(TCLASS_KIND_QFQ, network, filename, section_line, &tclass); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to create traffic control class, ignoring assignment: %m"); + + qfq = TCLASS_TO_QFQ(tclass); + + if (isempty(rvalue)) { + qfq->max_packet = 0; + tclass = NULL; + return 0; + } + + r = parse_size(rvalue, 1000, &v); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse '%s=', ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + if (v < QFQ_MIN_MAX_PACKET || v > QFQ_MAX_MAX_PACKET) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid '%s=', ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + qfq->max_packet = (uint32_t) v; + tclass = NULL; + + return 0; +} + +const TClassVTable qfq_tclass_vtable = { + .object_size = sizeof(QuickFairQueueingClass), + .tca_kind = "qfq", + .fill_message = quick_fair_queueing_class_fill_message, +}; diff --git a/src/network/tc/qfq.h b/src/network/tc/qfq.h index aa1bad219b..10bab3e642 100644 --- a/src/network/tc/qfq.h +++ b/src/network/tc/qfq.h @@ -2,6 +2,7 @@ * Copyright © 2020 VMware, Inc. */ #pragma once +#include "conf-parser.h" #include "qdisc.h" typedef struct QuickFairQueueing { @@ -10,3 +11,16 @@ typedef struct QuickFairQueueing { DEFINE_QDISC_CAST(QFQ, QuickFairQueueing); extern const QDiscVTable qfq_vtable; + +typedef struct QuickFairQueueingClass { + TClass meta; + + uint32_t weight; + uint32_t max_packet; +} QuickFairQueueingClass; + +DEFINE_TCLASS_CAST(QFQ, QuickFairQueueingClass); +extern const TClassVTable qfq_tclass_vtable; + +CONFIG_PARSER_PROTOTYPE(config_parse_quick_fair_queueing_weight); +CONFIG_PARSER_PROTOTYPE(config_parse_quick_fair_queueing_max_packet); diff --git a/src/network/tc/tclass.c b/src/network/tc/tclass.c index 219ffa2ea6..4f75e1b42d 100644 --- a/src/network/tc/tclass.c +++ b/src/network/tc/tclass.c @@ -18,6 +18,7 @@ const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX] = { [TCLASS_KIND_DRR] = &drr_tclass_vtable, [TCLASS_KIND_HTB] = &htb_tclass_vtable, + [TCLASS_KIND_QFQ] = &qfq_tclass_vtable, }; static int tclass_new(TClassKind kind, TClass **ret) { diff --git a/src/network/tc/tclass.h b/src/network/tc/tclass.h index 217dbfe001..dc6886ac3f 100644 --- a/src/network/tc/tclass.h +++ b/src/network/tc/tclass.h @@ -11,6 +11,7 @@ typedef enum TClassKind { TCLASS_KIND_DRR, TCLASS_KIND_HTB, + TCLASS_KIND_QFQ, _TCLASS_KIND_MAX, _TCLASS_KIND_INVALID = -1, } TClassKind; @@ -67,3 +68,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_tclass_classid); #include "drr.h" #include "htb.h" +#include "qfq.h" |