diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/network/networkd-network.c | 2 | ||||
-rw-r--r-- | src/network/tc/drr.c | 2 | ||||
-rw-r--r-- | src/network/tc/htb.c | 6 | ||||
-rw-r--r-- | src/network/tc/qfq.c | 4 | ||||
-rw-r--r-- | src/network/tc/tclass.c | 101 | ||||
-rw-r--r-- | src/network/tc/tclass.h | 7 |
6 files changed, 84 insertions, 38 deletions
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index fafa0e570e..a5bb6dd529 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -802,7 +802,7 @@ static Network *network_free(Network *network) { 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(network->qdiscs_by_section); - hashmap_free_with_destructor(network->tclasses_by_section, tclass_free); + hashmap_free(network->tclasses_by_section); return mfree(network); } diff --git a/src/network/tc/drr.c b/src/network/tc/drr.c index 373911bc70..5d754101de 100644 --- a/src/network/tc/drr.c +++ b/src/network/tc/drr.c @@ -54,7 +54,7 @@ int config_parse_drr_size( void *data, void *userdata) { - _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL; + _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL; DeficitRoundRobinSchedulerClass *drr; Network *network = ASSERT_PTR(data); uint64_t u; diff --git a/src/network/tc/htb.c b/src/network/tc/htb.c index 8f1faa1dc5..39f436a804 100644 --- a/src/network/tc/htb.c +++ b/src/network/tc/htb.c @@ -251,7 +251,7 @@ int config_parse_hierarchy_token_bucket_class_u32( void *data, void *userdata) { - _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL; + _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL; HierarchyTokenBucketClass *htb; Network *network = ASSERT_PTR(data); uint32_t v; @@ -304,7 +304,7 @@ int config_parse_hierarchy_token_bucket_class_size( void *data, void *userdata) { - _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL; + _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL; HierarchyTokenBucketClass *htb; Network *network = ASSERT_PTR(data); uint64_t v; @@ -387,7 +387,7 @@ int config_parse_hierarchy_token_bucket_class_rate( void *data, void *userdata) { - _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL; + _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL; HierarchyTokenBucketClass *htb; Network *network = ASSERT_PTR(data); uint64_t *v; diff --git a/src/network/tc/qfq.c b/src/network/tc/qfq.c index 7702e6ff6e..0da53a89e4 100644 --- a/src/network/tc/qfq.c +++ b/src/network/tc/qfq.c @@ -62,7 +62,7 @@ int config_parse_quick_fair_queueing_weight( void *data, void *userdata) { - _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL; + _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL; QuickFairQueueingClass *qfq; Network *network = ASSERT_PTR(data); uint32_t v; @@ -122,7 +122,7 @@ int config_parse_quick_fair_queueing_max_packet( void *data, void *userdata) { - _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL; + _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL; QuickFairQueueingClass *qfq; Network *network = ASSERT_PTR(data); uint64_t v; diff --git a/src/network/tc/tclass.c b/src/network/tc/tclass.c index fcbe8cbcf4..168d93e1c5 100644 --- a/src/network/tc/tclass.c +++ b/src/network/tc/tclass.c @@ -24,8 +24,54 @@ const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX] = { [TCLASS_KIND_QFQ] = &qfq_tclass_vtable, }; +static TClass* tclass_detach_impl(TClass *tclass) { + assert(tclass); + assert(!tclass->link || !tclass->network); + + if (tclass->network) { + assert(tclass->section); + hashmap_remove(tclass->network->tclasses_by_section, tclass->section); + + tclass->network = NULL; + return tclass; + } + + if (tclass->link) { + set_remove(tclass->link->tclasses, tclass); + + tclass->link = NULL; + return tclass; + } + + return NULL; +} + +static void tclass_detach(TClass *tclass) { + assert(tclass); + + tclass_unref(tclass_detach_impl(tclass)); +} + +static void tclass_hash_func(const TClass *tclass, struct siphash *state); +static int tclass_compare_func(const TClass *a, const TClass *b); + +DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( + tclass_hash_ops, + TClass, + tclass_hash_func, + tclass_compare_func, + tclass_detach); + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + tclass_section_hash_ops, + ConfigSection, + config_section_hash_func, + config_section_compare_func, + TClass, + tclass_detach); + static int tclass_new(TClassKind kind, TClass **ret) { - _cleanup_(tclass_freep) TClass *tclass = NULL; + _cleanup_(tclass_unrefp) TClass *tclass = NULL; int r; if (kind == _TCLASS_KIND_INVALID) { @@ -34,6 +80,7 @@ static int tclass_new(TClassKind kind, TClass **ret) { return -ENOMEM; *tclass = (TClass) { + .n_ref = 1, .parent = TC_H_ROOT, .kind = kind, }; @@ -43,6 +90,7 @@ static int tclass_new(TClassKind kind, TClass **ret) { if (!tclass) return -ENOMEM; + tclass->n_ref = 1; tclass->parent = TC_H_ROOT; tclass->kind = kind; @@ -60,7 +108,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; + _cleanup_(tclass_unrefp) TClass *tclass = NULL; TClass *existing; int r; @@ -90,7 +138,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->tclasses_by_section, &config_section_hash_ops, tclass->section, tclass); + r = hashmap_ensure_put(&network->tclasses_by_section, &tclass_section_hash_ops, tclass->section, tclass); if (r < 0) return r; @@ -98,22 +146,20 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u return 0; } -TClass* tclass_free(TClass *tclass) { +static TClass* tclass_free(TClass *tclass) { if (!tclass) return NULL; - if (tclass->network && tclass->section) - hashmap_remove(tclass->network->tclasses_by_section, tclass->section); + tclass_detach_impl(tclass); config_section_free(tclass->section); - if (tclass->link) - set_remove(tclass->link->tclasses, tclass); - free(tclass->tca_kind); return mfree(tclass); } +DEFINE_TRIVIAL_REF_UNREF_FUNC(TClass, tclass, tclass_free); + static const char *tclass_get_tca_kind(const TClass *tclass) { assert(tclass); @@ -147,13 +193,6 @@ static 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) { TClass *existing; @@ -169,11 +208,13 @@ static int tclass_get(Link *link, const TClass *in, TClass **ret) { return 0; } -static int tclass_add(Link *link, TClass *tclass) { +static int tclass_attach(Link *link, TClass *tclass) { int r; assert(link); assert(tclass); + assert(!tclass->link); + assert(!tclass->network); r = set_ensure_put(&link->tclasses, &tclass_hash_ops, tclass); if (r < 0) @@ -182,11 +223,12 @@ static int tclass_add(Link *link, TClass *tclass) { return -EEXIST; tclass->link = link; + tclass_ref(tclass); return 0; } static int tclass_dup(const TClass *src, TClass **ret) { - _cleanup_(tclass_freep) TClass *dst = NULL; + _cleanup_(tclass_unrefp) TClass *dst = NULL; assert(src); assert(ret); @@ -198,7 +240,8 @@ static int tclass_dup(const TClass *src, TClass **ret) { if (!dst) return -ENOMEM; - /* clear all pointers */ + /* clear the reference counter and all pointers */ + dst->n_ref = 1; dst->network = NULL; dst->section = NULL; dst->link = NULL; @@ -286,7 +329,7 @@ void link_tclass_drop_marked(Link *link) { if (tclass->state == 0) { log_tclass_debug(tclass, link, "Forgetting"); - tclass_free(tclass); + tclass_detach(tclass); } else log_tclass_debug(tclass, link, "Removed"); } @@ -393,17 +436,17 @@ int link_request_tclass(Link *link, TClass *tclass) { assert(tclass); if (tclass_get(link, tclass, &existing) < 0) { - _cleanup_(tclass_freep) TClass *tmp = NULL; + _cleanup_(tclass_unrefp) TClass *tmp = NULL; r = tclass_dup(tclass, &tmp); if (r < 0) return log_oom(); - r = tclass_add(link, tmp); + r = tclass_attach(link, tmp); if (r < 0) return log_link_warning_errno(link, r, "Failed to store TClass: %m"); - existing = TAKE_PTR(tmp); + existing = tmp; } else existing->source = tclass->source; @@ -426,7 +469,7 @@ int link_request_tclass(Link *link, TClass *tclass) { } int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { - _cleanup_(tclass_freep) TClass *tmp = NULL; + _cleanup_(tclass_unrefp) TClass *tmp = NULL; TClass *tclass = NULL; Link *link; uint16_t type; @@ -501,13 +544,13 @@ int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, M tclass_enter_configured(tmp); log_tclass_debug(tmp, link, "Received new"); - r = tclass_add(link, tmp); + r = tclass_attach(link, tmp); if (r < 0) { log_link_warning_errno(link, r, "Failed to remember TClass, ignoring: %m"); return 0; } - tclass = TAKE_PTR(tmp); + tclass = tmp; } break; @@ -566,7 +609,7 @@ void network_drop_invalid_tclass(Network *network) { HASHMAP_FOREACH(tclass, network->tclasses_by_section) if (tclass_section_verify(tclass) < 0) - tclass_free(tclass); + tclass_detach(tclass); } int config_parse_tclass_parent( @@ -581,7 +624,7 @@ int config_parse_tclass_parent( void *data, void *userdata) { - _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL; + _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL; Network *network = ASSERT_PTR(data); int r; @@ -627,7 +670,7 @@ int config_parse_tclass_classid( void *data, void *userdata) { - _cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL; + _cleanup_(tclass_unref_or_set_invalidp) TClass *tclass = NULL; Network *network = ASSERT_PTR(data); int r; diff --git a/src/network/tc/tclass.h b/src/network/tc/tclass.h index 85df57d42c..44f7181450 100644 --- a/src/network/tc/tclass.h +++ b/src/network/tc/tclass.h @@ -24,6 +24,8 @@ typedef struct TClass { NetworkConfigSource source; NetworkConfigState state; + unsigned n_ref; + uint32_t classid; uint32_t parent; @@ -55,7 +57,8 @@ extern const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX]; DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(TClass, tclass); -TClass* tclass_free(TClass *tclass); +TClass* tclass_ref(TClass *tclass); +TClass* tclass_unref(TClass *tclass); int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret); void tclass_mark_recursive(TClass *tclass); @@ -71,7 +74,7 @@ void network_drop_invalid_tclass(Network *network); int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); int link_enumerate_tclass(Link *link, uint32_t parent); -DEFINE_SECTION_CLEANUP_FUNCTIONS(TClass, tclass_free); +DEFINE_SECTION_CLEANUP_FUNCTIONS(TClass, tclass_unref); CONFIG_PARSER_PROTOTYPE(config_parse_tclass_parent); CONFIG_PARSER_PROTOTYPE(config_parse_tclass_classid); |