1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-05 13:18:06 +03:00

network/route: introduce ref/unref functions for Route object

Then, Route object can live if it is detached from the owner (Manager,
Network, or Wireguard object).

This is the one for routes of ebd9690647.
This commit is contained in:
Yu Watanabe 2024-01-07 15:16:03 +09:00
parent 3caed9ea08
commit 74c301b9ee
9 changed files with 97 additions and 61 deletions

View File

@ -1190,7 +1190,7 @@ static int wireguard_verify(NetDev *netdev, const char *filename) {
continue;
LIST_FOREACH(ipmasks, ipmask, peer->ipmasks) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
r = route_new(&route);
if (r < 0)

View File

@ -282,7 +282,7 @@ static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Reques
}
static int dhcp_pd_request_route(Link *link, const struct in6_addr *prefix, usec_t lifetime_usec) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
Route *existing;
int r;
@ -670,7 +670,7 @@ static int dhcp_request_unreachable_route(
route_netlink_handler_t callback,
bool *configured) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
Route *existing;
int r;
@ -781,7 +781,7 @@ static int dhcp_pd_prefix_add(Link *link, const struct in6_addr *prefix, uint8_t
}
static int dhcp4_pd_request_default_gateway_on_6rd_tunnel(Link *link, const struct in_addr *br_address, usec_t lifetime_usec) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
Route *existing;
int r;

View File

