]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: traffic control: drop meta from QDisc and TClass
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 24 Feb 2022 07:08:50 +0000 (16:08 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 26 Feb 2022 05:58:01 +0000 (14:58 +0900)
Since #22248, it is not necessary to manage QDisc and TClass in same Set
or Hashmap. Let's manage them independently.

14 files changed:
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-queue.c
src/network/networkd-queue.h
src/network/tc/ets.c
src/network/tc/htb.c
src/network/tc/qdisc.c
src/network/tc/qdisc.h
src/network/tc/tc.c
src/network/tc/tc.h
src/network/tc/tclass.c
src/network/tc/tclass.h

index e46f209e7aecaf86170f1922371f3e43b8c1a378..48f8e40fb40107902c73fa9b98353c2f97b96884 100644 (file)
@@ -210,7 +210,8 @@ static Link *link_free(Link *link) {
         link->nexthops = set_free(link->nexthops);
         link->neighbors = set_free(link->neighbors);
         link->addresses = set_free(link->addresses);
-        link->traffic_control = set_free(link->traffic_control);
+        link->qdiscs = set_free(link->qdiscs);
+        link->tclasses = set_free(link->tclasses);
 
         link->dhcp_pd_prefixes = set_free(link->dhcp_pd_prefixes);
 
index 645a8e7147888a4165844d18a699b44e2d283ff3..733ac128efbf6050d3ee674aca87697eb1f0a2e3 100644 (file)
@@ -113,7 +113,8 @@ typedef struct Link {
         Set *neighbors;
         Set *routes;
         Set *nexthops;
-        Set *traffic_control;
+        Set *qdiscs;
+        Set *tclasses;
 
         sd_dhcp_client *dhcp_client;
         sd_dhcp_lease *dhcp_lease;
index eeededcb6c81add2814729839953715b649e7df4..c6dceef1e9530ca4aa384f6126a3db9b2025ed30 100644 (file)
@@ -33,6 +33,7 @@
 #include "networkd-sriov.h"
 #include "parse-util.h"
 #include "path-lookup.h"
+#include "qdisc.h"
 #include "radv-internal.h"
 #include "set.h"
 #include "socket-util.h"
@@ -40,7 +41,7 @@
 #include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
-#include "tc.h"
+#include "tclass.h"
 #include "util.h"
 
 /* Let's assume that anything above this number is a user misconfiguration. */
@@ -322,7 +323,8 @@ int network_verify(Network *network) {
         network_drop_invalid_prefixes(network);
         network_drop_invalid_route_prefixes(network);
         network_drop_invalid_routing_policy_rules(network);
-        network_drop_invalid_traffic_control(network);
+        network_drop_invalid_qdisc(network);
+        network_drop_invalid_tclass(network);
         r = sr_iov_drop_invalid_sections(UINT32_MAX, network->sr_iov_by_section);
         if (r < 0)
                 return r;
@@ -756,7 +758,8 @@ static Network *network_free(Network *network) {
         hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free);
         hashmap_free_with_destructor(network->dhcp_static_leases_by_section, dhcp_static_lease_free);
         ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
-        hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
+        hashmap_free_with_destructor(network->qdiscs_by_section, qdisc_free);
+        hashmap_free_with_destructor(network->tclasses_by_section, tclass_free);
 
         free(network->name);
 
index 299d84ed8b590aec7430df413c7dcc2891ed497b..74d71735fbca4e05b94bcb532e16d49451eed109 100644 (file)
@@ -335,7 +335,8 @@ struct Network {
         Hashmap *route_prefixes_by_section;
         Hashmap *rules_by_section;
         Hashmap *dhcp_static_leases_by_section;
-        Hashmap *tc_by_section;
+        Hashmap *qdiscs_by_section;
+        Hashmap *tclasses_by_section;
         OrderedHashmap *sr_iov_by_section;
 
         /* All kinds of DNS configuration */
index 5d06735774a1bef4763a726a94ef69f07a36faae..5f420c08c37e3af3d4113cb4ce50e46e7d4e4615 100644 (file)
@@ -16,7 +16,8 @@
 #include "networkd-routing-policy-rule.h"
 #include "networkd-queue.h"
 #include "networkd-setlink.h"
-#include "tc.h"
+#include "qdisc.h"
+#include "tclass.h"
 
 static void request_free_object(RequestType type, void *object) {
         switch (type) {
@@ -63,8 +64,11 @@ static void request_free_object(RequestType type, void *object) {
                 break;
         case REQUEST_TYPE_SET_LINK:
                 break;
-        case REQUEST_TYPE_TRAFFIC_CONTROL:
-                traffic_control_free(object);
+        case REQUEST_TYPE_TC_QDISC:
+                qdisc_free(object);
+                break;
+        case REQUEST_TYPE_TC_CLASS:
+                tclass_free(object);
                 break;
         case REQUEST_TYPE_UP_DOWN:
                 break;
@@ -154,8 +158,11 @@ static void request_hash_func(const Request *req, struct siphash *state) {
         case REQUEST_TYPE_SET_LINK:
                 trivial_hash_func(req->set_link_operation_ptr, state);
                 break;
-        case REQUEST_TYPE_TRAFFIC_CONTROL:
-                traffic_control_hash_func(req->traffic_control, state);
+        case REQUEST_TYPE_TC_QDISC:
+                qdisc_hash_func(req->qdisc, state);
+                break;
+        case REQUEST_TYPE_TC_CLASS:
+                tclass_hash_func(req->tclass, state);
                 break;
         case REQUEST_TYPE_UP_DOWN:
                 break;
@@ -215,8 +222,10 @@ static int request_compare_func(const struct Request *a, const struct Request *b
                 return routing_policy_rule_compare_func(a->rule, b->rule);
         case REQUEST_TYPE_SET_LINK:
                 return trivial_compare_func(a->set_link_operation_ptr, b->set_link_operation_ptr);
-        case REQUEST_TYPE_TRAFFIC_CONTROL:
-                return traffic_control_compare_func(a->traffic_control, b->traffic_control);
+        case REQUEST_TYPE_TC_QDISC:
+                return qdisc_compare_func(a->qdisc, b->qdisc);
+        case REQUEST_TYPE_TC_CLASS:
+                return tclass_compare_func(a->tclass, b->tclass);
         case REQUEST_TYPE_UP_DOWN:
                 return 0;
         default:
@@ -305,7 +314,8 @@ int link_queue_request(
                       REQUEST_TYPE_DHCP6_CLIENT,
                       REQUEST_TYPE_NDISC,
                       REQUEST_TYPE_RADV,
-                      REQUEST_TYPE_TRAFFIC_CONTROL) ||
+                      REQUEST_TYPE_TC_QDISC,
+                      REQUEST_TYPE_TC_CLASS) ||
                netlink_handler);
 
         req = new(Request, 1);
@@ -414,8 +424,11 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
                         case REQUEST_TYPE_SET_LINK:
                                 r = request_process_set_link(req);
                                 break;
-                        case REQUEST_TYPE_TRAFFIC_CONTROL:
-                                r = request_process_traffic_control(req);
+                        case REQUEST_TYPE_TC_QDISC:
+                                r = request_process_qdisc(req);
+                                break;
+                        case REQUEST_TYPE_TC_CLASS:
+                                r = request_process_tclass(req);
                                 break;
                         case REQUEST_TYPE_UP_DOWN:
                                 r = request_process_link_up_or_down(req);
index 9b2c6baf44056410617d95d0c249fbcf8e052efa..593f3dde6e473cbf735b14969b77a79af4585429 100644 (file)
@@ -14,7 +14,8 @@ typedef struct NetDev NetDev;
 typedef struct NextHop NextHop;
 typedef struct Route Route;
 typedef struct RoutingPolicyRule RoutingPolicyRule;
-typedef struct TrafficControl TrafficControl;
+typedef struct QDisc QDisc;
+typedef struct TClass TClass;
 
 typedef enum RequestType {
         REQUEST_TYPE_ACTIVATE_LINK,
@@ -35,7 +36,8 @@ typedef enum RequestType {
         REQUEST_TYPE_ROUTE,
         REQUEST_TYPE_ROUTING_POLICY_RULE,
         REQUEST_TYPE_SET_LINK,
-        REQUEST_TYPE_TRAFFIC_CONTROL,
+        REQUEST_TYPE_TC_CLASS,
+        REQUEST_TYPE_TC_QDISC,
         REQUEST_TYPE_UP_DOWN,
         _REQUEST_TYPE_MAX,
         _REQUEST_TYPE_INVALID = -EINVAL,
@@ -57,7 +59,8 @@ typedef struct Request {
                 RoutingPolicyRule *rule;
                 void *set_link_operation_ptr;
                 NetDev *netdev;
-                TrafficControl *traffic_control;
+                QDisc *qdisc;
+                TClass *tclass;
                 void *object;
         };
         void *userdata;
index c4d594cd1bedc682d70b965c037d765a5a1212f8..00c46f24a414edc680b5b139c5eb6a97bdafb65b 100644 (file)
@@ -5,6 +5,7 @@
 #include "alloc-util.h"
 #include "conf-parser.h"
 #include "ets.h"
+#include "extract-word.h"
 #include "memory-util.h"
 #include "netlink-util.h"
 #include "parse-util.h"
index 78fcd3f05fe2e505b7f1d7f93b877c8008563983..f50b0e50107e0934b152418829e417cf29462d6b 100644 (file)
@@ -5,6 +5,7 @@
 #include "alloc-util.h"
 #include "conf-parser.h"
 #include "netlink-util.h"
+#include "networkd-link.h"
 #include "parse-util.h"
 #include "qdisc.h"
 #include "htb.h"
index 665b2a270c89af82585209bb530fb8d01d442bf8..d69d8b48e99bf281fa885dea7818fd1e10f85533 100644 (file)
@@ -7,7 +7,9 @@
 #include "conf-parser.h"
 #include "in-addr-util.h"
 #include "netlink-util.h"
+#include "networkd-link.h"
 #include "networkd-manager.h"
+#include "networkd-network.h"
 #include "networkd-queue.h"
 #include "parse-util.h"
 #include "qdisc.h"
@@ -50,7 +52,6 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) {
                         return -ENOMEM;
 
                 *qdisc = (QDisc) {
-                        .meta.kind = TC_KIND_QDISC,
                         .parent = TC_H_ROOT,
                         .kind = kind,
                 };
@@ -60,7 +61,6 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) {
                 if (!qdisc)
                         return -ENOMEM;
 
-                qdisc->meta.kind = TC_KIND_QDISC,
                 qdisc->parent = TC_H_ROOT;
                 qdisc->kind = kind;
 
@@ -79,8 +79,7 @@ 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_(config_section_freep) ConfigSection *n = NULL;
         _cleanup_(qdisc_freep) QDisc *qdisc = NULL;
-        TrafficControl *existing;
-        QDisc *q = NULL;
+        QDisc *existing;
         int r;
 
         assert(network);
@@ -92,20 +91,15 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
         if (r < 0)
                 return r;
 
-        existing = hashmap_get(network->tc_by_section, n);
+        existing = hashmap_get(network->qdiscs_by_section, n);
         if (existing) {
-                if (existing->kind != TC_KIND_QDISC)
-                        return -EINVAL;
-
-                q = TC_TO_QDISC(existing);
-
-                if (q->kind != _QDISC_KIND_INVALID &&
+                if (existing->kind != _QDISC_KIND_INVALID &&
                     kind != _QDISC_KIND_INVALID &&
-                    q->kind != kind)
+                    existing->kind != kind)
                         return -EINVAL;
 
-                if (q->kind == kind || kind == _QDISC_KIND_INVALID) {
-                        *ret = q;
+                if (existing->kind == kind || kind == _QDISC_KIND_INVALID) {
+                        *ret = existing;
                         return 0;
                 }
         }
@@ -114,19 +108,19 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
         if (r < 0)
                 return r;
 
-        if (q) {
-                qdisc->handle = q->handle;
-                qdisc->parent = q->parent;
-                qdisc->tca_kind = TAKE_PTR(q->tca_kind);
+        if (existing) {
+                qdisc->handle = existing->handle;
+                qdisc->parent = existing->parent;
+                qdisc->tca_kind = TAKE_PTR(existing->tca_kind);
 
-                qdisc_free(q);
+                qdisc_free(existing);
         }
 
         qdisc->network = network;
         qdisc->section = TAKE_PTR(n);
         qdisc->source = NETWORK_CONFIG_SOURCE_STATIC;
 
-        r = hashmap_ensure_put(&network->tc_by_section, &config_section_hash_ops, qdisc->section, TC(qdisc));
+        r = hashmap_ensure_put(&network->qdiscs_by_section, &config_section_hash_ops, qdisc->section, qdisc);
         if (r < 0)
                 return r;
 
@@ -139,12 +133,12 @@ QDisc* qdisc_free(QDisc *qdisc) {
                 return NULL;
 
         if (qdisc->network && qdisc->section)
-                hashmap_remove(qdisc->network->tc_by_section, qdisc->section);
+                hashmap_remove(qdisc->network->qdiscs_by_section, qdisc->section);
 
         config_section_free(qdisc->section);
 
         if (qdisc->link)
-                set_remove(qdisc->link->traffic_control, TC(qdisc));
+                set_remove(qdisc->link->qdiscs, qdisc);
 
         free(qdisc->tca_kind);
         return mfree(qdisc);
@@ -183,19 +177,25 @@ int qdisc_compare_func(const QDisc *a, const QDisc *b) {
         return strcmp_ptr(qdisc_get_tca_kind(a), qdisc_get_tca_kind(b));
 }
 
+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
+        qdisc_hash_ops,
+        QDisc,
+        qdisc_hash_func,
+        qdisc_compare_func,
+        qdisc_free);
+
 static int qdisc_get(Link *link, const QDisc *in, QDisc **ret) {
-        TrafficControl *existing;
-        int r;
+        QDisc *existing;
 
         assert(link);
         assert(in);
 
-        r = traffic_control_get(link, TC(in), &existing);
-        if (r < 0)
-                return r;
+        existing = set_get(link->qdiscs, in);
+        if (!existing)
+                return -ENOENT;
 
         if (ret)
-                *ret = TC_TO_QDISC(existing);
+                *ret = existing;
         return 0;
 }
 
@@ -205,9 +205,11 @@ static int qdisc_add(Link *link, QDisc *qdisc) {
         assert(link);
         assert(qdisc);
 
-        r = traffic_control_add(link, TC(qdisc));
+        r = set_ensure_put(&link->qdiscs, &qdisc_hash_ops, qdisc);
         if (r < 0)
                 return r;
+        if (r == 0)
+                return -EEXIST;
 
         qdisc->link = link;
         return 0;
@@ -261,20 +263,13 @@ static void log_qdisc_debug(QDisc *qdisc, Link *link, const char *str) {
 }
 
 int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *kind, QDisc **ret) {
-        TrafficControl *tc;
+        QDisc *qdisc;
 
         assert(link);
 
         handle = TC_H_MAJ(handle);
 
-        SET_FOREACH(tc, link->traffic_control) {
-                QDisc *qdisc;
-
-                if (tc->kind != TC_KIND_QDISC)
-                        continue;
-
-                qdisc = TC_TO_QDISC(tc);
-
+        SET_FOREACH(qdisc, link->qdiscs) {
                 if (qdisc->handle != handle)
                         continue;
 
@@ -324,10 +319,11 @@ static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         return 1;
 }
 
-int qdisc_configure(Link *link, QDisc *qdisc) {
+static int qdisc_configure(QDisc *qdisc, Link *link) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
+        assert(qdisc);
         assert(link);
         assert(link->manager);
         assert(link->manager->rtnl);
@@ -355,14 +351,15 @@ int qdisc_configure(Link *link, QDisc *qdisc) {
                 return log_link_debug_errno(link, r, "Could not send netlink message: %m");
 
         link_ref(link);
-
-        qdisc_enter_configuring(qdisc);
         return 0;
 }
 
-int qdisc_is_ready_to_configure(Link *link, QDisc *qdisc) {
-        assert(link);
+static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) {
         assert(qdisc);
+        assert(link);
+
+        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
+                return false;
 
         if (IN_SET(qdisc->parent, TC_H_ROOT, TC_H_CLSACT)) /* TC_H_CLSACT == TC_H_INGRESS */
                 return true;
@@ -370,6 +367,26 @@ int qdisc_is_ready_to_configure(Link *link, QDisc *qdisc) {
         return link_find_tclass(link, qdisc->parent, NULL) >= 0;
 }
 
+int request_process_qdisc(Request *req) {
+        QDisc *qdisc;
+        Link *link;
+        int r;
+
+        assert(req);
+        assert_se(link = req->link);
+        assert_se(qdisc = req->qdisc);
+
+        if (!qdisc_is_ready_to_configure(qdisc, link))
+                return 0;
+
+        r = qdisc_configure(qdisc, link);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to configure QDisc: %m");
+
+        qdisc_enter_configuring(qdisc);
+        return 1;
+}
+
 int link_request_qdisc(Link *link, QDisc *qdisc) {
         QDisc *existing;
         int r;
@@ -393,7 +410,7 @@ int link_request_qdisc(Link *link, QDisc *qdisc) {
                 existing->source = qdisc->source;
 
         log_qdisc_debug(existing, link, "Requesting");
-        r = link_queue_request(link, REQUEST_TYPE_TRAFFIC_CONTROL, TC(existing), false,
+        r = link_queue_request(link, REQUEST_TYPE_TC_QDISC, existing, false,
                                &link->tc_messages, NULL, NULL);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to request QDisc: %m");
@@ -511,7 +528,7 @@ int manager_rtnl_process_qdisc(sd_netlink *rtnl, sd_netlink_message *message, Ma
         return 1;
 }
 
-int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact) {
+static int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact) {
         int r;
 
         assert(qdisc);
@@ -546,6 +563,17 @@ int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact) {
         return 0;
 }
 
+void network_drop_invalid_qdisc(Network *network) {
+        bool has_root = false, has_clsact = false;
+        QDisc *qdisc;
+
+        assert(network);
+
+        HASHMAP_FOREACH(qdisc, network->qdiscs_by_section)
+                if (qdisc_section_verify(qdisc, &has_root, &has_clsact) < 0)
+                        qdisc_free(qdisc);
+}
+
 int config_parse_qdisc_parent(
                 const char *unit,
                 const char *filename,
index 1e4b72e271f6e7c1a70230fa3c8011ee88ff65f9..54afe97ced1fb5be11df3d99a9ef8ba2cf41c84d 100644 (file)
@@ -3,10 +3,12 @@
 #pragma once
 
 #include "conf-parser.h"
-#include "networkd-link.h"
-#include "networkd-network.h"
 #include "networkd-util.h"
-#include "tc.h"
+
+typedef struct Link Link;
+typedef struct Manager Manager;
+typedef struct Network Network;
+typedef struct Request Request;
 
 typedef enum QDiscKind {
         QDISC_KIND_BFIFO,
@@ -35,8 +37,6 @@ typedef enum QDiscKind {
 } QDiscKind;
 
 typedef struct QDisc {
-        TrafficControl meta;
-
         Link *link;
         Network *network;
         ConfigSection *section;
@@ -72,30 +72,25 @@ extern const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX];
                 return (MixedCase*) q;                                    \
         }
 
-/* For casting the various qdisc kinds into a qdisc */
-#define QDISC(q) (&(q)->meta)
-
 DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(QDisc, qdisc);
 
 QDisc* qdisc_free(QDisc *qdisc);
 int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret);
 
-void qdisc_hash_func(const QDisc *qdic, struct siphash *state);
+void qdisc_hash_func(const QDisc *qdisc, struct siphash *state);
 int qdisc_compare_func(const QDisc *a, const QDisc *b);
 
 int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *kind, QDisc **qdisc);
 
+int request_process_qdisc(Request *req);
 int link_request_qdisc(Link *link, QDisc *qdisc);
-int qdisc_is_ready_to_configure(Link *link, QDisc *qdisc);
-int qdisc_configure(Link *link, QDisc *qdisc);
-int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact);
+
+void network_drop_invalid_qdisc(Network *network);
 
 int manager_rtnl_process_qdisc(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
 
 DEFINE_SECTION_CLEANUP_FUNCTIONS(QDisc, qdisc_free);
 
-DEFINE_TC_CAST(QDISC, QDisc);
-
 CONFIG_PARSER_PROTOTYPE(config_parse_qdisc_parent);
 CONFIG_PARSER_PROTOTYPE(config_parse_qdisc_handle);
 
index 796036c0718c9cb10e4c97e3efb1b12d13b7f3be..8a1c5b3a3b3a12ca94acaa695ab7f089bedbe06f 100644 (file)
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include "macro.h"
-#include "networkd-queue.h"
+#include "networkd-link.h"
+#include "networkd-network.h"
 #include "qdisc.h"
 #include "tc.h"
 #include "tclass.h"
 
-void traffic_control_free(TrafficControl *tc) {
-        if (!tc)
-                return;
-
-        switch (tc->kind) {
-        case TC_KIND_QDISC:
-                qdisc_free(TC_TO_QDISC(tc));
-                break;
-        case TC_KIND_TCLASS:
-                tclass_free(TC_TO_TCLASS(tc));
-                break;
-        default:
-                assert_not_reached();
-        }
-}
-
-void traffic_control_hash_func(const TrafficControl *tc, struct siphash *state) {
-        assert(tc);
-        assert(state);
-
-        siphash24_compress(&tc->kind, sizeof(tc->kind), state);
-
-        switch (tc->kind) {
-        case TC_KIND_QDISC:
-                qdisc_hash_func(TC_TO_QDISC_CONST(tc), state);
-                break;
-        case TC_KIND_TCLASS:
-                tclass_hash_func(TC_TO_TCLASS_CONST(tc), state);
-                break;
-        default:
-                assert_not_reached();
-        }
-}
-
-int traffic_control_compare_func(const TrafficControl *a, const TrafficControl *b) {
-        int r;
-
-        assert(a);
-        assert(b);
-
-        r = CMP(a->kind, b->kind);
-        if (r != 0)
-                return r;
-
-        switch (a->kind) {
-        case TC_KIND_QDISC:
-                return qdisc_compare_func(TC_TO_QDISC_CONST(a), TC_TO_QDISC_CONST(b));
-        case TC_KIND_TCLASS:
-                return tclass_compare_func(TC_TO_TCLASS_CONST(a), TC_TO_TCLASS_CONST(b));
-        default:
-                assert_not_reached();
-        }
-}
-
-DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
-        traffic_control_hash_ops,
-        TrafficControl,
-        traffic_control_hash_func,
-        traffic_control_compare_func,
-        traffic_control_free);
-
-int traffic_control_get(Link *link, const TrafficControl *in, TrafficControl **ret) {
-        TrafficControl *existing;
-
-        assert(link);
-        assert(in);
-
-        existing = set_get(link->traffic_control, in);
-        if (!existing)
-                return -ENOENT;
-
-        if (ret)
-                *ret = existing;
-        return 0;
-}
-
-int traffic_control_add(Link *link, TrafficControl *tc) {
-        int r;
-
-        assert(link);
-        assert(tc);
-
-        /* This must be called only from qdisc_add() or tclass_add(). */
-
-        r = set_ensure_put(&link->traffic_control, &traffic_control_hash_ops, tc);
-        if (r < 0)
-                return r;
-        if (r == 0)
-                return -EEXIST;
-
-        return 0;
-}
-
-static 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));
-        case TC_KIND_TCLASS:
-                return tclass_configure(link, TC_TO_TCLASS(tc));
-        default:
-                assert_not_reached();
-        }
-}
-
-static int link_request_traffic_control_one(Link *link, TrafficControl *tc) {
-        assert(link);
-        assert(tc);
-
-        switch (tc->kind) {
-        case TC_KIND_QDISC:
-                return link_request_qdisc(link, TC_TO_QDISC(tc));
-        case TC_KIND_TCLASS:
-                return link_request_tclass(link, TC_TO_TCLASS(tc));
-        default:
-                assert_not_reached();
-        }
-}
-
 int link_request_traffic_control(Link *link) {
-        TrafficControl *tc;
+        TClass *tclass;
+        QDisc *qdisc;
         int r;
 
         assert(link);
@@ -136,8 +17,14 @@ int link_request_traffic_control(Link *link) {
 
         link->tc_configured = false;
 
-        HASHMAP_FOREACH(tc, link->network->tc_by_section) {
-                r = link_request_traffic_control_one(link, tc);
+        HASHMAP_FOREACH(qdisc, link->network->qdiscs_by_section) {
+                r = link_request_qdisc(link, qdisc);
+                if (r < 0)
+                        return r;
+        }
+
+        HASHMAP_FOREACH(tclass, link->network->tclasses_by_section) {
+                r = link_request_tclass(link, tclass);
                 if (r < 0)
                         return r;
         }
@@ -152,67 +39,3 @@ int link_request_traffic_control(Link *link) {
 
         return 0;
 }
-
-static int traffic_control_is_ready_to_configure(Link *link, TrafficControl *tc) {
-        assert(link);
-        assert(tc);
-
-        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
-                return false;
-
-        switch(tc->kind) {
-        case TC_KIND_QDISC:
-                return qdisc_is_ready_to_configure(link, TC_TO_QDISC(tc));
-        case TC_KIND_TCLASS:
-                return tclass_is_ready_to_configure(link, TC_TO_TCLASS(tc));
-        default:
-                assert_not_reached();
-        }
-}
-
-int request_process_traffic_control(Request *req) {
-        TrafficControl *tc;
-        Link *link;
-        int r;
-
-        assert(req);
-        assert(req->traffic_control);
-        assert(req->type == REQUEST_TYPE_TRAFFIC_CONTROL);
-
-        link = ASSERT_PTR(req->link);
-        tc = ASSERT_PTR(req->traffic_control);
-
-        r = traffic_control_is_ready_to_configure(link, tc);
-        if (r <= 0)
-                return r;
-
-        r = traffic_control_configure(link, tc);
-        if (r < 0)
-                return r;
-
-        return 1;
-}
-
-static 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);
-        case TC_KIND_TCLASS:
-                return tclass_section_verify(TC_TO_TCLASS(tc));
-        default:
-                assert_not_reached();
-        }
-}
-
-void network_drop_invalid_traffic_control(Network *network) {
-        bool has_root = false, has_clsact = false;
-        TrafficControl *tc;
-
-        assert(network);
-
-        HASHMAP_FOREACH(tc, network->tc_by_section)
-                if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0)
-                        traffic_control_free(tc);
-}
index 57458ee65e9213a82ed492c74b16a390b36e82d3..6226578ec516aa0a33a720274e6283793b5926d8 100644 (file)
@@ -1,48 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
-#include "networkd-link.h"
-
-typedef struct Request Request;
-
-typedef enum TrafficControlKind {
-        TC_KIND_QDISC,
-        TC_KIND_TCLASS,
-        TC_KIND_FILTER,
-        _TC_KIND_MAX,
-        _TC_KIND_INVALID = -EINVAL,
-} 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;                                 \
-        }                                                               \
-        static inline const MixedCase* TC_TO_##UPPERCASE##_CONST(const TrafficControl *tc) { \
-                if (_unlikely_(!tc || tc->kind != TC_KIND_##UPPERCASE)) \
-                        return NULL;                                    \
-                                                                        \
-                return (const MixedCase*) tc;                           \
-        }
-
-/* For casting the various tc kinds into a tc */
-#define TC(tc) (&(tc)->meta)
-
-void traffic_control_free(TrafficControl *tc);
-void network_drop_invalid_traffic_control(Network *network);
-
-void traffic_control_hash_func(const TrafficControl *tc, struct siphash *state);
-int traffic_control_compare_func(const TrafficControl *a, const TrafficControl *b);
-
-int traffic_control_get(Link *link, const TrafficControl *in, TrafficControl **ret);
-int traffic_control_add(Link *link, TrafficControl *tc);
+typedef struct Link Link;
 
 int link_request_traffic_control(Link *link);
-int request_process_traffic_control(Request *req);
index 676733c33f113aa6eef380d044dc3a040cafbcfa..74df5528f3065e653d2aaa9a5561be7f5894500d 100644 (file)
@@ -7,7 +7,9 @@
 #include "conf-parser.h"
 #include "in-addr-util.h"
 #include "netlink-util.h"
+#include "networkd-link.h"
 #include "networkd-manager.h"
+#include "networkd-network.h"
 #include "networkd-queue.h"
 #include "parse-util.h"
 #include "set.h"
@@ -32,7 +34,6 @@ static int tclass_new(TClassKind kind, TClass **ret) {
                         return -ENOMEM;
 
                 *tclass = (TClass) {
-                        .meta.kind = TC_KIND_TCLASS,
                         .parent = TC_H_ROOT,
                         .kind = kind,
                 };
@@ -42,7 +43,6 @@ static int tclass_new(TClassKind kind, TClass **ret) {
                 if (!tclass)
                         return -ENOMEM;
 
-                tclass->meta.kind = TC_KIND_TCLASS;
                 tclass->parent = TC_H_ROOT;
                 tclass->kind = kind;
 
@@ -61,7 +61,7 @@ static int tclass_new(TClassKind kind, TClass **ret) {
 int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret) {
         _cleanup_(config_section_freep) ConfigSection *n = NULL;
         _cleanup_(tclass_freep) TClass *tclass = NULL;
-        TrafficControl *existing;
+        TClass *existing;
         int r;
 
         assert(network);
@@ -73,19 +73,12 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
         if (r < 0)
                 return r;
 
-        existing = hashmap_get(network->tc_by_section, n);
+        existing = hashmap_get(network->tclasses_by_section, n);
         if (existing) {
-                TClass *t;
-
-                if (existing->kind != TC_KIND_TCLASS)
-                        return -EINVAL;
-
-                t = TC_TO_TCLASS(existing);
-
-                if (t->kind != kind)
+                if (existing->kind != kind)
                         return -EINVAL;
 
-                *ret = t;
+                *ret = existing;
                 return 0;
         }
 
@@ -97,7 +90,7 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
         tclass->section = TAKE_PTR(n);
         tclass->source = NETWORK_CONFIG_SOURCE_STATIC;
 
-        r = hashmap_ensure_put(&network->tc_by_section, &config_section_hash_ops, tclass->section, tclass);
+        r = hashmap_ensure_put(&network->tclasses_by_section, &config_section_hash_ops, tclass->section, tclass);
         if (r < 0)
                 return r;
 
@@ -110,12 +103,12 @@ TClass* tclass_free(TClass *tclass) {
                 return NULL;
 
         if (tclass->network && tclass->section)
-                hashmap_remove(tclass->network->tc_by_section, tclass->section);
+                hashmap_remove(tclass->network->tclasses_by_section, tclass->section);
 
         config_section_free(tclass->section);
 
         if (tclass->link)
-                set_remove(tclass->link->traffic_control, TC(tclass));
+                set_remove(tclass->link->tclasses, tclass);
 
         free(tclass->tca_kind);
         return mfree(tclass);
@@ -154,19 +147,25 @@ int tclass_compare_func(const TClass *a, const TClass *b) {
         return strcmp_ptr(tclass_get_tca_kind(a), tclass_get_tca_kind(b));
 }
 
+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
+        tclass_hash_ops,
+        TClass,
+        tclass_hash_func,
+        tclass_compare_func,
+        tclass_free);
+
 static int tclass_get(Link *link, const TClass *in, TClass **ret) {
-        TrafficControl *existing;
-        int r;
+        TClass *existing;
 
         assert(link);
         assert(in);
 
-        r = traffic_control_get(link, TC(in), &existing);
-        if (r < 0)
-                return r;
+        existing = set_get(link->tclasses, in);
+        if (!existing)
+                return -ENOENT;
 
         if (ret)
-                *ret = TC_TO_TCLASS(existing);
+                *ret = existing;
         return 0;
 }
 
@@ -176,9 +175,11 @@ static int tclass_add(Link *link, TClass *tclass) {
         assert(link);
         assert(tclass);
 
-        r = traffic_control_add(link, TC(tclass));
+        r = set_ensure_put(&link->tclasses, &tclass_hash_ops, tclass);
         if (r < 0)
                 return r;
+        if (r == 0)
+                return -EEXIST;
 
         tclass->link = link;
         return 0;
@@ -214,18 +215,11 @@ static int tclass_dup(const TClass *src, TClass **ret) {
 }
 
 int link_find_tclass(Link *link, uint32_t classid, TClass **ret) {
-        TrafficControl *tc;
+        TClass *tclass;
 
         assert(link);
 
-        SET_FOREACH(tc, link->traffic_control) {
-                TClass *tclass;
-
-                if (tc->kind != TC_KIND_TCLASS)
-                        continue;
-
-                tclass = TC_TO_TCLASS(tc);
-
+        SET_FOREACH(tclass, link->tclasses) {
                 if (tclass->classid != classid)
                         continue;
 
@@ -287,10 +281,11 @@ static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         return 1;
 }
 
-int tclass_configure(Link *link, TClass *tclass) {
+static int tclass_configure(TClass *tclass, Link *link) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
+        assert(tclass);
         assert(link);
         assert(link->manager);
         assert(link->manager->rtnl);
@@ -318,18 +313,39 @@ int tclass_configure(Link *link, TClass *tclass) {
                 return log_link_debug_errno(link, r, "Could not send netlink message: %m");
 
         link_ref(link);
-
-        tclass_enter_configuring(tclass);
         return 0;
 }
 
-int tclass_is_ready_to_configure(Link *link, TClass *tclass) {
-        assert(link);
+static bool tclass_is_ready_to_configure(TClass *tclass, Link *link) {
         assert(tclass);
+        assert(link);
+
+        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
+                return false;
 
         return link_find_qdisc(link, tclass->classid, tclass->parent, tclass_get_tca_kind(tclass), NULL) >= 0;
 }
 
+int request_process_tclass(Request *req) {
+        TClass *tclass;
+        Link *link;
+        int r;
+
+        assert(req);
+        assert_se(link = req->link);
+        assert_se(tclass = req->tclass);
+
+        if (!tclass_is_ready_to_configure(tclass, link))
+                return 0;
+
+        r = tclass_configure(tclass, link);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to configure TClass: %m");
+
+        tclass_enter_configuring(tclass);
+        return 1;
+}
+
 int link_request_tclass(Link *link, TClass *tclass) {
         TClass *existing;
         int r;
@@ -353,7 +369,7 @@ int link_request_tclass(Link *link, TClass *tclass) {
                 existing->source = tclass->source;
 
         log_tclass_debug(existing, link, "Requesting");
-        r = link_queue_request(link, REQUEST_TYPE_TRAFFIC_CONTROL, TC(existing), false,
+        r = link_queue_request(link, REQUEST_TYPE_TC_CLASS, existing, false,
                                &link->tc_messages, NULL, NULL);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to request TClass: %m");
@@ -471,7 +487,7 @@ int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, M
         return 1;
 }
 
-int tclass_section_verify(TClass *tclass) {
+static int tclass_section_verify(TClass *tclass) {
         int r;
 
         assert(tclass);
@@ -488,6 +504,16 @@ int tclass_section_verify(TClass *tclass) {
         return 0;
 }
 
+void network_drop_invalid_tclass(Network *network) {
+        TClass *tclass;
+
+        assert(network);
+
+        HASHMAP_FOREACH(tclass, network->tclasses_by_section)
+                if (tclass_section_verify(tclass) < 0)
+                        tclass_free(tclass);
+}
+
 int config_parse_tclass_parent(
                 const char *unit,
                 const char *filename,
index 6b12fba1e8bda1823d9d9f5652648bdf8d98dce0..c588b38abe5defadd48952eb8f920137ec76c2fd 100644 (file)
@@ -3,10 +3,12 @@
 #pragma once
 
 #include "conf-parser.h"
-#include "networkd-link.h"
-#include "networkd-network.h"
 #include "networkd-util.h"
-#include "tc.h"
+
+typedef struct Link Link;
+typedef struct Manager Manager;
+typedef struct Network Network;
+typedef struct Request Request;
 
 typedef enum TClassKind {
         TCLASS_KIND_DRR,
@@ -17,8 +19,6 @@ typedef enum TClassKind {
 } TClassKind;
 
 typedef struct TClass {
-        TrafficControl meta;
-
         Link *link;
         Network *network;
         ConfigSection *section;
@@ -54,30 +54,25 @@ extern const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX];
                 return (MixedCase*) t;                                    \
         }
 
-/* For casting the various tclass kinds into a tclass */
-#define TCLASS(t) (&(t)->meta)
-
 DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(TClass, tclass);
 
 TClass* tclass_free(TClass *tclass);
 int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret);
 
-void tclass_hash_func(const TClass *tclass, struct siphash *state);
+void tclass_hash_func(const TClass *qdisc, struct siphash *state);
 int tclass_compare_func(const TClass *a, const TClass *b);
 
 int link_find_tclass(Link *link, uint32_t classid, TClass **ret);
 
+int request_process_tclass(Request *req);
 int link_request_tclass(Link *link, TClass *tclass);
-int tclass_is_ready_to_configure(Link *link, TClass *tclass);
-int tclass_configure(Link *link, TClass *tclass);
-int tclass_section_verify(TClass *tclass);
+
+void network_drop_invalid_tclass(Network *network);
 
 int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
 
 DEFINE_SECTION_CLEANUP_FUNCTIONS(TClass, tclass_free);
 
-DEFINE_TC_CAST(TCLASS, TClass);
-
 CONFIG_PARSER_PROTOTYPE(config_parse_tclass_parent);
 CONFIG_PARSER_PROTOTYPE(config_parse_tclass_classid);