diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-01-02 20:41:20 +0100 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-01-03 20:58:36 +0100 |
commit | 2a75f23b0d186d4aa2a2e0886f0b9b9ce13f9202 (patch) | |
tree | 7ee9cbab02710a6541b6d9b27ac26fe9361feeaa /src | |
parent | network/address: introduce ref/unref functions for Address object (diff) | |
download | systemd-2a75f23b0d186d4aa2a2e0886f0b9b9ce13f9202.tar.xz systemd-2a75f23b0d186d4aa2a2e0886f0b9b9ce13f9202.zip |
network/neighbor: introduce ref/unref function for Neighbor object
Diffstat (limited to 'src')
-rw-r--r-- | src/network/networkd-neighbor.c | 148 | ||||
-rw-r--r-- | src/network/networkd-neighbor.h | 5 | ||||
-rw-r--r-- | src/network/networkd-network.c | 2 |
3 files changed, 102 insertions, 53 deletions
diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index e172c564b0..ac4682ab18 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -10,28 +10,87 @@ #include "networkd-queue.h" #include "set.h" -Neighbor *neighbor_free(Neighbor *neighbor) { - if (!neighbor) - return NULL; +static Neighbor* neighbor_detach_impl(Neighbor *neighbor) { + assert(neighbor); + assert(!neighbor->link || !neighbor->network); if (neighbor->network) { assert(neighbor->section); ordered_hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section); + neighbor->network = NULL; + return neighbor; } - config_section_free(neighbor->section); - - if (neighbor->link) + if (neighbor->link) { set_remove(neighbor->link->neighbors, neighbor); + neighbor->link = NULL; + return neighbor; + } + + return NULL; +} +static void neighbor_detach(Neighbor *neighbor) { + neighbor_unref(neighbor_detach_impl(neighbor)); +} + +static Neighbor* neighbor_free(Neighbor *neighbor) { + if (!neighbor) + return NULL; + + neighbor_detach_impl(neighbor); + + config_section_free(neighbor->section); return mfree(neighbor); } -DEFINE_SECTION_CLEANUP_FUNCTIONS(Neighbor, neighbor_free); +DEFINE_TRIVIAL_REF_UNREF_FUNC(Neighbor, neighbor, neighbor_free); +DEFINE_SECTION_CLEANUP_FUNCTIONS(Neighbor, neighbor_unref); + +static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state); +static int neighbor_compare_func(const Neighbor *a, const Neighbor *b); + +DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( + neighbor_hash_ops_detach, + Neighbor, + neighbor_hash_func, + neighbor_compare_func, + neighbor_detach); + +DEFINE_PRIVATE_HASH_OPS( + neighbor_hash_ops, + Neighbor, + neighbor_hash_func, + neighbor_compare_func); + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + neighbor_section_hash_ops, + ConfigSection, + config_section_hash_func, + config_section_compare_func, + Neighbor, + neighbor_detach); + +static int neighbor_new(Neighbor **ret) { + Neighbor *neighbor; + + assert(ret); + + neighbor = new(Neighbor, 1); + if (!neighbor) + return -ENOMEM; + + *neighbor = (Neighbor) { + .n_ref = 1, + }; + + *ret = TAKE_PTR(neighbor); + return 0; +} static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) { _cleanup_(config_section_freep) ConfigSection *n = NULL; - _cleanup_(neighbor_freep) Neighbor *neighbor = NULL; + _cleanup_(neighbor_unrefp) Neighbor *neighbor = NULL; int r; assert(network); @@ -49,18 +108,15 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned return 0; } - neighbor = new(Neighbor, 1); - if (!neighbor) - return -ENOMEM; + r = neighbor_new(&neighbor); + if (r < 0) + return r; - *neighbor = (Neighbor) { - .network = network, - .family = AF_UNSPEC, - .section = TAKE_PTR(n), - .source = NETWORK_CONFIG_SOURCE_STATIC, - }; + neighbor->network = network; + neighbor->section = TAKE_PTR(n); + neighbor->source = NETWORK_CONFIG_SOURCE_STATIC; - r = ordered_hashmap_ensure_put(&network->neighbors_by_section, &config_section_hash_ops, neighbor->section, neighbor); + r = ordered_hashmap_ensure_put(&network->neighbors_by_section, &neighbor_section_hash_ops, neighbor->section, neighbor); if (r < 0) return r; @@ -69,7 +125,7 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned } static int neighbor_dup(const Neighbor *neighbor, Neighbor **ret) { - _cleanup_(neighbor_freep) Neighbor *dest = NULL; + _cleanup_(neighbor_unrefp) Neighbor *dest = NULL; assert(neighbor); assert(ret); @@ -78,7 +134,8 @@ static int neighbor_dup(const Neighbor *neighbor, Neighbor **ret) { if (!dest) return -ENOMEM; - /* Unset all pointers */ + /* Clear the reference counter and all pointers */ + dest->n_ref = 1; dest->link = NULL; dest->network = NULL; dest->section = NULL; @@ -115,19 +172,6 @@ static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) { return memcmp(&a->in_addr, &b->in_addr, FAMILY_ADDRESS_SIZE(a->family)); } -DEFINE_PRIVATE_HASH_OPS( - neighbor_hash_ops, - Neighbor, - neighbor_hash_func, - neighbor_compare_func); - -DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( - neighbor_hash_ops_free, - Neighbor, - neighbor_hash_func, - neighbor_compare_func, - neighbor_free); - static int neighbor_get_request(Link *link, const Neighbor *neighbor, Request **ret) { Request *req; @@ -167,19 +211,21 @@ static int neighbor_get(Link *link, const Neighbor *in, Neighbor **ret) { return 0; } -static int neighbor_add(Link *link, Neighbor *neighbor) { +static int neighbor_attach(Link *link, Neighbor *neighbor) { int r; assert(link); assert(neighbor); + assert(!neighbor->link); - r = set_ensure_put(&link->neighbors, &neighbor_hash_ops_free, neighbor); + r = set_ensure_put(&link->neighbors, &neighbor_hash_ops_detach, neighbor); if (r < 0) return r; if (r == 0) return -EEXIST; neighbor->link = link; + neighbor_ref(neighbor); return 0; } @@ -279,7 +325,7 @@ static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_messag } static int link_request_neighbor(Link *link, const Neighbor *neighbor) { - _cleanup_(neighbor_freep) Neighbor *tmp = NULL; + _cleanup_(neighbor_unrefp) Neighbor *tmp = NULL; Neighbor *existing = NULL; int r; @@ -308,7 +354,7 @@ static int link_request_neighbor(Link *link, const Neighbor *neighbor) { log_neighbor_debug(tmp, "Requesting", link); r = link_queue_request_safe(link, REQUEST_TYPE_NEIGHBOR, tmp, - neighbor_free, + neighbor_unref, neighbor_hash_func, neighbor_compare_func, neighbor_process_request, @@ -477,7 +523,7 @@ void link_foreignize_neighbors(Link *link) { } int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { - _cleanup_(neighbor_freep) Neighbor *tmp = NULL; + _cleanup_(neighbor_unrefp) Neighbor *tmp = NULL; Neighbor *neighbor = NULL; Request *req = NULL; uint16_t type, state; @@ -529,8 +575,8 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, * kernel sends messages about neighbors after a link is removed. So, just ignore it. */ return 0; - tmp = new0(Neighbor, 1); - if (!tmp) + r = neighbor_new(&tmp); + if (r < 0) return log_oom(); /* First, retrieve the fundamental information about the neighbor. */ @@ -560,7 +606,7 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, if (neighbor) { neighbor_enter_removed(neighbor); log_neighbor_debug(neighbor, "Forgetting removed", link); - neighbor_free(neighbor); + neighbor_detach(neighbor); } else log_neighbor_debug(tmp, "Kernel removed unknown", link); @@ -572,12 +618,12 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, /* If we did not know the neighbor, then save it. */ if (!neighbor) { - r = neighbor_add(link, tmp); + r = neighbor_attach(link, tmp); if (r < 0) { log_link_warning_errno(link, r, "Failed to save received neighbor, ignoring: %m"); return 0; } - neighbor = TAKE_PTR(tmp); + neighbor = tmp; is_new = true; } @@ -638,9 +684,9 @@ int network_drop_invalid_neighbors(Network *network) { Neighbor *dup; if (neighbor_section_verify(neighbor) < 0) { - /* Drop invalid [Neighbor] sections. Note that neighbor_free() will drop the + /* Drop invalid [Neighbor] sections. Note that neighbor_detach() will drop the * neighbor from neighbors_by_section. */ - neighbor_free(neighbor); + neighbor_detach(neighbor); continue; } @@ -653,12 +699,12 @@ int network_drop_invalid_neighbors(Network *network) { IN_ADDR_TO_STRING(neighbor->family, &neighbor->in_addr), neighbor->section->line, dup->section->line, dup->section->line); - /* neighbor_free() will drop the neighbor from neighbors_by_section. */ - neighbor_free(dup); + /* neighbor_detach() will drop the neighbor from neighbors_by_section. */ + neighbor_detach(dup); } - /* Use neighbor_hash_ops, instead of neighbor_hash_ops_free. Otherwise, the Neighbor objects - * will be freed. */ + /* Use neighbor_hash_ops, instead of neighbor_hash_ops_detach. Otherwise, the Neighbor objects + * will be detached. */ r = set_ensure_put(&neighbors, &neighbor_hash_ops, neighbor); if (r < 0) return log_oom(); @@ -681,7 +727,7 @@ int config_parse_neighbor_address( void *data, void *userdata) { - _cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL; + _cleanup_(neighbor_unref_or_set_invalidp) Neighbor *n = NULL; Network *network = ASSERT_PTR(userdata); int r; @@ -724,7 +770,7 @@ int config_parse_neighbor_lladdr( void *data, void *userdata) { - _cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL; + _cleanup_(neighbor_unref_or_set_invalidp) Neighbor *n = NULL; Network *network = ASSERT_PTR(userdata); int r; diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 683a310b3f..4a5503ca13 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -21,12 +21,15 @@ typedef struct Neighbor { NetworkConfigSource source; NetworkConfigState state; + unsigned n_ref; + int family; union in_addr_union in_addr; struct hw_addr_data ll_addr; } Neighbor; -Neighbor *neighbor_free(Neighbor *neighbor); +Neighbor* neighbor_ref(Neighbor *neighbor); +Neighbor* neighbor_unref(Neighbor *neighbor); int network_drop_invalid_neighbors(Network *network); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 591b4093cc..51f5cacc14 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -787,7 +787,7 @@ static Network *network_free(Network *network) { ordered_hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free); hashmap_free_with_destructor(network->bridge_fdb_entries_by_section, bridge_fdb_free); hashmap_free_with_destructor(network->bridge_mdb_entries_by_section, bridge_mdb_free); - ordered_hashmap_free_with_destructor(network->neighbors_by_section, neighbor_free); + ordered_hashmap_free(network->neighbors_by_section); hashmap_free_with_destructor(network->address_labels_by_section, address_label_free); hashmap_free_with_destructor(network->prefixes_by_section, prefix_free); hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free); |