@ -410,7 +410,7 @@ static bool link_prefixroute(Link *link) {
}
static int dhcp4_request_prefix_route(Link *link) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
int r;
assert(link);
@ -438,7 +438,7 @@ static int dhcp4_request_prefix_route(Link *link) {
}
static int dhcp4_request_route_to_gateway(Link *link, const struct in_addr *gw) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
struct in_addr address;
int r;
@ -556,7 +556,7 @@ static int dhcp4_request_classless_static_or_static_routes(Link *link) {
return r;
FOREACH_ARRAY(e, routes, n_routes) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
struct in_addr gw;
r = route_new(&route);
@ -584,7 +584,7 @@ static int dhcp4_request_classless_static_or_static_routes(Link *link) {
}
static int dhcp4_request_default_gateway(Link *link) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
struct in_addr address, router;
int r;
@ -639,7 +639,7 @@ static int dhcp4_request_semi_static_routes(Link *link) {
assert(link->network);
HASHMAP_FOREACH(rt, link->network->routes_by_section) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
struct in_addr gw;
if (!rt->gateway_from_dhcp_or_ra)
@ -690,7 +690,7 @@ static int dhcp4_request_routes_to_servers(
assert(servers || n_servers == 0);
FOREACH_ARRAY(dst, servers, n_servers) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
struct in_addr gw;
if (in4_addr_is_null(dst))

View File

@ -316,7 +316,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
if (link->network->ipv6_accept_ra_use_gateway) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
r = route_new(&route);
if (r < 0)
@ -335,7 +335,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
Route *route_gw;
HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
if (!route_gw->gateway_from_dhcp_or_ra)
continue;
@ -498,7 +498,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
}
static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
unsigned prefixlen, preference;
usec_t lifetime_usec;
struct in6_addr prefix;
@ -600,7 +600,7 @@ static int ndisc_router_process_prefix(Link *link, sd_ndisc_router *rt) {
}
static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
unsigned preference, prefixlen;
struct in6_addr gateway, dst;
usec_t lifetime_usec;

View File

@ -188,7 +188,7 @@ int network_verify(Network *network) {
network->filename);
network->addresses_by_section = ordered_hashmap_free(network->addresses_by_section);
network->routes_by_section = hashmap_free_with_destructor(network->routes_by_section, route_free);
network->routes_by_section = hashmap_free(network->routes_by_section);
}
if (network->link_local < 0) {
@ -782,7 +782,7 @@ static Network *network_free(Network *network) {
/* static configs */
set_free_free(network->ipv6_proxy_ndp_addresses);
ordered_hashmap_free(network->addresses_by_section);
hashmap_free_with_destructor(network->routes_by_section, route_free);
hashmap_free(network->routes_by_section);
ordered_hashmap_free(network->nexthops_by_section);
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);

View File

@ -374,7 +374,7 @@ static int config_parse_route_metric_boolean_impl(
void *userdata) { \
\
Network *network = ASSERT_PTR(userdata); \
_cleanup_(route_free_or_set_invalidp) Route *route = NULL; \
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL; \
uint16_t attr_type = ltype; \
int r; \
\
@ -436,7 +436,7 @@ int config_parse_route_metric_tcp_congestion(
void *userdata) {
Network *network = ASSERT_PTR(userdata);
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);

View File

@ -899,7 +899,7 @@ int config_parse_gateway(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
@ -986,7 +986,7 @@ int config_parse_route_gateway_onlink(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
@ -1026,7 +1026,7 @@ int config_parse_route_nexthop(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
uint32_t id;
int r;
@ -1079,7 +1079,7 @@ int config_parse_multipath_route(
void *userdata) {
_cleanup_(route_nexthop_freep) RouteNextHop *nh = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
_cleanup_free_ char *word = NULL;
Network *network = userdata;
const char *p;

View File

@ -21,20 +21,41 @@
#include "vrf.h"
#include "wireguard.h"
Route* route_free(Route *route) {
if (!route)
return NULL;
static Route* route_detach_impl(Route *route) {
assert(route);
assert(!!route->network + !!route->manager + !!route->wireguard <= 1);
if (route->network) {
assert(route->section);
hashmap_remove(route->network->routes_by_section, route->section);
route->network = NULL;
return route;
}
if (route->manager)
if (route->manager) {
set_remove(route->manager->routes, route);
route->manager = NULL;
return route;
}
if (route->wireguard)
if (route->wireguard) {
set_remove(route->wireguard->routes, route);
route->wireguard = NULL;
return route;
}
return NULL;
}
static void route_detach(Route *route) {
route_unref(route_detach_impl(route));
}
static Route* route_free(Route *route) {
if (!route)
return NULL;
route_detach_impl(route);
config_section_free(route->section);
route_nexthops_done(route);
@ -44,6 +65,8 @@ Route* route_free(Route *route) {
return mfree(route);
}
DEFINE_TRIVIAL_REF_UNREF_FUNC(Route, route, route_free);
static void route_hash_func(const Route *route, struct siphash *state) {
assert(route);
@ -195,16 +218,25 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
Route,
route_hash_func,
route_compare_func,
route_free);
route_detach);
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
route_section_hash_ops,
ConfigSection,
config_section_hash_func,
config_section_compare_func,
Route,
route_detach);
int route_new(Route **ret) {
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
route = new(Route, 1);
if (!route)
return -ENOMEM;
*route = (Route) {
.n_ref = 1,
.family = AF_UNSPEC,
.scope = RT_SCOPE_UNIVERSE,
.protocol = RTPROT_UNSPEC,
@ -221,7 +253,7 @@ int route_new(Route **ret) {
int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(route_freep) Route *route = NULL;
_cleanup_(route_unrefp) Route *route = NULL;
int r;
assert(network);
@ -251,7 +283,7 @@ int route_new_static(Network *network, const char *filename, unsigned section_li
route->section = TAKE_PTR(n);
route->source = NETWORK_CONFIG_SOURCE_STATIC;
r = hashmap_ensure_put(&network->routes_by_section, &config_section_hash_ops, route->section, route);
r = hashmap_ensure_put(&network->routes_by_section, &route_section_hash_ops, route->section, route);
if (r < 0)
return r;
@ -259,7 +291,7 @@ int route_new_static(Network *network, const char *filename, unsigned section_li
return 0;
}
static int route_add(Manager *manager, Route *route) {
static int route_attach(Manager *manager, Route *route) {
int r;
assert(manager);
@ -334,7 +366,7 @@ static int route_get_request(Manager *manager, const Route *route, Request **ret
}
int route_dup(const Route *src, const RouteNextHop *nh, Route **ret) {
_cleanup_(route_freep) Route *dest = NULL;
_cleanup_(route_unrefp) Route *dest = NULL;
int r;
assert(src);
@ -344,7 +376,8 @@ int route_dup(const Route *src, const RouteNextHop *nh, Route **ret) {
if (!dest)
return -ENOMEM;
/* Unset all pointers */
/* Unset number of reference and all pointers */
dest->n_ref = 1;
dest->manager = NULL;
dest->network = NULL;
dest->wireguard = NULL;
@ -570,7 +603,8 @@ static int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdat
Route *route = ASSERT_PTR(userdata);
int r;
assert(route->manager);
if (!route->manager)
return 0; /* already detached. */
r = route_remove(route, route->manager);
if (r < 0) {
@ -683,7 +717,7 @@ static int route_configure(const Route *route, uint32_t lifetime_sec, Link *link
static int route_requeue_request(Request *req, Link *link, const Route *route) {
_unused_ _cleanup_(request_unrefp) Request *req_unref = NULL;
_cleanup_(route_freep) Route *tmp = NULL;
_cleanup_(route_unrefp) Route *tmp = NULL;
int r;
assert(req);
@ -806,7 +840,7 @@ static int link_request_route_one(
unsigned *message_counter,
route_netlink_handler_t netlink_handler) {
_cleanup_(route_freep) Route *tmp = NULL;
_cleanup_(route_unrefp) Route *tmp = NULL;
Route *existing = NULL;
int r;
@ -829,7 +863,7 @@ static int link_request_route_one(
log_route_debug(tmp, "Requesting", link->manager);
r = link_queue_request_safe(link, REQUEST_TYPE_ROUTE,
tmp,
route_free,
route_unref,
route_hash_func,
route_compare_func,
route_process_request,
@ -957,10 +991,9 @@ int link_request_static_routes(Link *link, bool only_ipv4) {
static int process_route_one(
Manager *manager,
uint16_t type,
Route *in,
Route *tmp,
const struct rta_cacheinfo *cacheinfo) {
_cleanup_(route_freep) Route *tmp = in;
Request *req = NULL;
Route *route = NULL;
Link *link = NULL;
@ -987,13 +1020,13 @@ static int process_route_one(
}
/* If we do not know the route, then save it. */
r = route_add(manager, tmp);
r = route_attach(manager, tmp);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m");
return 0;
}
route = TAKE_PTR(tmp);
route = route_ref(tmp);
is_new = true;
} else
@ -1020,7 +1053,7 @@ static int process_route_one(
if (route) {
route_enter_removed(route);
log_route_debug(route, "Forgetting removed", manager);
route_free(route);
route_detach(route);
} else
log_route_debug(tmp,
manager->manage_foreign_routes ? "Kernel removed unknown" : "Ignoring received",
@ -1047,7 +1080,7 @@ static int process_route_one(
}
int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
_cleanup_(route_freep) Route *tmp = NULL;
_cleanup_(route_unrefp) Route *tmp = NULL;
int r;
assert(rtnl);
@ -1190,17 +1223,17 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
has_cacheinfo = r >= 0;
if (tmp->family == AF_INET || ordered_set_isempty(tmp->nexthops))
return process_route_one(m, type, TAKE_PTR(tmp), has_cacheinfo ? &cacheinfo : NULL);
return process_route_one(m, type, tmp, has_cacheinfo ? &cacheinfo : NULL);
RouteNextHop *nh;
ORDERED_SET_FOREACH(nh, tmp->nexthops) {
_cleanup_(route_freep) Route *dup = NULL;
_cleanup_(route_unrefp) Route *dup = NULL;
r = route_dup(tmp, nh, &dup);
if (r < 0)
return log_oom();
r = process_route_one(m, type, TAKE_PTR(dup), has_cacheinfo ? &cacheinfo : NULL);
r = process_route_one(m, type, dup, has_cacheinfo ? &cacheinfo : NULL);
if (r < 0)
return r;
}
@ -1248,7 +1281,7 @@ static bool route_by_kernel(const Route *route) {
}
static int link_unmark_route(Link *link, const Route *route, const RouteNextHop *nh) {
_cleanup_(route_freep) Route *tmp = NULL;
_cleanup_(route_unrefp) Route *tmp = NULL;
Route *existing;
int r;
@ -1400,7 +1433,7 @@ int link_foreignize_routes(Link *link) {
}
int network_add_ipv4ll_route(Network *network) {
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
unsigned section_line;
int r;
@ -1435,7 +1468,7 @@ int network_add_ipv4ll_route(Network *network) {
}
int network_add_default_route_on_device(Network *network) {
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
unsigned section_line;
int r;
@ -1475,7 +1508,7 @@ int config_parse_preferred_src(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
@ -1520,7 +1553,7 @@ int config_parse_destination(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
union in_addr_union *buffer;
unsigned char *prefixlen;
int r;
@ -1578,7 +1611,7 @@ int config_parse_route_priority(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
@ -1621,7 +1654,7 @@ int config_parse_route_scope(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
@ -1663,7 +1696,7 @@ int config_parse_route_table(
void *data,
void *userdata) {
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
Network *network = userdata;
int r;
@ -1707,7 +1740,7 @@ int config_parse_ipv6_route_preference(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int r;
r = route_new_static(network, filename, section_line, &route);
@ -1748,7 +1781,7 @@ int config_parse_route_protocol(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int r;
r = route_new_static(network, filename, section_line, &route);
@ -1786,7 +1819,7 @@ int config_parse_route_type(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int t, r;
r = route_new_static(network, filename, section_line, &route);
@ -1871,5 +1904,5 @@ void network_drop_invalid_routes(Network *network) {
HASHMAP_FOREACH(route, network->routes_by_section)
if (route_section_verify(route) < 0)
route_free(route);
route_detach(route);
}

View File

@ -35,6 +35,8 @@ struct Route {
NetworkConfigState state;
union in_addr_union provider; /* DHCP server or router address */
unsigned n_ref;
/* rtmsg header */
int family;
unsigned char dst_prefixlen;
@ -80,8 +82,9 @@ struct Route {
extern const struct hash_ops route_hash_ops;
Route* route_free(Route *route);
DEFINE_SECTION_CLEANUP_FUNCTIONS(Route, route_free);
Route* route_ref(Route *route);
Route* route_unref(Route *route);
DEFINE_SECTION_CLEANUP_FUNCTIONS(Route, route_unref);
int route_new(Route **ret);
int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret);