From: Yu Watanabe Date: Mon, 28 Feb 2022 01:55:51 +0000 (+0900) Subject: network: re-design request queue X-Git-Tag: v251-rc1~164^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=09d09207dece533ced25c91024ce7a1c0ed660d8;p=thirdparty%2Fsystemd.git network: re-design request queue This makes Request object takes hash, compare, free, and process functions. With this change, the logic in networkd-queue.c can be mostly independent of the type of the request or the object (e.g. Address) assigned to the request, and it becomes simpler. --- diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index ee3b883b5ca..187b24c5582 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -629,7 +629,7 @@ static int netdev_is_ready_to_create(NetDev *netdev, Link *link) { return true; } -int stacked_netdev_process_request(Request *req, Link *link, void *userdata) { +static int stacked_netdev_process_request(Request *req, Link *link, void *userdata) { NetDev *netdev = ASSERT_PTR(userdata); int r; @@ -682,10 +682,12 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) { return 0; /* Already created. */ link->stacked_netdevs_created = false; - r = link_queue_request(link, REQUEST_TYPE_NETDEV_STACKED, netdev_ref(netdev), true, - &link->create_stacked_netdev_messages, - create_stacked_netdev_handler, - NULL); + r = link_queue_request_full(link, REQUEST_TYPE_NETDEV_STACKED, + netdev_ref(netdev), (mfree_func_t) netdev_unref, + trivial_hash_func, trivial_compare_func, + stacked_netdev_process_request, + &link->create_stacked_netdev_messages, + create_stacked_netdev_handler, NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to request stacked netdev '%s': %m", netdev->ifname); @@ -694,7 +696,7 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) { return 0; } -int independent_netdev_process_request(Request *req, Link *link, void *userdata) { +static int independent_netdev_process_request(Request *req, Link *link, void *userdata) { NetDev *netdev = ASSERT_PTR(userdata); int r; @@ -730,9 +732,9 @@ static int netdev_request_to_create(NetDev *netdev) { } else { /* Otherwise, wait for the dependencies being resolved. */ - r = netdev_queue_request(netdev, NULL); + r = netdev_queue_request(netdev, independent_netdev_process_request, NULL); if (r < 0) - return log_netdev_warning_errno(netdev, r, "Failed to request to create: %m"); + return log_netdev_warning_errno(netdev, r, "Failed to request to create netdev: %m"); } return 0; diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 4c2e949fb28..6054e322d65 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -109,7 +109,6 @@ typedef enum NetDevCreateType { typedef struct Manager Manager; typedef struct Condition Condition; -typedef struct Request Request; typedef struct NetDev { Manager *manager; @@ -209,8 +208,6 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink); int netdev_generate_hw_addr(NetDev *netdev, Link *link, const char *name, const struct hw_addr_data *hw_addr, struct hw_addr_data *ret); -int independent_netdev_process_request(Request *req, Link *link, void *userdata); -int stacked_netdev_process_request(Request *req, Link *link, void *userdata); int link_request_stacked_netdev(Link *link, NetDev *netdev); const char *netdev_kind_to_string(NetDevKind d) _const_; diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index 5c31a44ce42..745b959f774 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -124,7 +124,7 @@ static int address_label_configure(AddressLabel *label, Link *link, Request *req return request_call_netlink_async(link->manager->rtnl, m, req); } -int address_label_process_request(Request *req, Link *link, void *userdata) { +static int address_label_process_request(Request *req, Link *link, void *userdata) { AddressLabel *label = ASSERT_PTR(userdata); int r; @@ -151,8 +151,11 @@ int link_request_static_address_labels(Link *link) { link->static_address_labels_configured = false; HASHMAP_FOREACH(label, link->network->address_labels_by_section) { - r = link_queue_request(link, REQUEST_TYPE_ADDRESS_LABEL, label, false, - &link->static_address_label_messages, address_label_configure_handler, NULL); + r = link_queue_request_full(link, REQUEST_TYPE_ADDRESS_LABEL, + label, NULL, trivial_hash_func, trivial_compare_func, + address_label_process_request, + &link->static_address_label_messages, + address_label_configure_handler, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request address label: %m"); } diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h index 19bb0383e65..1e2ee70deeb 100644 --- a/src/network/networkd-address-label.h +++ b/src/network/networkd-address-label.h @@ -9,7 +9,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef struct AddressLabel { Network *network; @@ -26,7 +25,6 @@ AddressLabel *address_label_free(AddressLabel *label); void network_drop_invalid_address_labels(Network *network); int link_request_static_address_labels(Link *link); -int address_label_process_request(Request *req, Link *link, void *userdata); CONFIG_PARSER_PROTOTYPE(config_parse_address_label); CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index e9a79d352d1..19a357130b5 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -316,7 +316,7 @@ DEFINE_PRIVATE_HASH_OPS( address_kernel_hash_func, address_kernel_compare_func); -void address_hash_func(const Address *a, struct siphash *state) { +static void address_hash_func(const Address *a, struct siphash *state) { assert(a); siphash24_compress(&a->family, sizeof(a->family), state); @@ -1104,7 +1104,7 @@ static bool address_is_ready_to_configure(Link *link, const Address *address) { return true; } -int address_process_request(Request *req, Link *link, Address *address) { +static int address_process_request(Request *req, Link *link, Address *address) { int r; assert(req); @@ -1196,8 +1196,12 @@ int link_request_address( return r; log_address_debug(existing, "Requesting", link); - r = link_queue_request(link, REQUEST_TYPE_ADDRESS, existing, false, - message_counter, (request_netlink_handler_t) netlink_handler, ret); + r = link_queue_request_safe(link, REQUEST_TYPE_ADDRESS, + existing, NULL, + address_hash_func, + address_compare_func, + address_process_request, + message_counter, netlink_handler, ret); if (r < 0) return log_link_warning_errno(link, r, "Failed to request address: %m"); if (r == 0) @@ -1281,7 +1285,9 @@ void address_cancel_request(Address *address) { req = (Request) { .link = address->link, .type = REQUEST_TYPE_ADDRESS, - .address = address, + .userdata = address, + .hash_func = (hash_func_t) address_hash_func, + .compare_func = (compare_func_t) address_compare_func, }; request_detach(address->link->manager, &req); diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index a41274a1fc3..563a3de4e27 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -107,13 +107,11 @@ int link_request_address( Request **ret); int link_request_static_address(Link *link, Address *address, bool consume); int link_request_static_addresses(Link *link); -int address_process_request(Request *req, Link *link, Address *address); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); int network_drop_invalid_addresses(Network *network); -void address_hash_func(const Address *a, struct siphash *state); int address_compare_func(const Address *a1, const Address *a2); DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Address, address); diff --git a/src/network/networkd-bridge-fdb.c b/src/network/networkd-bridge-fdb.c index cc02213c28a..803e27cdae1 100644 --- a/src/network/networkd-bridge-fdb.c +++ b/src/network/networkd-bridge-fdb.c @@ -208,7 +208,7 @@ static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) { return true; } -int bridge_fdb_process_request(Request *req, Link *link, void *userdata) { +static int bridge_fdb_process_request(Request *req, Link *link, void *userdata) { BridgeFDB *fdb = ASSERT_PTR(userdata); int r; @@ -235,8 +235,14 @@ int link_request_static_bridge_fdb(Link *link) { link->static_bridge_fdb_configured = false; HASHMAP_FOREACH(fdb, link->network->bridge_fdb_entries_by_section) { - r = link_queue_request(link, REQUEST_TYPE_BRIDGE_FDB, fdb, false, - &link->static_bridge_fdb_messages, bridge_fdb_configure_handler, NULL); + r = link_queue_request_full(link, REQUEST_TYPE_BRIDGE_FDB, + fdb, NULL, + trivial_hash_func, + trivial_compare_func, + bridge_fdb_process_request, + &link->static_bridge_fdb_messages, + bridge_fdb_configure_handler, + NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to request static bridge FDB entry: %m"); } diff --git a/src/network/networkd-bridge-fdb.h b/src/network/networkd-bridge-fdb.h index 6a6e80384ec..b59d673d048 100644 --- a/src/network/networkd-bridge-fdb.h +++ b/src/network/networkd-bridge-fdb.h @@ -14,7 +14,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef enum NeighborCacheEntryFlags { NEIGHBOR_CACHE_ENTRY_FLAGS_USE = NTF_USE, @@ -47,8 +46,6 @@ void network_drop_invalid_bridge_fdb_entries(Network *network); int link_request_static_bridge_fdb(Link *link); -int bridge_fdb_process_request(Request *req, Link *link, void *userdata); - CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id); CONFIG_PARSER_PROTOTYPE(config_parse_fdb_destination); diff --git a/src/network/networkd-bridge-mdb.c b/src/network/networkd-bridge-mdb.c index 88ae091c1a5..3af4afe4a1d 100644 --- a/src/network/networkd-bridge-mdb.c +++ b/src/network/networkd-bridge-mdb.c @@ -194,7 +194,7 @@ static bool bridge_mdb_is_ready_to_configure(Link *link) { return true; } -int bridge_mdb_process_request(Request *req, Link *link, void *userdata) { +static int bridge_mdb_process_request(Request *req, Link *link, void *userdata) { BridgeMDB *mdb = ASSERT_PTR(userdata); int r; @@ -227,8 +227,14 @@ int link_request_static_bridge_mdb(Link *link) { goto finish; HASHMAP_FOREACH(mdb, link->network->bridge_mdb_entries_by_section) { - r = link_queue_request(link, REQUEST_TYPE_BRIDGE_MDB, mdb, false, - &link->static_bridge_mdb_messages, bridge_mdb_configure_handler, NULL); + r = link_queue_request_full(link, REQUEST_TYPE_BRIDGE_MDB, + mdb, NULL, + trivial_hash_func, + trivial_compare_func, + bridge_mdb_process_request, + &link->static_bridge_mdb_messages, + bridge_mdb_configure_handler, + NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to request MDB entry to multicast group database: %m"); } diff --git a/src/network/networkd-bridge-mdb.h b/src/network/networkd-bridge-mdb.h index c9a34af88ad..edea255769d 100644 --- a/src/network/networkd-bridge-mdb.h +++ b/src/network/networkd-bridge-mdb.h @@ -9,7 +9,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef struct BridgeMDB { Network *network; @@ -25,7 +24,6 @@ BridgeMDB *bridge_mdb_free(BridgeMDB *mdb); void network_drop_invalid_bridge_mdb_entries(Network *network); int link_request_static_bridge_mdb(Link *link); -int bridge_mdb_process_request(Request *req, Link *link, void *userdata); CONFIG_PARSER_PROTOTYPE(config_parse_mdb_group_address); CONFIG_PARSER_PROTOTYPE(config_parse_mdb_vlan_id); diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index b11ff073bcf..3d24cbaf3ce 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -567,7 +567,7 @@ static bool dhcp_server_is_ready_to_configure(Link *link) { return true; } -int dhcp_server_process_request(Request *req, Link *link, void *userdata) { +static int dhcp_server_process_request(Request *req, Link *link, void *userdata) { int r; assert(link); @@ -594,7 +594,7 @@ int link_request_dhcp_server(Link *link) { return 0; log_link_debug(link, "Requesting DHCP server."); - r = link_queue_request(link, REQUEST_TYPE_DHCP_SERVER, NULL, false, NULL, NULL, NULL); + r = link_queue_request(link, REQUEST_TYPE_DHCP_SERVER, dhcp_server_process_request, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request configuration of DHCP server: %m"); diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h index 7a204e7d0a0..cb2a8b6a34b 100644 --- a/src/network/networkd-dhcp-server.h +++ b/src/network/networkd-dhcp-server.h @@ -5,13 +5,11 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; void network_adjust_dhcp_server(Network *network); int link_request_dhcp_server_address(Link *link); int link_request_dhcp_server(Link *link); -int dhcp_server_process_request(Request *req, Link *link, void *userdata); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index dcde7f9bedb..2fcb9c853f3 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1589,7 +1589,7 @@ static int dhcp4_configure_duid(Link *link) { return dhcp_configure_duid(link, link_get_dhcp4_duid(link)); } -int dhcp4_process_request(Request *req, Link *link, void *userdata) { +static int dhcp4_process_request(Request *req, Link *link, void *userdata) { int r; assert(link); @@ -1630,7 +1630,7 @@ int link_request_dhcp4_client(Link *link) { if (link->dhcp_client) return 0; - r = link_queue_request(link, REQUEST_TYPE_DHCP4_CLIENT, NULL, false, NULL, NULL, NULL); + r = link_queue_request(link, REQUEST_TYPE_DHCP4_CLIENT, dhcp4_process_request, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request configuring of the DHCPv4 client: %m"); diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index 4e466ca4f96..1d30cd15dfb 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -5,7 +5,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef enum DHCPClientIdentifier { DHCP_CLIENT_ID_MAC, @@ -25,7 +24,6 @@ int dhcp4_start(Link *link); int dhcp4_lease_lost(Link *link); int dhcp4_check_ready(Link *link); -int dhcp4_process_request(Request *req, Link *link, void *userdata); int link_request_dhcp4_client(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index bceae735b09..c443098889c 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -712,7 +712,7 @@ int dhcp6_update_mac(Link *link) { return 0; } -int dhcp6_process_request(Request *req, Link *link, void *userdata) { +static int dhcp6_process_request(Request *req, Link *link, void *userdata) { int r; assert(link); @@ -757,7 +757,7 @@ int link_request_dhcp6_client(Link *link) { if (link->dhcp6_client) return 0; - r = link_queue_request(link, REQUEST_TYPE_DHCP6_CLIENT, NULL, false, NULL, NULL, NULL); + r = link_queue_request(link, REQUEST_TYPE_DHCP6_CLIENT, dhcp6_process_request, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request configuring of the DHCPv6 client: %m"); diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h index e3bc57cc300..81267c255f6 100644 --- a/src/network/networkd-dhcp6.h +++ b/src/network/networkd-dhcp6.h @@ -13,7 +13,6 @@ typedef enum DHCP6ClientStartMode { } DHCP6ClientStartMode; typedef struct Link Link; -typedef struct Request Request; bool link_dhcp6_with_address_enabled(Link *link); int dhcp6_check_ready(Link *link); @@ -21,7 +20,6 @@ int dhcp6_update_mac(Link *link); int dhcp6_start(Link *link); int dhcp6_start_on_ra(Link *link, bool information_request); -int dhcp6_process_request(Request *req, Link *link, void *userdata); int link_request_dhcp6_client(Link *link); int link_serialize_dhcp6_client(Link *link, FILE *f); diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index b245a9eba26..8166851ed3c 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -78,7 +78,7 @@ static int ipv6_proxy_ndp_address_configure(const struct in6_addr *address, Link return request_call_netlink_async(link->manager->rtnl, m, req); } -int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address) { +static int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address) { int r; assert(req); @@ -105,10 +105,14 @@ int link_request_static_ipv6_proxy_ndp_addresses(Link *link) { link->static_ipv6_proxy_ndp_configured = false; SET_FOREACH(address, link->network->ipv6_proxy_ndp_addresses) { - r = link_queue_request(link, REQUEST_TYPE_IPV6_PROXY_NDP, address, false, - &link->static_ipv6_proxy_ndp_messages, - (request_netlink_handler_t) ipv6_proxy_ndp_address_configure_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_IPV6_PROXY_NDP, + address, NULL, + in6_addr_hash_func, + in6_addr_compare_func, + ipv6_proxy_ndp_address_process_request, + &link->static_ipv6_proxy_ndp_messages, + ipv6_proxy_ndp_address_configure_handler, + NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request IPv6 proxy NDP address: %m"); } diff --git a/src/network/networkd-ipv6-proxy-ndp.h b/src/network/networkd-ipv6-proxy-ndp.h index 39a78205999..e57d28f99dd 100644 --- a/src/network/networkd-ipv6-proxy-ndp.h +++ b/src/network/networkd-ipv6-proxy-ndp.h @@ -5,11 +5,9 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; void network_adjust_ipv6_proxy_ndp(Network *network); int link_request_static_ipv6_proxy_ndp_addresses(Link *link); -int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 2a85fb3cfb1..8cbc67f5429 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1116,7 +1116,7 @@ int ndisc_start(Link *link) { return 1; } -int ndisc_process_request(Request *req, Link *link, void *userdata) { +static int ndisc_process_request(Request *req, Link *link, void *userdata) { int r; assert(link); @@ -1152,7 +1152,7 @@ int link_request_ndisc(Link *link) { if (link->ndisc) return 0; - r = link_queue_request(link, REQUEST_TYPE_NDISC, NULL, false, NULL, NULL, NULL); + r = link_queue_request(link, REQUEST_TYPE_NDISC, ndisc_process_request, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Discovery: %m"); diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index 5a7eb58a562..f88a002c73e 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -6,7 +6,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef enum IPv6AcceptRAStartDHCP6Client { IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO, @@ -48,7 +47,6 @@ int ndisc_start(Link *link); void ndisc_vacuum(Link *link); void ndisc_flush(Link *link); -int ndisc_process_request(Request *req, Link *link, void *userdata); int link_request_ndisc(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client); diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 1cb5333b661..435fa7002e2 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -87,7 +87,7 @@ static int neighbor_dup(const Neighbor *neighbor, Neighbor **ret) { return 0; } -void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) { +static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) { assert(neighbor); siphash24_compress(&neighbor->family, sizeof(neighbor->family), state); @@ -106,7 +106,7 @@ void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) { hw_addr_hash_func(&neighbor->ll_addr, state); } -int neighbor_compare_func(const Neighbor *a, const Neighbor *b) { +static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) { int r; r = CMP(a->family, b->family); @@ -218,7 +218,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) { return request_call_netlink_async(link->manager->rtnl, m, req); } -int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) { +static int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) { int r; assert(req); @@ -282,10 +282,14 @@ static int link_request_neighbor(Link *link, const Neighbor *neighbor) { existing->source = neighbor->source; log_neighbor_debug(existing, "Requesting", link); - r = link_queue_request(link, REQUEST_TYPE_NEIGHBOR, existing, false, - &link->static_neighbor_messages, - (request_netlink_handler_t) static_neighbor_configure_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_NEIGHBOR, + existing, NULL, + neighbor_hash_func, + neighbor_compare_func, + neighbor_process_request, + &link->static_neighbor_messages, + static_neighbor_configure_handler, + NULL); if (r <= 0) return r; diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h index 52a7733a893..758475a8ff6 100644 --- a/src/network/networkd-neighbor.h +++ b/src/network/networkd-neighbor.h @@ -13,7 +13,6 @@ typedef struct Link Link; typedef struct Manager Manager; typedef struct Network Network; -typedef struct Request Request; typedef struct Neighbor { Network *network; @@ -29,9 +28,6 @@ typedef struct Neighbor { Neighbor *neighbor_free(Neighbor *neighbor); -void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state); -int neighbor_compare_func(const Neighbor *a, const Neighbor *b); - void network_drop_invalid_neighbors(Network *network); int link_drop_managed_neighbors(Link *link); @@ -39,7 +35,6 @@ int link_drop_foreign_neighbors(Link *link); void link_foreignize_neighbors(Link *link); int link_request_static_neighbors(Link *link); -int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor); int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index 219a08e1597..3eb9d62f7c7 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -104,7 +104,7 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s return 0; } -void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) { +static void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) { assert(nexthop); siphash24_compress(&nexthop->protocol, sizeof(nexthop->protocol), state); @@ -124,7 +124,7 @@ void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) { } } -int nexthop_compare_func(const NextHop *a, const NextHop *b) { +static int nexthop_compare_func(const NextHop *a, const NextHop *b) { int r; r = CMP(a->protocol, b->protocol); @@ -546,7 +546,7 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) { ORDERED_SET_FOREACH(req, link->manager->request_queue) { if (req->type != REQUEST_TYPE_NEXTHOP) continue; - if (req->nexthop->id != 0) + if (((NextHop*) req->userdata)->id != 0) return false; /* first configure nexthop with id. */ } } @@ -554,7 +554,7 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) { return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw); } -int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) { +static int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) { int r; assert(req); @@ -600,10 +600,14 @@ static int link_request_nexthop(Link *link, NextHop *nexthop) { existing->source = nexthop->source; log_nexthop_debug(existing, "Requesting", link); - r = link_queue_request(link, REQUEST_TYPE_NEXTHOP, existing, false, - &link->static_nexthop_messages, - (request_netlink_handler_t) static_nexthop_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_NEXTHOP, + existing, NULL, + nexthop_hash_func, + nexthop_compare_func, + nexthop_process_request, + &link->static_nexthop_messages, + static_nexthop_handler, + NULL); if (r <= 0) return r; diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h index c5b58e5d38a..6f2aa6f6dc3 100644 --- a/src/network/networkd-nexthop.h +++ b/src/network/networkd-nexthop.h @@ -16,7 +16,6 @@ typedef struct Link Link; typedef struct Manager Manager; typedef struct Network Network; -typedef struct Request Request; typedef struct NextHop { Network *network; @@ -39,9 +38,6 @@ typedef struct NextHop { NextHop *nexthop_free(NextHop *nexthop); -void nexthop_hash_func(const NextHop *nexthop, struct siphash *state); -int nexthop_compare_func(const NextHop *a, const NextHop *b); - void network_drop_invalid_nexthops(Network *network); int link_drop_managed_nexthops(Link *link); @@ -49,7 +45,6 @@ int link_drop_foreign_nexthops(Link *link); void link_foreignize_nexthops(Link *link); int link_request_static_nexthops(Link *link, bool only_ipv4); -int nexthop_process_request(Request *req, Link *link, NextHop *nexthop); int manager_get_nexthop_by_id(Manager *manager, uint32_t id, NextHop **ret); int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index ecfb7acdd2d..1463f610b25 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -1,93 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "netdev.h" #include "netlink-util.h" -#include "networkd-address.h" -#include "networkd-address-label.h" -#include "networkd-bridge-fdb.h" -#include "networkd-bridge-mdb.h" -#include "networkd-dhcp-server.h" -#include "networkd-dhcp4.h" -#include "networkd-dhcp6.h" -#include "networkd-ipv6-proxy-ndp.h" +#include "networkd-link.h" #include "networkd-manager.h" -#include "networkd-ndisc.h" -#include "networkd-neighbor.h" -#include "networkd-nexthop.h" -#include "networkd-route.h" -#include "networkd-routing-policy-rule.h" #include "networkd-queue.h" -#include "networkd-setlink.h" -#include "qdisc.h" #include "string-table.h" -#include "tclass.h" - -static void request_free_object(RequestType type, void *object) { - switch (type) { - case REQUEST_TYPE_ACTIVATE_LINK: - break; - case REQUEST_TYPE_ADDRESS: - address_free(object); - break; - case REQUEST_TYPE_ADDRESS_LABEL: - address_label_free(object); - break; - case REQUEST_TYPE_BRIDGE_FDB: - bridge_fdb_free(object); - break; - case REQUEST_TYPE_BRIDGE_MDB: - bridge_mdb_free(object); - break; - case REQUEST_TYPE_DHCP_SERVER: - case REQUEST_TYPE_DHCP4_CLIENT: - case REQUEST_TYPE_DHCP6_CLIENT: - break; - case REQUEST_TYPE_IPV6_PROXY_NDP: - free(object); - break; - case REQUEST_TYPE_NDISC: - break; - case REQUEST_TYPE_NEIGHBOR: - neighbor_free(object); - break; - case REQUEST_TYPE_NETDEV_INDEPENDENT: - case REQUEST_TYPE_NETDEV_STACKED: - netdev_unref(object); - break; - case REQUEST_TYPE_NEXTHOP: - nexthop_free(object); - break; - case REQUEST_TYPE_RADV: - break; - case REQUEST_TYPE_ROUTE: - route_free(object); - break; - case REQUEST_TYPE_ROUTING_POLICY_RULE: - routing_policy_rule_free(object); - break; - case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: - case REQUEST_TYPE_SET_LINK_BOND: - case REQUEST_TYPE_SET_LINK_BRIDGE: - case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: - case REQUEST_TYPE_SET_LINK_CAN: - case REQUEST_TYPE_SET_LINK_FLAGS: - case REQUEST_TYPE_SET_LINK_GROUP: - case REQUEST_TYPE_SET_LINK_IPOIB: - case REQUEST_TYPE_SET_LINK_MAC: - case REQUEST_TYPE_SET_LINK_MASTER: - case REQUEST_TYPE_SET_LINK_MTU: - break; - case REQUEST_TYPE_TC_QDISC: - qdisc_free(object); - break; - case REQUEST_TYPE_TC_CLASS: - tclass_free(object); - break; - case REQUEST_TYPE_UP_DOWN: - break; - default: - assert_not_reached(); - } -} static Request *request_free(Request *req) { if (!req) @@ -98,8 +16,8 @@ static Request *request_free(Request *req) { if (req->manager) ordered_set_remove(req->manager->request_queue, req); - if (req->consume_object) - request_free_object(req->type, req->object); + if (req->free_func) + req->free_func(req->userdata); if (req->counter) (*req->counter)--; @@ -136,70 +54,11 @@ static void request_hash_func(const Request *req, struct siphash *state) { siphash24_compress(&req->type, sizeof(req->type), state); - switch (req->type) { - case REQUEST_TYPE_ACTIVATE_LINK: - break; - case REQUEST_TYPE_ADDRESS: - address_hash_func(req->address, state); - break; - case REQUEST_TYPE_ADDRESS_LABEL: - case REQUEST_TYPE_BRIDGE_FDB: - case REQUEST_TYPE_BRIDGE_MDB: - case REQUEST_TYPE_NETDEV_INDEPENDENT: - case REQUEST_TYPE_NETDEV_STACKED: - /* TODO: Currently, these types do not have any specific hash and compare functions. - * Fortunately, all these objects are 'static', thus we can use the trivial functions. */ - trivial_hash_func(req->object, state); - break; - case REQUEST_TYPE_DHCP_SERVER: - case REQUEST_TYPE_DHCP4_CLIENT: - case REQUEST_TYPE_DHCP6_CLIENT: - /* These types do not have an object. */ - break; - case REQUEST_TYPE_IPV6_PROXY_NDP: - in6_addr_hash_func(req->ipv6_proxy_ndp, state); - break; - case REQUEST_TYPE_NDISC: - /* This type does not have an object. */ - break; - case REQUEST_TYPE_NEIGHBOR: - neighbor_hash_func(req->neighbor, state); - break; - case REQUEST_TYPE_NEXTHOP: - nexthop_hash_func(req->nexthop, state); - break; - case REQUEST_TYPE_RADV: - /* This type does not have an object. */ - break; - case REQUEST_TYPE_ROUTE: - route_hash_func(req->route, state); - break; - case REQUEST_TYPE_ROUTING_POLICY_RULE: - routing_policy_rule_hash_func(req->rule, state); - break; - case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: - case REQUEST_TYPE_SET_LINK_BOND: - case REQUEST_TYPE_SET_LINK_BRIDGE: - case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: - case REQUEST_TYPE_SET_LINK_CAN: - case REQUEST_TYPE_SET_LINK_FLAGS: - case REQUEST_TYPE_SET_LINK_GROUP: - case REQUEST_TYPE_SET_LINK_IPOIB: - case REQUEST_TYPE_SET_LINK_MAC: - case REQUEST_TYPE_SET_LINK_MASTER: - case REQUEST_TYPE_SET_LINK_MTU: - break; - case REQUEST_TYPE_TC_QDISC: - qdisc_hash_func(req->qdisc, state); - break; - case REQUEST_TYPE_TC_CLASS: - tclass_hash_func(req->tclass, state); - break; - case REQUEST_TYPE_UP_DOWN: - break; - default: - assert_not_reached(); - } + siphash24_compress(&req->hash_func, sizeof(req->hash_func), state); + siphash24_compress(&req->compare_func, sizeof(req->compare_func), state); + + if (req->hash_func) + req->hash_func(req->userdata, state); } static int request_compare_func(const struct Request *a, const struct Request *b) { @@ -222,56 +81,18 @@ static int request_compare_func(const struct Request *a, const struct Request *b if (r != 0) return r; - switch (a->type) { - case REQUEST_TYPE_ACTIVATE_LINK: - return 0; - case REQUEST_TYPE_ADDRESS: - return address_compare_func(a->address, b->address); - case REQUEST_TYPE_ADDRESS_LABEL: - case REQUEST_TYPE_BRIDGE_FDB: - case REQUEST_TYPE_BRIDGE_MDB: - case REQUEST_TYPE_NETDEV_INDEPENDENT: - case REQUEST_TYPE_NETDEV_STACKED: - return trivial_compare_func(a->object, b->object); - case REQUEST_TYPE_DHCP_SERVER: - case REQUEST_TYPE_DHCP4_CLIENT: - case REQUEST_TYPE_DHCP6_CLIENT: - return 0; - case REQUEST_TYPE_IPV6_PROXY_NDP: - return in6_addr_compare_func(a->ipv6_proxy_ndp, b->ipv6_proxy_ndp); - case REQUEST_TYPE_NDISC: - return 0; - case REQUEST_TYPE_NEIGHBOR: - return neighbor_compare_func(a->neighbor, b->neighbor); - case REQUEST_TYPE_NEXTHOP: - return nexthop_compare_func(a->nexthop, b->nexthop); - case REQUEST_TYPE_ROUTE: - return route_compare_func(a->route, b->route); - case REQUEST_TYPE_RADV: - return 0; - case REQUEST_TYPE_ROUTING_POLICY_RULE: - return routing_policy_rule_compare_func(a->rule, b->rule); - case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: - case REQUEST_TYPE_SET_LINK_BOND: - case REQUEST_TYPE_SET_LINK_BRIDGE: - case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: - case REQUEST_TYPE_SET_LINK_CAN: - case REQUEST_TYPE_SET_LINK_FLAGS: - case REQUEST_TYPE_SET_LINK_GROUP: - case REQUEST_TYPE_SET_LINK_IPOIB: - case REQUEST_TYPE_SET_LINK_MAC: - case REQUEST_TYPE_SET_LINK_MASTER: - case REQUEST_TYPE_SET_LINK_MTU: - return 0; - case REQUEST_TYPE_TC_QDISC: - return qdisc_compare_func(a->qdisc, b->qdisc); - case REQUEST_TYPE_TC_CLASS: - return tclass_compare_func(a->tclass, b->tclass); - case REQUEST_TYPE_UP_DOWN: - return 0; - default: - assert_not_reached(); - } + r = CMP(PTR_TO_UINT64(a->hash_func), PTR_TO_UINT64(b->hash_func)); + if (r != 0) + return r; + + r = CMP(PTR_TO_UINT64(a->compare_func), PTR_TO_UINT64(b->compare_func)); + if (r != 0) + return r; + + if (a->compare_func) + return a->compare_func(a->userdata, b->userdata); + + return 0; } DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( @@ -281,54 +102,15 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( request_compare_func, request_unref); -int netdev_queue_request( - NetDev *netdev, - Request **ret) { - - _cleanup_(request_unrefp) Request *req = NULL; - Request *existing; - int r; - - assert(netdev); - assert(netdev->manager); - - req = new(Request, 1); - if (!req) - return -ENOMEM; - - *req = (Request) { - .n_ref = 1, - .manager = netdev->manager, - .netdev = netdev_ref(netdev), - .type = REQUEST_TYPE_NETDEV_INDEPENDENT, - .consume_object = true, - }; - - existing = ordered_set_get(netdev->manager->request_queue, req); - if (existing) { - if (ret) - *ret = existing; - return 0; - } - - r = ordered_set_ensure_put(&netdev->manager->request_queue, &request_hash_ops, req); - if (r < 0) - return r; - - req->manager = netdev->manager; - - if (ret) - *ret = req; - - TAKE_PTR(req); - return 1; -} - -int link_queue_request( +static int request_new( + Manager *manager, Link *link, RequestType type, - void *object, - bool consume_object, + void *userdata, + mfree_func_t free_func, + hash_func_t hash_func, + compare_func_t compare_func, + request_process_func_t process, unsigned *counter, request_netlink_handler_t netlink_handler, Request **ret) { @@ -337,65 +119,40 @@ int link_queue_request( Request *existing; int r; - assert(link); - assert(link->manager); - assert(type >= 0 && type < _REQUEST_TYPE_MAX); - assert(IN_SET(type, - REQUEST_TYPE_ACTIVATE_LINK, - REQUEST_TYPE_DHCP_SERVER, - REQUEST_TYPE_DHCP4_CLIENT, - REQUEST_TYPE_DHCP6_CLIENT, - REQUEST_TYPE_NDISC, - REQUEST_TYPE_RADV, - REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE, - REQUEST_TYPE_SET_LINK_BOND, - REQUEST_TYPE_SET_LINK_BRIDGE, - REQUEST_TYPE_SET_LINK_BRIDGE_VLAN, - REQUEST_TYPE_SET_LINK_CAN, - REQUEST_TYPE_SET_LINK_FLAGS, - REQUEST_TYPE_SET_LINK_GROUP, - REQUEST_TYPE_SET_LINK_IPOIB, - REQUEST_TYPE_SET_LINK_MAC, - REQUEST_TYPE_SET_LINK_MASTER, - REQUEST_TYPE_SET_LINK_MTU, - REQUEST_TYPE_UP_DOWN) || - object); - assert(IN_SET(type, - REQUEST_TYPE_DHCP_SERVER, - REQUEST_TYPE_DHCP4_CLIENT, - REQUEST_TYPE_DHCP6_CLIENT, - REQUEST_TYPE_NDISC, - REQUEST_TYPE_RADV) || - netlink_handler); + assert(manager); + assert(process); req = new(Request, 1); if (!req) { - if (consume_object) - request_free_object(type, object); + if (free_func) + free_func(userdata); return -ENOMEM; } *req = (Request) { .n_ref = 1, - .link = link_ref(link), + .link = link_ref(link), /* link may be NULL, but link_ref() handles it gracefully. */ .type = type, - .object = object, - .consume_object = consume_object, + .userdata = userdata, + .free_func = free_func, + .hash_func = hash_func, + .compare_func = compare_func, + .process = process, .netlink_handler = netlink_handler, }; - existing = ordered_set_get(link->manager->request_queue, req); + existing = ordered_set_get(manager->request_queue, req); if (existing) { if (ret) *ret = existing; return 0; } - r = ordered_set_ensure_put(&link->manager->request_queue, &request_hash_ops, req); + r = ordered_set_ensure_put(&manager->request_queue, &request_hash_ops, req); if (r < 0) return r; - req->manager = link->manager; + req->manager = manager; req->counter = counter; if (req->counter) (*req->counter)++; @@ -407,12 +164,42 @@ int link_queue_request( return 1; } +int netdev_queue_request( + NetDev *netdev, + request_process_func_t process, + Request **ret) { + + assert(netdev); + + return request_new(netdev->manager, NULL, REQUEST_TYPE_NETDEV_INDEPENDENT, + netdev_ref(netdev), (mfree_func_t) netdev_unref, + trivial_hash_func, trivial_compare_func, + process, NULL, NULL, ret); +} + +int link_queue_request_full( + Link *link, + RequestType type, + void *userdata, + mfree_func_t free_func, + hash_func_t hash_func, + compare_func_t compare_func, + request_process_func_t process, + unsigned *counter, + request_netlink_handler_t netlink_handler, + Request **ret) { + + assert(link); + + return request_new(link->manager, link, type, + userdata, free_func, hash_func, compare_func, + process, counter, netlink_handler, ret); +} + int manager_process_requests(sd_event_source *s, void *userdata) { - Manager *manager = userdata; + Manager *manager = ASSERT_PTR(userdata); int r; - assert(manager); - for (;;) { bool processed = false; Request *req; @@ -421,83 +208,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) { _unused_ _cleanup_(request_unrefp) Request *ref = request_ref(req); _cleanup_(link_unrefp) Link *link = link_ref(req->link); - switch (req->type) { - case REQUEST_TYPE_ACTIVATE_LINK: - r = link_process_activation(req, req->link, req->userdata); - break; - case REQUEST_TYPE_ADDRESS: - r = address_process_request(req, req->link, req->address); - break; - case REQUEST_TYPE_ADDRESS_LABEL: - r = address_label_process_request(req, req->link, req->label); - break; - case REQUEST_TYPE_BRIDGE_FDB: - r = bridge_fdb_process_request(req, req->link, req->fdb); - break; - case REQUEST_TYPE_BRIDGE_MDB: - r = bridge_mdb_process_request(req, req->link, req->mdb); - break; - case REQUEST_TYPE_DHCP_SERVER: - r = dhcp_server_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_DHCP4_CLIENT: - r = dhcp4_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_DHCP6_CLIENT: - r = dhcp6_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_IPV6_PROXY_NDP: - r = ipv6_proxy_ndp_address_process_request(req, req->link, req->ipv6_proxy_ndp); - break; - case REQUEST_TYPE_NDISC: - r = ndisc_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_NEIGHBOR: - r = neighbor_process_request(req, req->link, req->neighbor); - break; - case REQUEST_TYPE_NETDEV_INDEPENDENT: - r = independent_netdev_process_request(req, req->link, req->netdev); - break; - case REQUEST_TYPE_NETDEV_STACKED: - r = stacked_netdev_process_request(req, req->link, req->netdev); - break; - case REQUEST_TYPE_NEXTHOP: - r = nexthop_process_request(req, req->link, req->nexthop); - break; - case REQUEST_TYPE_RADV: - r = radv_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_ROUTE: - r = route_process_request(req, req->link, req->route); - break; - case REQUEST_TYPE_ROUTING_POLICY_RULE: - r = routing_policy_rule_process_request(req, req->link, req->rule); - break; - case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE: - case REQUEST_TYPE_SET_LINK_BOND: - case REQUEST_TYPE_SET_LINK_BRIDGE: - case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN: - case REQUEST_TYPE_SET_LINK_CAN: - case REQUEST_TYPE_SET_LINK_FLAGS: - case REQUEST_TYPE_SET_LINK_GROUP: - case REQUEST_TYPE_SET_LINK_IPOIB: - case REQUEST_TYPE_SET_LINK_MAC: - case REQUEST_TYPE_SET_LINK_MASTER: - case REQUEST_TYPE_SET_LINK_MTU: - r = link_process_set_link(req, req->link, NULL); - break; - case REQUEST_TYPE_TC_QDISC: - r = qdisc_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_TC_CLASS: - r = tclass_process_request(req, req->link, NULL); - break; - case REQUEST_TYPE_UP_DOWN: - r = link_process_up_or_down(req, req->link, req->userdata); - break; - default: - return -EINVAL; - } + assert(req->process); + + r = req->process(req, link, req->userdata); if (r == 0) continue; @@ -533,7 +246,7 @@ static int request_netlink_handler(sd_netlink *nl, sd_netlink_message *m, Reques return 0; if (req->netlink_handler) - return req->netlink_handler(nl, m, req, req->link, req->object); + return req->netlink_handler(nl, m, req, req->link, req->userdata); return 0; } diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 0c822094e86..d1110119ccc 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -4,21 +4,15 @@ #include "sd-event.h" #include "sd-netlink.h" -#include "networkd-link.h" +#include "alloc-util.h" +#include "hash-funcs.h" -typedef struct Address Address; -typedef struct AddressLabel AddressLabel; -typedef struct BridgeFDB BridgeFDB; -typedef struct BridgeMDB BridgeMDB; -typedef struct Neighbor Neighbor; +typedef struct Link Link; typedef struct NetDev NetDev; -typedef struct NextHop NextHop; -typedef struct Route Route; -typedef struct RoutingPolicyRule RoutingPolicyRule; -typedef struct QDisc QDisc; -typedef struct TClass TClass; +typedef struct Manager Manager; typedef struct Request Request; +typedef int (*request_process_func_t)(Request *req, Link *link, void *userdata); typedef int (*request_netlink_handler_t)(sd_netlink *nl, sd_netlink_message *m, Request *req, Link *link, void *userdata); typedef enum RequestType { @@ -64,24 +58,19 @@ struct Request { Link *link; /* can be NULL */ RequestType type; - bool consume_object; - union { - Address *address; - AddressLabel *label; - BridgeFDB *fdb; - BridgeMDB *mdb; - struct in6_addr *ipv6_proxy_ndp; - Neighbor *neighbor; - NextHop *nexthop; - Route *route; - RoutingPolicyRule *rule; - void *set_link_operation_ptr; - NetDev *netdev; - QDisc *qdisc; - TClass *tclass; - void *object; - }; + + /* Target object, e.g. Address, Route, NetDev, and so on. */ void *userdata; + /* freeing userdata when the request is completed or failed. */ + mfree_func_t free_func; + + /* hash and compare functions for userdata, used for dedup requests. */ + hash_func_t hash_func; + compare_func_t compare_func; + + /* Checks the request dependencies, and then processes this request, e.g. call address_configure(). + * Return 1 when processed, 0 when its dependencies not resolved, and negative errno on failure. */ + request_process_func_t process; /* incremented when requested, decremented when request is completed or failed. */ unsigned *counter; @@ -100,17 +89,49 @@ void request_detach(Manager *manager, Request *req); int netdev_queue_request( NetDev *netdev, + request_process_func_t process, Request **ret); -int link_queue_request( +int link_queue_request_full( Link *link, RequestType type, - void *object, - bool consume_object, + void *userdata, + mfree_func_t free_func, + hash_func_t hash_func, + compare_func_t compare_func, + request_process_func_t process, unsigned *counter, request_netlink_handler_t netlink_handler, Request **ret); +static inline int link_queue_request( + Link *link, + RequestType type, + request_process_func_t process, + Request **ret) { + + return link_queue_request_full(link, type, NULL, NULL, NULL, NULL, + process, NULL, NULL, ret); +} + +#define link_queue_request_safe(link, type, userdata, free_func, hash_func, compare_func, process, counter, netlink_handler, ret) \ + ({ \ + typeof(userdata) (*_f)(typeof(userdata)) = (free_func); \ + void (*_h)(const typeof(*userdata)*, struct siphash*) = (hash_func); \ + int (*_c)(const typeof(*userdata)*, const typeof(*userdata)*) = (compare_func); \ + int (*_p)(Request*, Link*, typeof(userdata)) = (process); \ + int (*_n)(sd_netlink*, sd_netlink_message*, Request*, Link*, typeof(userdata)) = (netlink_handler); \ + \ + link_queue_request_full(link, type, userdata, \ + (mfree_func_t) _f, \ + (hash_func_t) _h, \ + (compare_func_t) _c, \ + (request_process_func_t) _p, \ + counter, \ + (request_netlink_handler_t) _n, \ + ret); \ + }) + int manager_process_requests(sd_event_source *s, void *userdata); int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index f6e1841c058..b9f5c55f4c5 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -582,7 +582,7 @@ static int radv_is_ready_to_configure(Link *link) { return true; } -int radv_process_request(Request *req, Link *link, void *userdata) { +static int radv_process_request(Request *req, Link *link, void *userdata) { int r; assert(link); @@ -617,7 +617,7 @@ int link_request_radv(Link *link) { if (link->radv) return 0; - r = link_queue_request(link, REQUEST_TYPE_RADV, NULL, false, NULL, NULL, NULL); + r = link_queue_request(link, REQUEST_TYPE_RADV, radv_process_request, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Advertisement engine: %m"); diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 0d340c955ed..ebebb3942b8 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -16,7 +16,6 @@ typedef struct Link Link; typedef struct Network Network; -typedef struct Request Request; typedef enum RADVPrefixDelegation { RADV_PREFIX_DELEGATION_NONE = 0, @@ -68,7 +67,6 @@ int radv_update_mac(Link *link); int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len, usec_t lifetime_preferred_usec, usec_t lifetime_valid_usec); -int radv_process_request(Request *req, Link *link, void *userdata); int link_request_radv(Link *link); const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index cfc69679632..c9fb872ae57 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -110,7 +110,7 @@ Route *route_free(Route *route) { return mfree(route); } -void route_hash_func(const Route *route, struct siphash *state) { +static void route_hash_func(const Route *route, struct siphash *state) { assert(route); siphash24_compress(&route->family, sizeof(route->family), state); @@ -152,7 +152,7 @@ void route_hash_func(const Route *route, struct siphash *state) { } } -int route_compare_func(const Route *a, const Route *b) { +static int route_compare_func(const Route *a, const Route *b) { int r; r = CMP(a->family, b->family); @@ -1310,7 +1310,7 @@ static int route_is_ready_to_configure(const Route *route, Link *link) { return true; } -int route_process_request(Request *req, Link *link, Route *route) { +static int route_process_request(Request *req, Link *link, Route *route) { _cleanup_(converted_routes_freep) ConvertedRoutes *converted = NULL; int r; @@ -1423,8 +1423,12 @@ int link_request_route( } log_route_debug(existing, "Requesting", link, link->manager); - r = link_queue_request(link, REQUEST_TYPE_ROUTE, existing, false, - message_counter, (request_netlink_handler_t) netlink_handler, ret); + r = link_queue_request_safe(link, REQUEST_TYPE_ROUTE, + existing, NULL, + route_hash_func, + route_compare_func, + route_process_request, + message_counter, netlink_handler, ret); if (r <= 0) return r; @@ -1460,10 +1464,10 @@ static int link_request_static_route(Link *link, Route *route) { static_route_handler, NULL); log_route_debug(route, "Requesting", link, link->manager); - return link_queue_request(link, REQUEST_TYPE_ROUTE, route, false, - &link->static_route_messages, - (request_netlink_handler_t) static_route_handler, - NULL); + return link_queue_request_safe(link, REQUEST_TYPE_ROUTE, + route, NULL, route_hash_func, route_compare_func, + route_process_request, + &link->static_route_messages, static_route_handler, NULL); } static int link_request_wireguard_routes(Link *link, bool only_ipv4) { @@ -1547,7 +1551,9 @@ void route_cancel_request(Route *route, Link *link) { req = (Request) { .link = link, .type = REQUEST_TYPE_ROUTE, - .route = route, + .userdata = route, + .hash_func = (hash_func_t) route_hash_func, + .compare_func = (compare_func_t) route_compare_func, }; request_detach(link->manager, &req); diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 8c1c5cf6809..b431e1a30f4 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -75,8 +75,6 @@ struct Route { sd_event_source *expire; }; -void route_hash_func(const Route *route, struct siphash *state); -int route_compare_func(const Route *a, const Route *b); extern const struct hash_ops route_hash_ops; int route_new(Route **ret); @@ -102,7 +100,6 @@ int link_request_route( route_netlink_handler_t netlink_handler, Request **ret); int link_request_static_routes(Link *link, bool only_ipv4); -int route_process_request(Request *req, Link *link, Route *route); int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 535af175a32..8f4297a86ad 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -153,7 +153,7 @@ static int routing_policy_rule_dup(const RoutingPolicyRule *src, RoutingPolicyRu return 0; } -void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state) { +static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state) { assert(rule); siphash24_compress(&rule->family, sizeof(rule->family), state); @@ -194,7 +194,7 @@ void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash } } -int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b) { +static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b) { int r; r = CMP(a->family, b->family); @@ -718,7 +718,7 @@ void link_foreignize_routing_policy_rules(Link *link) { } } -int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule) { +static int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule) { int r; assert(req); @@ -793,10 +793,14 @@ static int link_request_routing_policy_rule(Link *link, RoutingPolicyRule *rule) existing->source = rule->source; log_routing_policy_rule_debug(existing, "Requesting", link, link->manager); - r = link_queue_request(link, REQUEST_TYPE_ROUTING_POLICY_RULE, existing, false, - &link->static_routing_policy_rule_messages, - (request_netlink_handler_t) static_routing_policy_rule_configure_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_ROUTING_POLICY_RULE, + existing, NULL, + routing_policy_rule_hash_func, + routing_policy_rule_compare_func, + routing_policy_rule_process_request, + &link->static_routing_policy_rule_messages, + static_routing_policy_rule_configure_handler, + NULL); if (r <= 0) return r; diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 2d60e595655..b6ce2fa19c4 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -12,7 +12,6 @@ typedef struct Link Link; typedef struct Manager Manager; typedef struct Network Network; -typedef struct Request Request; typedef struct RoutingPolicyRule { Manager *manager; @@ -58,13 +57,9 @@ const char *fr_act_type_full_to_string(int t) _const_; RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule); -void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state); -int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b); - void network_drop_invalid_routing_policy_rules(Network *network); int link_request_static_routing_policy_rules(Link *link); -int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule); int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except); diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index 5128c33719b..148277685e0 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -420,7 +420,6 @@ static int link_configure(Link *link, Request *req) { assert(link); assert(link->manager); - assert(link->manager->rtnl); assert(req); log_link_debug(link, "Setting %s", request_type_to_string(req->type)); @@ -560,7 +559,7 @@ static int link_is_ready_to_set_link(Link *link, Request *req) { return true; } -int link_process_set_link(Request *req, Link *link, void *userdata) { +static int link_process_set_link(Request *req, Link *link, void *userdata) { int r; assert(req); @@ -587,10 +586,12 @@ static int link_request_set_link( int r; assert(link); - assert(netlink_handler); - r = link_queue_request(link, type, NULL, false, - &link->set_link_messages, netlink_handler, &req); + r = link_queue_request_full(link, type, NULL, NULL, NULL, NULL, + link_process_set_link, + &link->set_link_messages, + netlink_handler, + &req); if (r < 0) return log_link_warning_errno(link, r, "Failed to request to set %s: %m", request_type_to_string(type)); @@ -1016,7 +1017,7 @@ static bool link_is_ready_to_activate(Link *link) { return true; } -int link_process_activation(Request *req, Link *link, void *userdata) { +static int link_process_activation(Request *req, Link *link, void *userdata) { bool up = PTR_TO_INT(userdata); int r; @@ -1034,7 +1035,6 @@ int link_process_activation(Request *req, Link *link, void *userdata) { } int link_request_to_activate(Link *link) { - Request *req; bool up; int r; @@ -1065,13 +1065,14 @@ int link_request_to_activate(Link *link) { link->activated = false; - r = link_queue_request(link, REQUEST_TYPE_ACTIVATE_LINK, NULL, false, &link->set_flags_messages, - link_up_or_down_handler, &req); + r = link_queue_request_full(link, REQUEST_TYPE_ACTIVATE_LINK, + INT_TO_PTR(up), NULL, NULL, NULL, + link_process_activation, + &link->set_flags_messages, + link_up_or_down_handler, NULL); if (r < 0) return log_link_error_errno(link, r, "Failed to request to activate link: %m"); - req->userdata = INT_TO_PTR(up); - log_link_debug(link, "Requested to activate link"); return 0; } @@ -1106,7 +1107,7 @@ static bool link_is_ready_to_bring_up_or_down(Link *link, bool up) { return true; } -int link_process_up_or_down(Request *req, Link *link, void *userdata) { +static int link_process_up_or_down(Request *req, Link *link, void *userdata) { bool up = PTR_TO_INT(userdata); int r; @@ -1124,19 +1125,19 @@ int link_process_up_or_down(Request *req, Link *link, void *userdata) { } int link_request_to_bring_up_or_down(Link *link, bool up) { - Request *req; int r; assert(link); - r = link_queue_request(link, REQUEST_TYPE_UP_DOWN, NULL, false, &link->set_flags_messages, - link_up_or_down_handler, &req); + r = link_queue_request_full(link, REQUEST_TYPE_UP_DOWN, + INT_TO_PTR(up), NULL, NULL, NULL, + link_process_up_or_down, + &link->set_flags_messages, + link_up_or_down_handler, NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request to bring link %s: %m", up_or_down(up)); - req->userdata = INT_TO_PTR(up); - log_link_debug(link, "Requested to bring link %s", up_or_down(up)); return 0; } diff --git a/src/network/networkd-setlink.h b/src/network/networkd-setlink.h index 5dce0c7b5f4..7e5ba32ef1c 100644 --- a/src/network/networkd-setlink.h +++ b/src/network/networkd-setlink.h @@ -5,7 +5,6 @@ #include typedef struct Link Link; -typedef struct Request Request; int link_request_to_set_addrgen_mode(Link *link); int link_request_to_set_bond(Link *link); @@ -21,12 +20,8 @@ int link_request_to_set_mtu(Link *link, uint32_t mtu); int link_configure_mtu(Link *link); -int link_process_set_link(Request *req, Link *link, void *userdata); - -int link_process_activation(Request *req, Link *link, void *userdata); int link_request_to_activate(Link *link); -int link_process_up_or_down(Request *req, Link *link, void *userdata); int link_request_to_bring_up_or_down(Link *link, bool up); int link_down_now(Link *link); diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c index 6ec6ed0aff7..6aef268d1f9 100644 --- a/src/network/tc/qdisc.c +++ b/src/network/tc/qdisc.c @@ -151,7 +151,7 @@ static const char *qdisc_get_tca_kind(const QDisc *qdisc) { QDISC_VTABLE(qdisc)->tca_kind : qdisc->tca_kind; } -void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) { +static void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) { assert(qdisc); assert(state); @@ -160,7 +160,7 @@ void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) { siphash24_compress_string(qdisc_get_tca_kind(qdisc), state); } -int qdisc_compare_func(const QDisc *a, const QDisc *b) { +static int qdisc_compare_func(const QDisc *a, const QDisc *b) { int r; assert(a); @@ -359,7 +359,7 @@ static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) { return link_find_tclass(link, qdisc->parent, NULL) >= 0; } -int qdisc_process_request(Request *req, Link *link, QDisc *qdisc) { +static int qdisc_process_request(Request *req, Link *link, QDisc *qdisc) { int r; assert(req); @@ -400,10 +400,14 @@ int link_request_qdisc(Link *link, QDisc *qdisc) { existing->source = qdisc->source; log_qdisc_debug(existing, link, "Requesting"); - r = link_queue_request(link, REQUEST_TYPE_TC_QDISC, existing, false, - &link->tc_messages, - (request_netlink_handler_t) qdisc_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_TC_QDISC, + existing, NULL, + qdisc_hash_func, + qdisc_compare_func, + qdisc_process_request, + &link->tc_messages, + qdisc_handler, + NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request QDisc: %m"); if (r == 0) diff --git a/src/network/tc/qdisc.h b/src/network/tc/qdisc.h index 37ec61cbc70..adaaf260c47 100644 --- a/src/network/tc/qdisc.h +++ b/src/network/tc/qdisc.h @@ -8,7 +8,6 @@ typedef struct Link Link; typedef struct Manager Manager; typedef struct Network Network; -typedef struct Request Request; typedef enum QDiscKind { QDISC_KIND_BFIFO, @@ -77,12 +76,8 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(QDisc, qdisc); QDisc* qdisc_free(QDisc *qdisc); int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret); -void qdisc_hash_func(const QDisc *qdisc, struct siphash *state); -int qdisc_compare_func(const QDisc *a, const QDisc *b); - int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *kind, QDisc **qdisc); -int qdisc_process_request(Request *req, Link *link, QDisc *qdisc); int link_request_qdisc(Link *link, QDisc *qdisc); void network_drop_invalid_qdisc(Network *network); diff --git a/src/network/tc/tclass.c b/src/network/tc/tclass.c index 42011a93e8f..d3b3c19bdf2 100644 --- a/src/network/tc/tclass.c +++ b/src/network/tc/tclass.c @@ -121,7 +121,7 @@ static const char *tclass_get_tca_kind(const TClass *tclass) { TCLASS_VTABLE(tclass)->tca_kind : tclass->tca_kind; } -void tclass_hash_func(const TClass *tclass, struct siphash *state) { +static void tclass_hash_func(const TClass *tclass, struct siphash *state) { assert(tclass); assert(state); @@ -130,7 +130,7 @@ void tclass_hash_func(const TClass *tclass, struct siphash *state) { siphash24_compress_string(tclass_get_tca_kind(tclass), state); } -int tclass_compare_func(const TClass *a, const TClass *b) { +static int tclass_compare_func(const TClass *a, const TClass *b) { int r; assert(a); @@ -318,7 +318,7 @@ static bool tclass_is_ready_to_configure(TClass *tclass, Link *link) { return link_find_qdisc(link, tclass->classid, tclass->parent, tclass_get_tca_kind(tclass), NULL) >= 0; } -int tclass_process_request(Request *req, Link *link, TClass *tclass) { +static int tclass_process_request(Request *req, Link *link, TClass *tclass) { int r; assert(req); @@ -359,10 +359,14 @@ int link_request_tclass(Link *link, TClass *tclass) { existing->source = tclass->source; log_tclass_debug(existing, link, "Requesting"); - r = link_queue_request(link, REQUEST_TYPE_TC_CLASS, existing, false, - &link->tc_messages, - (request_netlink_handler_t) tclass_handler, - NULL); + r = link_queue_request_safe(link, REQUEST_TYPE_TC_CLASS, + existing, NULL, + tclass_hash_func, + tclass_compare_func, + tclass_process_request, + &link->tc_messages, + tclass_handler, + NULL); if (r < 0) return log_link_warning_errno(link, r, "Failed to request TClass: %m"); if (r == 0) diff --git a/src/network/tc/tclass.h b/src/network/tc/tclass.h index f7b724b0020..606bb3fef33 100644 --- a/src/network/tc/tclass.h +++ b/src/network/tc/tclass.h @@ -8,7 +8,6 @@ typedef struct Link Link; typedef struct Manager Manager; typedef struct Network Network; -typedef struct Request Request; typedef enum TClassKind { TCLASS_KIND_DRR, @@ -59,12 +58,8 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(TClass, tclass); TClass* tclass_free(TClass *tclass); int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret); -void tclass_hash_func(const TClass *qdisc, struct siphash *state); -int tclass_compare_func(const TClass *a, const TClass *b); - int link_find_tclass(Link *link, uint32_t classid, TClass **ret); -int tclass_process_request(Request *req, Link *link, TClass *tclass); int link_request_tclass(Link *link, TClass *tclass); void network_drop_invalid_tclass(Network *network);