mirror of
https://github.com/systemd/systemd.git
synced 2025-01-10 05:18:17 +03:00
network/neighbor: introduce ref/unref function for Neighbor object
This commit is contained in:
parent
ebd9690647
commit
2a75f23b0d
@ -10,28 +10,87 @@
|
|||||||
#include "networkd-queue.h"
|
#include "networkd-queue.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
|
|
||||||
Neighbor *neighbor_free(Neighbor *neighbor) {
|
static Neighbor* neighbor_detach_impl(Neighbor *neighbor) {
|
||||||
if (!neighbor)
|
assert(neighbor);
|
||||||
return NULL;
|
assert(!neighbor->link || !neighbor->network);
|
||||||
|
|
||||||
if (neighbor->network) {
|
if (neighbor->network) {
|
||||||
assert(neighbor->section);
|
assert(neighbor->section);
|
||||||
ordered_hashmap_remove(neighbor->network->neighbors_by_section, 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);
|
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);
|
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) {
|
static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) {
|
||||||
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
|
_cleanup_(neighbor_unrefp) Neighbor *neighbor = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(network);
|
assert(network);
|
||||||
@ -49,18 +108,15 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
neighbor = new(Neighbor, 1);
|
r = neighbor_new(&neighbor);
|
||||||
if (!neighbor)
|
if (r < 0)
|
||||||
return -ENOMEM;
|
return r;
|
||||||
|
|
||||||
*neighbor = (Neighbor) {
|
neighbor->network = network;
|
||||||
.network = network,
|
neighbor->section = TAKE_PTR(n);
|
||||||
.family = AF_UNSPEC,
|
neighbor->source = NETWORK_CONFIG_SOURCE_STATIC;
|
||||||
.section = TAKE_PTR(n),
|
|
||||||
.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)
|
if (r < 0)
|
||||||
return r;
|
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) {
|
static int neighbor_dup(const Neighbor *neighbor, Neighbor **ret) {
|
||||||
_cleanup_(neighbor_freep) Neighbor *dest = NULL;
|
_cleanup_(neighbor_unrefp) Neighbor *dest = NULL;
|
||||||
|
|
||||||
assert(neighbor);
|
assert(neighbor);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
@ -78,7 +134,8 @@ static int neighbor_dup(const Neighbor *neighbor, Neighbor **ret) {
|
|||||||
if (!dest)
|
if (!dest)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Unset all pointers */
|
/* Clear the reference counter and all pointers */
|
||||||
|
dest->n_ref = 1;
|
||||||
dest->link = NULL;
|
dest->link = NULL;
|
||||||
dest->network = NULL;
|
dest->network = NULL;
|
||||||
dest->section = 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));
|
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) {
|
static int neighbor_get_request(Link *link, const Neighbor *neighbor, Request **ret) {
|
||||||
Request *req;
|
Request *req;
|
||||||
|
|
||||||
@ -167,19 +211,21 @@ static int neighbor_get(Link *link, const Neighbor *in, Neighbor **ret) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int neighbor_add(Link *link, Neighbor *neighbor) {
|
static int neighbor_attach(Link *link, Neighbor *neighbor) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(neighbor);
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
|
||||||
neighbor->link = link;
|
neighbor->link = link;
|
||||||
|
neighbor_ref(neighbor);
|
||||||
return 0;
|
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) {
|
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;
|
Neighbor *existing = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -308,7 +354,7 @@ static int link_request_neighbor(Link *link, const Neighbor *neighbor) {
|
|||||||
log_neighbor_debug(tmp, "Requesting", link);
|
log_neighbor_debug(tmp, "Requesting", link);
|
||||||
r = link_queue_request_safe(link, REQUEST_TYPE_NEIGHBOR,
|
r = link_queue_request_safe(link, REQUEST_TYPE_NEIGHBOR,
|
||||||
tmp,
|
tmp,
|
||||||
neighbor_free,
|
neighbor_unref,
|
||||||
neighbor_hash_func,
|
neighbor_hash_func,
|
||||||
neighbor_compare_func,
|
neighbor_compare_func,
|
||||||
neighbor_process_request,
|
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) {
|
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;
|
Neighbor *neighbor = NULL;
|
||||||
Request *req = NULL;
|
Request *req = NULL;
|
||||||
uint16_t type, state;
|
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. */
|
* kernel sends messages about neighbors after a link is removed. So, just ignore it. */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
tmp = new0(Neighbor, 1);
|
r = neighbor_new(&tmp);
|
||||||
if (!tmp)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
/* First, retrieve the fundamental information about the neighbor. */
|
/* 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) {
|
if (neighbor) {
|
||||||
neighbor_enter_removed(neighbor);
|
neighbor_enter_removed(neighbor);
|
||||||
log_neighbor_debug(neighbor, "Forgetting removed", link);
|
log_neighbor_debug(neighbor, "Forgetting removed", link);
|
||||||
neighbor_free(neighbor);
|
neighbor_detach(neighbor);
|
||||||
} else
|
} else
|
||||||
log_neighbor_debug(tmp, "Kernel removed unknown", link);
|
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 we did not know the neighbor, then save it. */
|
||||||
if (!neighbor) {
|
if (!neighbor) {
|
||||||
r = neighbor_add(link, tmp);
|
r = neighbor_attach(link, tmp);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_link_warning_errno(link, r, "Failed to save received neighbor, ignoring: %m");
|
log_link_warning_errno(link, r, "Failed to save received neighbor, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
neighbor = TAKE_PTR(tmp);
|
neighbor = tmp;
|
||||||
is_new = true;
|
is_new = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,9 +684,9 @@ int network_drop_invalid_neighbors(Network *network) {
|
|||||||
Neighbor *dup;
|
Neighbor *dup;
|
||||||
|
|
||||||
if (neighbor_section_verify(neighbor) < 0) {
|
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 from neighbors_by_section. */
|
||||||
neighbor_free(neighbor);
|
neighbor_detach(neighbor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,12 +699,12 @@ int network_drop_invalid_neighbors(Network *network) {
|
|||||||
IN_ADDR_TO_STRING(neighbor->family, &neighbor->in_addr),
|
IN_ADDR_TO_STRING(neighbor->family, &neighbor->in_addr),
|
||||||
neighbor->section->line,
|
neighbor->section->line,
|
||||||
dup->section->line, dup->section->line);
|
dup->section->line, dup->section->line);
|
||||||
/* neighbor_free() will drop the neighbor from neighbors_by_section. */
|
/* neighbor_detach() will drop the neighbor from neighbors_by_section. */
|
||||||
neighbor_free(dup);
|
neighbor_detach(dup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use neighbor_hash_ops, instead of neighbor_hash_ops_free. Otherwise, the Neighbor objects
|
/* Use neighbor_hash_ops, instead of neighbor_hash_ops_detach. Otherwise, the Neighbor objects
|
||||||
* will be freed. */
|
* will be detached. */
|
||||||
r = set_ensure_put(&neighbors, &neighbor_hash_ops, neighbor);
|
r = set_ensure_put(&neighbors, &neighbor_hash_ops, neighbor);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
@ -681,7 +727,7 @@ int config_parse_neighbor_address(
|
|||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
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);
|
Network *network = ASSERT_PTR(userdata);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -724,7 +770,7 @@ int config_parse_neighbor_lladdr(
|
|||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
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);
|
Network *network = ASSERT_PTR(userdata);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -21,12 +21,15 @@ typedef struct Neighbor {
|
|||||||
NetworkConfigSource source;
|
NetworkConfigSource source;
|
||||||
NetworkConfigState state;
|
NetworkConfigState state;
|
||||||
|
|
||||||
|
unsigned n_ref;
|
||||||
|
|
||||||
int family;
|
int family;
|
||||||
union in_addr_union in_addr;
|
union in_addr_union in_addr;
|
||||||
struct hw_addr_data ll_addr;
|
struct hw_addr_data ll_addr;
|
||||||
} Neighbor;
|
} Neighbor;
|
||||||
|
|
||||||
Neighbor *neighbor_free(Neighbor *neighbor);
|
Neighbor* neighbor_ref(Neighbor *neighbor);
|
||||||
|
Neighbor* neighbor_unref(Neighbor *neighbor);
|
||||||
|
|
||||||
int network_drop_invalid_neighbors(Network *network);
|
int network_drop_invalid_neighbors(Network *network);
|
||||||
|
|
||||||
|
@ -787,7 +787,7 @@ static Network *network_free(Network *network) {
|
|||||||
ordered_hashmap_free_with_destructor(network->nexthops_by_section, nexthop_free);
|
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_fdb_entries_by_section, bridge_fdb_free);
|
||||||
hashmap_free_with_destructor(network->bridge_mdb_entries_by_section, bridge_mdb_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->address_labels_by_section, address_label_free);
|
||||||
hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
|
hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
|
||||||
hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
|
hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
|
||||||
|
Loading…
Reference in New Issue
Block a user