diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index df96d8ac9ce..f82aa7ea4cc 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -8,6 +8,7 @@ #include "networkd-link.h" #include "networkd-manager.h" #include "networkd-network.h" +#include "networkd-queue.h" #include "socket-util.h" #include "string-util.h" @@ -25,26 +26,41 @@ void network_adjust_ipv6_proxy_ndp(Network *network) { } } -static int set_ipv6_proxy_ndp_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +static int ipv6_proxy_ndp_address_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; assert(link); + assert(link->static_ipv6_proxy_ndp_messages > 0); + + link->static_ipv6_proxy_ndp_messages--; r = sd_netlink_message_get_errno(m); if (r < 0) log_link_message_warning_errno(link, m, r, "Could not add IPv6 proxy ndp address entry, ignoring"); + if (link->static_ipv6_proxy_ndp_messages == 0) { + log_link_debug(link, "IPv6 proxy NDP addresses set."); + link->static_ipv6_proxy_ndp_configured = true; + link_check_ready(link); + } + return 1; } /* send a request to the kernel to add a IPv6 Proxy entry to the neighbour table */ -static int ipv6_proxy_ndp_address_configure(Link *link, const struct in6_addr *address) { +static int ipv6_proxy_ndp_address_configure( + const struct in6_addr *address, + Link *link, + link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; + assert(address); assert(link); assert(link->manager); - assert(address); + assert(link->manager->rtnl); + assert(callback); /* create new netlink message */ r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, AF_INET6); @@ -59,32 +75,56 @@ static int ipv6_proxy_ndp_address_configure(Link *link, const struct in6_addr *a if (r < 0) return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); - r = netlink_call_async(link->manager->rtnl, NULL, req, set_ipv6_proxy_ndp_address_handler, + r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link); if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); - return 0; + return 1; } -int link_set_ipv6_proxy_ndp_addresses(Link *link) { +int link_request_static_ipv6_proxy_ndp_addresses(Link *link) { struct in6_addr *address; int r; assert(link); assert(link->network); + link->static_ipv6_proxy_ndp_configured = false; + SET_FOREACH(address, link->network->ipv6_proxy_ndp_addresses) { - r = ipv6_proxy_ndp_address_configure(link, address); + r = link_queue_request(link, REQUEST_TYPE_IPV6_PROXY_NDP, address, false, + &link->static_ipv6_proxy_ndp_messages, + ipv6_proxy_ndp_address_configure_handler, NULL); if (r < 0) - return r; + return log_link_warning_errno(link, r, "Failed to request IPv6 proxy NDP address: %m"); + } + + if (link->static_ipv6_proxy_ndp_messages == 0) { + link->static_ipv6_proxy_ndp_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting IPv6 proxy NDP addresses."); + link_set_state(link, LINK_STATE_CONFIGURING); } return 0; } +int request_process_ipv6_proxy_ndp_address(Request *req) { + assert(req); + assert(req->link); + assert(req->ipv6_proxy_ndp); + assert(req->type == REQUEST_TYPE_IPV6_PROXY_NDP); + + if (!link_is_ready_to_configure(req->link, false)) + return 0; + + return ipv6_proxy_ndp_address_configure(req->ipv6_proxy_ndp, req->link, req->netlink_handler); +} + int config_parse_ipv6_proxy_ndp_address( const char *unit, const char *filename, diff --git a/src/network/networkd-ipv6-proxy-ndp.h b/src/network/networkd-ipv6-proxy-ndp.h index 546137fdaca..b35cd56182f 100644 --- a/src/network/networkd-ipv6-proxy-ndp.h +++ b/src/network/networkd-ipv6-proxy-ndp.h @@ -5,9 +5,11 @@ typedef struct Link Link; typedef struct Network Network; +typedef struct Request Request; void network_adjust_ipv6_proxy_ndp(Network *network); -int link_set_ipv6_proxy_ndp_addresses(Link *link); +int link_request_static_ipv6_proxy_ndp_addresses(Link *link); +int request_process_ipv6_proxy_ndp_address(Request *req); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index d7e939c8eae..d117251d484 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -759,6 +759,9 @@ void link_check_ready(Link *link) { if (!link->static_bridge_mdb_configured) return (void) log_link_debug(link, "%s(): static bridge MDB entries are not configured.", __func__); + if (!link->static_ipv6_proxy_ndp_configured) + return (void) log_link_debug(link, "%s(): static IPv6 proxy NDP addresses are not configured.", __func__); + if (!link->static_neighbors_configured) return (void) log_link_debug(link, "%s(): static neighbors are not configured.", __func__); @@ -829,10 +832,6 @@ static int link_set_static_configs(Link *link) { assert(link->network); assert(link->state != _LINK_STATE_INVALID); - r = link_set_ipv6_proxy_ndp_addresses(link); - if (r < 0) - return r; - r = link_request_static_addresses(link); if (r < 0) return r; @@ -849,6 +848,10 @@ static int link_set_static_configs(Link *link) { if (r < 0) return r; + r = link_request_static_ipv6_proxy_ndp_addresses(link); + if (r < 0) + return r; + r = link_request_static_neighbors(link); if (r < 0) return r; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index ab102b1f12d..f5382887ee0 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -83,6 +83,7 @@ typedef struct Link { unsigned static_address_label_messages; unsigned static_bridge_fdb_messages; unsigned static_bridge_mdb_messages; + unsigned static_ipv6_proxy_ndp_messages; unsigned static_neighbor_messages; unsigned static_nexthop_messages; unsigned static_route_messages; @@ -126,6 +127,7 @@ typedef struct Link { bool static_address_labels_configured:1; bool static_bridge_fdb_configured:1; bool static_bridge_mdb_configured:1; + bool static_ipv6_proxy_ndp_configured:1; bool static_neighbors_configured:1; bool static_nexthops_configured:1; bool static_routes_configured:1; diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 77628cf47c8..ccc1b37b402 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -5,6 +5,7 @@ #include "networkd-bridge-fdb.h" #include "networkd-bridge-mdb.h" #include "networkd-dhcp-server.h" +#include "networkd-ipv6-proxy-ndp.h" #include "networkd-manager.h" #include "networkd-neighbor.h" #include "networkd-nexthop.h" @@ -28,6 +29,9 @@ static void request_free_object(RequestType type, void *object) { break; case REQUEST_TYPE_DHCP_SERVER: break; + case REQUEST_TYPE_IPV6_PROXY_NDP: + free(object); + break; case REQUEST_TYPE_NEIGHBOR: neighbor_free(object); break; @@ -148,6 +152,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) { case REQUEST_TYPE_DHCP_SERVER: r = request_process_dhcp_server(req); break; + case REQUEST_TYPE_IPV6_PROXY_NDP: + r = request_process_ipv6_proxy_ndp_address(req); + break; case REQUEST_TYPE_NEIGHBOR: r = request_process_neighbor(req); break; diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 20d153f140e..813ef260b0d 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -25,6 +25,7 @@ typedef enum RequestType { REQUEST_TYPE_BRIDGE_FDB, REQUEST_TYPE_BRIDGE_MDB, REQUEST_TYPE_DHCP_SERVER, + REQUEST_TYPE_IPV6_PROXY_NDP, REQUEST_TYPE_NEIGHBOR, REQUEST_TYPE_NEXTHOP, REQUEST_TYPE_ROUTE, @@ -42,6 +43,7 @@ typedef struct Request { AddressLabel *label; BridgeFDB *fdb; BridgeMDB *mdb; + struct in6_addr *ipv6_proxy_ndp; Neighbor *neighbor; NextHop *nexthop; Route *route;