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);
Set *neighbors;
Set *routes;
Set *nexthops;
- Set *traffic_control;
+ Set *qdiscs;
+ Set *tclasses;
sd_dhcp_client *dhcp_client;
sd_dhcp_lease *dhcp_lease;
#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"
#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. */
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;
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);
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 */
#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) {
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;
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;
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:
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);
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);
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,
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,
RoutingPolicyRule *rule;
void *set_link_operation_ptr;
NetDev *netdev;
- TrafficControl *traffic_control;
+ QDisc *qdisc;
+ TClass *tclass;
void *object;
};
void *userdata;
#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"
#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"
#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"
return -ENOMEM;
*qdisc = (QDisc) {
- .meta.kind = TC_KIND_QDISC,
.parent = TC_H_ROOT,
.kind = kind,
};
if (!qdisc)
return -ENOMEM;
- qdisc->meta.kind = TC_KIND_QDISC,
qdisc->parent = TC_H_ROOT;
qdisc->kind = kind;
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);
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;
}
}
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;
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);
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;
}
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;
}
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;
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);
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;
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;
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");
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);
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,
#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,
} QDiscKind;
typedef struct QDisc {
- TrafficControl meta;
-
Link *link;
Network *network;
ConfigSection *section;
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);
/* 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);
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;
}
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);
-}
/* 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);
#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"
return -ENOMEM;
*tclass = (TClass) {
- .meta.kind = TC_KIND_TCLASS,
.parent = TC_H_ROOT,
.kind = kind,
};
if (!tclass)
return -ENOMEM;
- tclass->meta.kind = TC_KIND_TCLASS;
tclass->parent = TC_H_ROOT;
tclass->kind = kind;
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);
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;
}
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;
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);
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;
}
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;
}
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;
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);
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;
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");
return 1;
}
-int tclass_section_verify(TClass *tclass) {
+static int tclass_section_verify(TClass *tclass) {
int r;
assert(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,
#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,
} TClassKind;
typedef struct TClass {
- TrafficControl meta;
-
Link *link;
Network *network;
ConfigSection *section;
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);