diff options
Diffstat (limited to 'src/network/tc/tc.c')
-rw-r--r-- | src/network/tc/tc.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/network/tc/tc.c b/src/network/tc/tc.c new file mode 100644 index 0000000..c32b040 --- /dev/null +++ b/src/network/tc/tc.c @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "macro.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("Invalid traffic control type"); + } +} + +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("Invalid traffic control type"); + } +} + +int link_configure_traffic_control(Link *link) { + TrafficControl *tc; + int r; + + link->tc_configured = false; + link->tc_messages = 0; + + ORDERED_HASHMAP_FOREACH(tc, link->network->tc_by_section) { + r = traffic_control_configure(link, tc); + if (r < 0) + return r; + } + + if (link->tc_messages == 0) + link->tc_configured = true; + else + log_link_debug(link, "Configuring traffic control"); + + return 0; +} + +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("Invalid traffic control type"); + } +} + +void network_drop_invalid_traffic_control(Network *network) { + bool has_root = false, has_clsact = false; + TrafficControl *tc; + + assert(network); + + ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section) + if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0) + traffic_control_free(tc); +} |