network: introduce TrafficControlKind to prepare for supporting tc class

This commit is contained in:
Yu Watanabe 2020-02-10 20:53:00 +09:00
parent 931c8c824a
commit 34658df256
9 changed files with 131 additions and 43 deletions

View File

@ -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())

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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 &&
kind != _QDISC_KIND_INVALID &&
existing->kind != kind)
if (existing->kind != TC_KIND_QDISC)
return -EINVAL;
if (existing->kind == kind || kind == _QDISC_KIND_INVALID) {
*ret = existing;
q = TC_TO_QDISC(existing);
if (q->kind != _QDISC_KIND_INVALID &&
kind != _QDISC_KIND_INVALID &&
q->kind != kind)
return -EINVAL;
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;
}

View File

@ -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);

41
src/network/tc/tc.c Normal file
View File

@ -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");
}
}

32
src/network/tc/tc.h Normal file
View File

@ -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);