From: Yu Watanabe Date: Mon, 10 Feb 2020 11:53:00 +0000 (+0900) Subject: network: introduce TrafficControlKind to prepare for supporting tc class X-Git-Tag: v246-rc1~781^2~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=34658df256f48626ac8370842e798991de7a842b;p=thirdparty%2Fsystemd.git network: introduce TrafficControlKind to prepare for supporting tc class --- diff --git a/src/network/meson.build b/src/network/meson.build index 1f5175e053f..ce0e7fb0ddd 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -125,6 +125,8 @@ sources = files(''' tc/tbf.h tc/tc-util.c tc/tc-util.h + tc/tc.c + tc/tc.h tc/teql.c tc/teql.h '''.split()) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 3dca043d99c..bd9d37aad20 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -34,7 +34,6 @@ #include "networkd-radv.h" #include "networkd-routing-policy-rule.h" #include "networkd-wifi.h" -#include "qdisc.h" #include "set.h" #include "socket-util.h" #include "stat-util.h" @@ -42,6 +41,7 @@ #include "string-table.h" #include "strv.h" #include "sysctl-util.h" +#include "tc.h" #include "tmpfile-util.h" #include "udev-util.h" #include "util.h" @@ -1116,7 +1116,7 @@ void link_check_ready(Link *link) { if (!link->routing_policy_rules_configured) return; - if (!link->qdiscs_configured) + if (!link->tc_configured) return; if (link_has_carrier(link) || !link->network->configure_without_carrier) { @@ -2702,24 +2702,24 @@ static int link_configure_ipv4_dad(Link *link) { return 0; } -static int link_configure_qdiscs(Link *link) { - QDisc *qdisc; +static int link_configure_traffic_control(Link *link) { + TrafficControl *tc; Iterator i; int r; - link->qdiscs_configured = false; - link->qdisc_messages = 0; + link->tc_configured = false; + link->tc_messages = 0; - ORDERED_HASHMAP_FOREACH(qdisc, link->network->qdiscs_by_section, i) { - r = qdisc_configure(link, qdisc); + ORDERED_HASHMAP_FOREACH(tc, link->network->tc_by_section, i) { + r = traffic_control_configure(link, tc); if (r < 0) return r; } - if (link->qdisc_messages == 0) - link->qdiscs_configured = true; + if (link->tc_messages == 0) + link->tc_configured = true; else - log_link_debug(link, "Configuring queuing discipline (qdisc)"); + log_link_debug(link, "Configuring traffic control"); return 0; } @@ -2731,7 +2731,7 @@ static int link_configure(Link *link) { assert(link->network); assert(link->state == LINK_STATE_INITIALIZED); - r = link_configure_qdiscs(link); + r = link_configure_traffic_control(link); if (r < 0) return r; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 59a51073113..3d07d882cda 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -80,7 +80,7 @@ typedef struct Link { unsigned nexthop_messages; unsigned routing_policy_rule_messages; unsigned routing_policy_rule_remove_messages; - unsigned qdisc_messages; + unsigned tc_messages; unsigned enslaving; Set *addresses; @@ -116,7 +116,7 @@ typedef struct Link { bool static_routes_ready:1; bool static_nexthops_configured:1; bool routing_policy_rules_configured:1; - bool qdiscs_configured:1; + bool tc_configured:1; bool setting_mtu:1; bool setting_genmode:1; bool ipv6_mtu_set:1; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index e6be07d9a19..5ca5ad32cd4 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -22,6 +22,7 @@ #include "string-table.h" #include "string-util.h" #include "strv.h" +#include "tc.h" #include "util.h" /* Let's assume that anything above this number is a user misconfiguration. */ @@ -154,7 +155,7 @@ int network_verify(Network *network) { Prefix *prefix, *prefix_next; Route *route, *route_next; FdbEntry *fdb, *fdb_next; - QDisc *qdisc; + TrafficControl *tc; Iterator i; assert(network); @@ -316,9 +317,9 @@ int network_verify(Network *network) { routing_policy_rule_free(rule); bool has_root = false, has_clsact = false; - ORDERED_HASHMAP_FOREACH(qdisc, network->qdiscs_by_section, i) - if (qdisc_section_verify(qdisc, &has_root, &has_clsact) < 0) - qdisc_free(qdisc); + ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section, i) + if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0) + traffic_control_free(tc); return 0; } @@ -691,7 +692,7 @@ static Network *network_free(Network *network) { hashmap_free(network->prefixes_by_section); hashmap_free(network->route_prefixes_by_section); hashmap_free(network->rules_by_section); - ordered_hashmap_free_with_destructor(network->qdiscs_by_section, qdisc_free); + ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free); if (network->manager && network->manager->duids_requesting_uuid) diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 66f010a7939..3ae1752acc8 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -30,7 +30,6 @@ #include "networkd-routing-policy-rule.h" #include "networkd-util.h" #include "ordered-set.h" -#include "qdisc.h" #include "resolve-util.h" typedef enum IPv6PrivacyExtensions { @@ -274,7 +273,7 @@ struct Network { Hashmap *prefixes_by_section; Hashmap *route_prefixes_by_section; Hashmap *rules_by_section; - OrderedHashmap *qdiscs_by_section; + OrderedHashmap *tc_by_section; /* All kinds of DNS configuration */ struct in_addr_data *dns; diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index 9f60888aa5c..2168234a71c 100644 --- a/src/network/tc/qdisc.c +++ b/src/network/tc/qdisc.c @@ -36,6 +36,7 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) { return -ENOMEM; *qdisc = (QDisc) { + .meta.kind = TC_KIND_QDISC, .family = AF_UNSPEC, .parent = TC_H_ROOT, .kind = kind, @@ -45,6 +46,7 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) { if (!qdisc) return -ENOMEM; + qdisc->meta.kind = TC_KIND_QDISC, qdisc->family = AF_UNSPEC; qdisc->parent = TC_H_ROOT; qdisc->kind = kind; @@ -64,7 +66,8 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) { int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret) { _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; _cleanup_(qdisc_freep) QDisc *qdisc = NULL; - QDisc *existing; + TrafficControl *existing; + QDisc *q = NULL; int r; assert(network); @@ -76,15 +79,20 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns if (r < 0) return r; - existing = ordered_hashmap_get(network->qdiscs_by_section, n); + existing = ordered_hashmap_get(network->tc_by_section, n); if (existing) { - if (existing->kind != _QDISC_KIND_INVALID && + if (existing->kind != TC_KIND_QDISC) + return -EINVAL; + + q = TC_TO_QDISC(existing); + + if (q->kind != _QDISC_KIND_INVALID && kind != _QDISC_KIND_INVALID && - existing->kind != kind) + q->kind != kind) return -EINVAL; - if (existing->kind == kind || kind == _QDISC_KIND_INVALID) { - *ret = existing; + if (q->kind == kind || kind == _QDISC_KIND_INVALID) { + *ret = q; return 0; } } @@ -93,23 +101,23 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns if (r < 0) return r; - if (existing) { - qdisc->family = existing->family; - qdisc->handle = existing->handle; - qdisc->parent = existing->parent; - qdisc->tca_kind = TAKE_PTR(existing->tca_kind); + if (q) { + qdisc->family = q->family; + qdisc->handle = q->handle; + qdisc->parent = q->parent; + qdisc->tca_kind = TAKE_PTR(q->tca_kind); - qdisc_free(ordered_hashmap_remove(network->qdiscs_by_section, n)); + qdisc_free(q); } qdisc->network = network; qdisc->section = TAKE_PTR(n); - r = ordered_hashmap_ensure_allocated(&network->qdiscs_by_section, &network_config_hash_ops); + r = ordered_hashmap_ensure_allocated(&network->tc_by_section, &network_config_hash_ops); if (r < 0) return r; - r = ordered_hashmap_put(network->qdiscs_by_section, qdisc->section, qdisc); + r = ordered_hashmap_put(network->tc_by_section, qdisc->section, TC(qdisc)); if (r < 0) return r; @@ -122,7 +130,7 @@ void qdisc_free(QDisc *qdisc) { return; if (qdisc->network && qdisc->section) - ordered_hashmap_remove(qdisc->network->qdiscs_by_section, qdisc->section); + ordered_hashmap_remove(qdisc->network->tc_by_section, qdisc->section); network_config_section_free(qdisc->section); @@ -134,8 +142,8 @@ static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(link); - assert(link->qdisc_messages > 0); - link->qdisc_messages--; + assert(link->tc_messages > 0); + link->tc_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; @@ -147,9 +155,9 @@ static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { return 1; } - if (link->qdisc_messages == 0) { - log_link_debug(link, "QDisc configured"); - link->qdiscs_configured = true; + if (link->tc_messages == 0) { + log_link_debug(link, "Traffic control configured"); + link->tc_configured = true; link_check_ready(link); } @@ -206,7 +214,7 @@ int qdisc_configure(Link *link, QDisc *qdisc) { return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); - link->qdisc_messages++; + link->tc_messages++; return 0; } diff --git a/src/network/tc/qdisc.h b/src/network/tc/qdisc.h index 7d9e0ddb06e..f33939d197a 100644 --- a/src/network/tc/qdisc.h +++ b/src/network/tc/qdisc.h @@ -6,6 +6,7 @@ #include "networkd-link.h" #include "networkd-network.h" #include "networkd-util.h" +#include "tc.h" typedef enum QDiscKind { QDISC_KIND_CODEL, @@ -21,6 +22,8 @@ typedef enum QDiscKind { } QDiscKind; typedef struct QDisc { + TrafficControl meta; + NetworkConfigSection *section; Network *network; @@ -66,6 +69,8 @@ int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact); DEFINE_NETWORK_SECTION_FUNCTIONS(QDisc, qdisc_free); +DEFINE_TC_CAST(QDISC, QDisc); + CONFIG_PARSER_PROTOTYPE(config_parse_qdisc_parent); CONFIG_PARSER_PROTOTYPE(config_parse_qdisc_handle); diff --git a/src/network/tc/tc.c b/src/network/tc/tc.c new file mode 100644 index 00000000000..e90ebf30a83 --- /dev/null +++ b/src/network/tc/tc.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "macro.h" +#include "qdisc.h" +#include "tc.h" + +void traffic_control_free(TrafficControl *tc) { + if (!tc) + return; + + switch (tc->kind) { + case TC_KIND_QDISC: + qdisc_free(TC_TO_QDISC(tc)); + break; + default: + assert_not_reached("Invalid traffic control type"); + } +} + +int traffic_control_configure(Link *link, TrafficControl *tc) { + assert(link); + assert(tc); + + switch(tc->kind) { + case TC_KIND_QDISC: + return qdisc_configure(link, TC_TO_QDISC(tc)); + default: + assert_not_reached("Invalid traffic control type"); + } +} + +int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact) { + assert(tc); + + switch(tc->kind) { + case TC_KIND_QDISC: + return qdisc_section_verify(TC_TO_QDISC(tc), qdisc_has_root, qdisc_has_clsact); + default: + assert_not_reached("Invalid traffic control type"); + } +} diff --git a/src/network/tc/tc.h b/src/network/tc/tc.h new file mode 100644 index 00000000000..defa0b774a5 --- /dev/null +++ b/src/network/tc/tc.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "networkd-link.h" + +typedef enum TrafficControlKind { + TC_KIND_QDISC, + TC_KIND_TCLASS, + TC_KIND_FILTER, + _TC_KIND_MAX, + _TC_KIND_INVALID = -1, +} TrafficControlKind; + +typedef struct TrafficControl { + TrafficControlKind kind; +} TrafficControl; + +/* For casting a tc into the various tc kinds */ +#define DEFINE_TC_CAST(UPPERCASE, MixedCase) \ + static inline MixedCase* TC_TO_##UPPERCASE(TrafficControl *tc) { \ + if (_unlikely_(!tc || tc->kind != TC_KIND_##UPPERCASE)) \ + return NULL; \ + \ + return (MixedCase*) tc; \ + } + +/* For casting the various tc kinds into a tc */ +#define TC(tc) (&(tc)->meta) + +void traffic_control_free(TrafficControl *tc); +int traffic_control_configure(Link *link, TrafficControl *tc); +int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact);