Merge pull request #22631 from yuwata/network-redesign-request-queue

network: re-design request queue
This commit is contained in:
Luca Boccassi
2022-03-11 10:48:45 +00:00
committed by GitHub
42 changed files with 780 additions and 1228 deletions
+1
View File
@@ -13,6 +13,7 @@
#endif
typedef void (*free_func_t)(void *p);
typedef void* (*mfree_func_t)(void *p);
/* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than
* proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */
+19 -34
View File
@@ -578,14 +578,14 @@ static int independent_netdev_create(NetDev *netdev) {
return 0;
}
static int stacked_netdev_create(NetDev *netdev, Link *link, link_netlink_message_handler_t callback) {
static int stacked_netdev_create(NetDev *netdev, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert(netdev);
assert(netdev->manager);
assert(link);
assert(callback);
assert(req);
r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
if (r < 0)
@@ -595,13 +595,10 @@ static int stacked_netdev_create(NetDev *netdev, Link *link, link_netlink_messag
if (r < 0)
return r;
r = netlink_call_async(netdev->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
r = request_call_netlink_async(netdev->manager->rtnl, m, req);
if (r < 0)
return r;
link_ref(link);
netdev->state = NETDEV_STATE_CREATING;
log_netdev_debug(netdev, "Creating");
return 0;
@@ -632,40 +629,29 @@ static int netdev_is_ready_to_create(NetDev *netdev, Link *link) {
return true;
}
int request_process_stacked_netdev(Request *req) {
NetDev *netdev;
Link *link;
static int stacked_netdev_process_request(Request *req, Link *link, void *userdata) {
NetDev *netdev = ASSERT_PTR(userdata);
int r;
assert(req);
assert(req->type == REQUEST_TYPE_NETDEV_STACKED);
assert(req->netlink_handler);
netdev = ASSERT_PTR(req->netdev);
link = ASSERT_PTR(req->link);
assert(link);
r = netdev_is_ready_to_create(netdev, link);
if (r <= 0)
return r;
r = stacked_netdev_create(netdev, link, req->netlink_handler);
r = stacked_netdev_create(netdev, link, req);
if (r < 0)
return log_netdev_warning_errno(netdev, r, "Failed to create netdev: %m");
return 1;
}
static int link_create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
int r;
assert(m);
assert(link);
assert(link->create_stacked_netdev_messages > 0);
link->create_stacked_netdev_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
@@ -696,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,
link_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);
@@ -708,14 +696,11 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) {
return 0;
}
int request_process_independent_netdev(Request *req) {
NetDev *netdev;
static int independent_netdev_process_request(Request *req, Link *link, void *userdata) {
NetDev *netdev = ASSERT_PTR(userdata);
int r;
assert(req);
assert(req->type == REQUEST_TYPE_NETDEV_INDEPENDENT);
netdev = ASSERT_PTR(req->netdev);
assert(!link);
r = netdev_is_ready_to_create(netdev, NULL);
if (r <= 0)
@@ -747,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;
-3
View File
@@ -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 request_process_independent_netdev(Request *req);
int request_process_stacked_netdev(Request *req);
int link_request_stacked_netdev(Link *link, NetDev *netdev);
const char *netdev_kind_to_string(NetDevKind d) _const_;
+19 -27
View File
@@ -65,19 +65,17 @@ static int address_label_new_static(Network *network, const char *filename, unsi
return 0;
}
static int address_label_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int address_label_configure_handler(
sd_netlink *rtnl,
sd_netlink_message *m,
Request *req,
Link *link,
void *userdata) {
int r;
assert(rtnl);
assert(m);
assert(link);
assert(link->ifname);
assert(link->static_address_label_messages > 0);
link->static_address_label_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
@@ -95,7 +93,7 @@ static int address_label_configure_handler(sd_netlink *rtnl, sd_netlink_message
return 1;
}
static int address_label_configure(AddressLabel *label, Link *link, link_netlink_message_handler_t callback) {
static int address_label_configure(AddressLabel *label, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
@@ -104,7 +102,7 @@ static int address_label_configure(AddressLabel *label, Link *link, link_netlink
assert(link->ifindex > 0);
assert(link->manager);
assert(link->manager->rtnl);
assert(callback);
assert(req);
r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &m, RTM_NEWADDRLABEL,
link->ifindex, AF_INET6);
@@ -123,29 +121,20 @@ static int address_label_configure(AddressLabel *label, Link *link, link_netlink
if (r < 0)
return r;
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
int request_process_address_label(Request *req) {
Link *link;
static int address_label_process_request(Request *req, Link *link, void *userdata) {
AddressLabel *label = ASSERT_PTR(userdata);
int r;
assert(req);
assert(req->label);
assert(req->type == REQUEST_TYPE_ADDRESS_LABEL);
link = ASSERT_PTR(req->link);
assert(link);
if (!link_is_ready_to_configure(link, false))
return 0;
r = address_label_configure(req->label, link, req->netlink_handler);
r = address_label_configure(label, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure address label: %m");
@@ -162,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");
}
-2
View File
@@ -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 request_process_address_label(Request *req);
CONFIG_PARSER_PROTOTYPE(config_parse_address_label);
CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix);
+20 -33
View File
@@ -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);
@@ -1023,9 +1023,6 @@ int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m,
assert(link);
assert(error_msg);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, error_msg);
@@ -1036,11 +1033,7 @@ int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m,
return 1;
}
static int address_configure(
const Address *address,
Link *link,
link_netlink_message_handler_t callback) {
static int address_configure(const Address *address, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
@@ -1050,7 +1043,7 @@ static int address_configure(
assert(link->ifindex > 0);
assert(link->manager);
assert(link->manager->rtnl);
assert(callback);
assert(req);
log_address_debug(address, "Configuring", link);
@@ -1091,12 +1084,7 @@ static int address_configure(
if (r < 0)
return r;
r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
static bool address_is_ready_to_configure(Link *link, const Address *address) {
@@ -1116,21 +1104,17 @@ static bool address_is_ready_to_configure(Link *link, const Address *address) {
return true;
}
int request_process_address(Request *req) {
Address *address;
Link *link;
static int address_process_request(Request *req, Link *link, Address *address) {
int r;
assert(req);
assert(req->type == REQUEST_TYPE_ADDRESS);
address = ASSERT_PTR(req->address);
link = ASSERT_PTR(req->link);
assert(link);
assert(address);
if (!address_is_ready_to_configure(link, address))
return 0;
r = address_configure(address, link, req->netlink_handler);
r = address_configure(address, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure address: %m");
@@ -1143,7 +1127,7 @@ int link_request_address(
Address *address,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
address_netlink_handler_t netlink_handler,
Request **ret) {
Address *acquired, *existing;
@@ -1212,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, 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)
@@ -1224,13 +1212,10 @@ int link_request_address(
return 1;
}
static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
int r;
assert(link);
assert(link->static_address_messages > 0);
link->static_address_messages--;
r = address_configure_handler_internal(rtnl, m, link, "Failed to set static address");
if (r <= 0)
@@ -1300,10 +1285,12 @@ 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_drop(ordered_set_get(address->link->manager->request_queue, &req));
request_detach(address->link->manager, &req);
address_cancel_requesting(address);
}
+7 -3
View File
@@ -18,6 +18,12 @@ typedef struct Manager Manager;
typedef struct Network Network;
typedef struct Request Request;
typedef int (*address_ready_callback_t)(Address *address);
typedef int (*address_netlink_handler_t)(
sd_netlink *rtnl,
sd_netlink_message *m,
Request *req,
Link *link,
Address *address);
struct Address {
Link *link;
@@ -97,17 +103,15 @@ int link_request_address(
Address *address,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
address_netlink_handler_t netlink_handler,
Request **ret);
int link_request_static_address(Link *link, Address *address, bool consume);
int link_request_static_addresses(Link *link);
int request_process_address(Request *req);
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);
+17 -25
View File
@@ -93,16 +93,11 @@ static int bridge_fdb_new_static(
return 0;
}
static int bridge_fdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int bridge_fdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
int r;
assert(m);
assert(link);
assert(link->static_bridge_fdb_messages > 0);
link->static_bridge_fdb_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
@@ -168,14 +163,14 @@ static int bridge_fdb_configure_message(const BridgeFDB *fdb, Link *link, sd_net
return 0;
}
static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, link_netlink_message_handler_t callback) {
static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert(fdb);
assert(link);
assert(link->manager);
assert(callback);
assert(req);
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_BRIDGE);
if (r < 0)
@@ -185,13 +180,7 @@ static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, link_netlink_message
if (r < 0)
return r;
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) {
@@ -219,20 +208,17 @@ static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) {
return true;
}
int request_process_bridge_fdb(Request *req) {
BridgeFDB *fdb;
Link *link;
static int bridge_fdb_process_request(Request *req, Link *link, void *userdata) {
BridgeFDB *fdb = ASSERT_PTR(userdata);
int r;
assert(req);
assert(req->type == REQUEST_TYPE_BRIDGE_FDB);
assert_se(link = req->link);
assert_se(fdb = req->fdb);
assert(link);
if (!bridge_fdb_is_ready_to_configure(fdb, link))
return 0;
r = bridge_fdb_configure(fdb, link, req->netlink_handler);
r = bridge_fdb_configure(fdb, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure bridge FDB: %m");
@@ -249,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");
}
-3
View File
@@ -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 request_process_bridge_fdb(Request *req);
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id);
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_destination);
+17 -24
View File
@@ -81,16 +81,11 @@ static int bridge_mdb_new_static(
return 0;
}
static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
int r;
assert(m);
assert(link);
assert(link->static_bridge_mdb_messages > 0);
link->static_bridge_mdb_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r == -EINVAL && streq_ptr(link->kind, "bridge") && link->master_ifindex <= 0) {
@@ -114,7 +109,7 @@ static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m,
}
/* send a request to the kernel to add an MDB entry */
static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message_handler_t callback) {
static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
struct br_mdb_entry entry;
int r;
@@ -122,7 +117,7 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message
assert(mdb);
assert(link);
assert(link->manager);
assert(callback);
assert(req);
if (DEBUG_LOGGING) {
_cleanup_free_ char *a = NULL;
@@ -164,13 +159,7 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message
if (r < 0)
return r;
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
static bool bridge_mdb_is_ready_to_configure(Link *link) {
@@ -205,19 +194,17 @@ static bool bridge_mdb_is_ready_to_configure(Link *link) {
return true;
}
int request_process_bridge_mdb(Request *req) {
Link *link;
static int bridge_mdb_process_request(Request *req, Link *link, void *userdata) {
BridgeMDB *mdb = ASSERT_PTR(userdata);
int r;
assert(req);
assert(req->mdb);
assert(req->type == REQUEST_TYPE_BRIDGE_MDB);
assert_se(link = req->link);
assert(link);
if (!bridge_mdb_is_ready_to_configure(link))
return 0;
r = bridge_mdb_configure(req->mdb, link, req->netlink_handler);
r = bridge_mdb_configure(mdb, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure bridge MDB: %m");
@@ -240,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");
}
-2
View File
@@ -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 request_process_bridge_mdb(Request *req);
CONFIG_PARSER_PROTOTYPE(config_parse_mdb_group_address);
CONFIG_PARSER_PROTOTYPE(config_parse_mdb_vlan_id);
+5 -17
View File
@@ -288,13 +288,10 @@ static int dhcp_pd_check_ready(Link *link) {
return 1;
}
static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
int r;
assert(link);
assert(link->dhcp_pd_messages > 0);
link->dhcp_pd_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Failed to add prefix route for DHCP delegated subnet prefix");
if (r <= 0)
@@ -344,13 +341,10 @@ static int dhcp_pd_request_route(Link *link, const struct in6_addr *prefix, usec
return 0;
}
static int dhcp_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int dhcp_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
int r;
assert(link);
assert(link->dhcp_pd_messages > 0);
link->dhcp_pd_messages--;
r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCP-PD address");
if (r <= 0)
@@ -658,13 +652,10 @@ void dhcp4_pd_prefix_lost(Link *uplink) {
(void) link_remove(tunnel);
}
static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
int r;
assert(link);
assert(link->dhcp4_messages > 0);
link->dhcp4_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv4 delegated prefix");
if (r <= 0)
@@ -677,13 +668,10 @@ static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message
return 1;
}
static int dhcp6_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int dhcp6_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
int r;
assert(link);
assert(link->dhcp6_messages > 0);
link->dhcp6_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv6 delegated prefix");
if (r <= 0)
@@ -704,7 +692,7 @@ static int dhcp_request_unreachable_route(
NetworkConfigSource source,
const union in_addr_union *server_address,
unsigned *counter,
link_netlink_message_handler_t callback) {
route_netlink_handler_t callback) {
_cleanup_(route_freep) Route *route = NULL;
Route *existing;
+3 -6
View File
@@ -571,13 +571,10 @@ static bool dhcp_server_is_ready_to_configure(Link *link) {
return true;
}
int request_process_dhcp_server(Request *req) {
Link *link;
static int dhcp_server_process_request(Request *req, Link *link, void *userdata) {
int r;
assert(req);
assert(req->type == REQUEST_TYPE_DHCP_SERVER);
assert_se(link = req->link);
assert(link);
if (!dhcp_server_is_ready_to_configure(link))
return 0;
@@ -601,7 +598,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");
-2
View File
@@ -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 request_process_dhcp_server(Request *req);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit);
+7 -21
View File
@@ -177,16 +177,11 @@ static int dhcp4_retry(Link *link) {
return dhcp4_request_address_and_routes(link, false);
}
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
int r;
assert(m);
assert(link);
assert(link->dhcp4_messages > 0);
link->dhcp4_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r == -ENETUNREACH && !link->dhcp4_route_retrying) {
@@ -829,13 +824,10 @@ int dhcp4_lease_lost(Link *link) {
return link_request_static_routes(link, true);
}
static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
int r;
assert(link);
assert(link->dhcp4_messages > 0);
link->dhcp4_messages--;
r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv4 address");
if (r <= 0)
@@ -1597,15 +1589,10 @@ static int dhcp4_configure_duid(Link *link) {
return dhcp_configure_duid(link, link_get_dhcp4_duid(link));
}
int request_process_dhcp4_client(Request *req) {
Link *link;
static int dhcp4_process_request(Request *req, Link *link, void *userdata) {
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_DHCP4_CLIENT);
link = req->link;
assert(link);
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return 0;
@@ -1619,7 +1606,7 @@ int request_process_dhcp4_client(Request *req) {
if (r <= 0)
return r;
r = dhcp4_configure(req->link);
r = dhcp4_configure(link);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure DHCPv4 client: %m");
@@ -1629,7 +1616,6 @@ int request_process_dhcp4_client(Request *req) {
log_link_debug(link, "DHCPv4 client is configured%s.",
r > 0 ? ", acquiring DHCPv4 lease" : "");
return 1;
}
@@ -1644,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");
-2
View File
@@ -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 request_process_dhcp4_client(Request *req);
int link_request_dhcp4_client(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
+4 -13
View File
@@ -136,13 +136,10 @@ int dhcp6_check_ready(Link *link) {
return 0;
}
static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
int r;
assert(link);
assert(link->dhcp6_messages > 0);
link->dhcp6_messages--;
r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv6 address");
if (r <= 0)
@@ -715,15 +712,10 @@ int dhcp6_update_mac(Link *link) {
return 0;
}
int request_process_dhcp6_client(Request *req) {
Link *link;
static int dhcp6_process_request(Request *req, Link *link, void *userdata) {
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_DHCP6_CLIENT);
link = req->link;
assert(link);
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return 0;
@@ -751,7 +743,6 @@ int request_process_dhcp6_client(Request *req) {
log_link_debug(link, "DHCPv6 client is configured%s.",
r > 0 ? ", acquiring DHCPv6 lease" : "");
return 1;
}
@@ -766,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");
-2
View File
@@ -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 request_process_dhcp6_client(Request *req);
int link_request_dhcp6_client(Link *link);
int link_serialize_dhcp6_client(Link *link, FILE *f);
+1 -1
View File
@@ -70,7 +70,7 @@ static int ipv4ll_address_lost(Link *link) {
return address_remove(existing);
}
static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
int r;
assert(link);
+23 -26
View File
@@ -26,13 +26,17 @@ void network_adjust_ipv6_proxy_ndp(Network *network) {
}
}
static int ipv6_proxy_ndp_address_configure_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,
Request *req,
Link *link,
struct in6_addr *address) {
int r;
assert(m);
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)
@@ -48,11 +52,7 @@ static int ipv6_proxy_ndp_address_configure_handler(sd_netlink *rtnl, sd_netlink
}
/* send a request to the kernel to add an IPv6 Proxy entry to the neighbour table */
static int ipv6_proxy_ndp_address_configure(
const struct in6_addr *address,
Link *link,
link_netlink_message_handler_t callback) {
static int ipv6_proxy_ndp_address_configure(const struct in6_addr *address, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
@@ -60,7 +60,7 @@ static int ipv6_proxy_ndp_address_configure(
assert(link);
assert(link->manager);
assert(link->manager->rtnl);
assert(callback);
assert(req);
/* create new netlink message */
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_INET6);
@@ -75,28 +75,20 @@ static int ipv6_proxy_ndp_address_configure(
if (r < 0)
return r;
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
int request_process_ipv6_proxy_ndp_address(Request *req) {
Link *link;
static int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address) {
int r;
assert(req);
assert(req->ipv6_proxy_ndp);
assert(req->type == REQUEST_TYPE_IPV6_PROXY_NDP);
assert_se(link = req->link);
assert(link);
assert(address);
if (!link_is_ready_to_configure(link, false))
return 0;
r = ipv6_proxy_ndp_address_configure(req->ipv6_proxy_ndp, link, req->netlink_handler);
r = ipv6_proxy_ndp_address_configure(address, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure IPv6 proxy NDP address: %m");
@@ -113,9 +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,
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");
}
-2
View File
@@ -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 request_process_ipv6_proxy_ndp_address(Request *req);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address);
+1 -1
View File
@@ -906,7 +906,7 @@ static void link_drop_requests(Link *link) {
ORDERED_SET_FOREACH(req, link->manager->request_queue)
if (req->link == link)
request_drop(req);
request_detach(link->manager, req);
}
static Link *link_drop(Link *link) {
+5 -16
View File
@@ -203,13 +203,10 @@ static int ndisc_check_ready(Link *link) {
return 0;
}
static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
int r;
assert(link);
assert(link->ndisc_messages > 0);
link->ndisc_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Could not set NDisc route");
if (r <= 0)
@@ -254,13 +251,10 @@ static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) {
ndisc_route_handler, NULL);
}
static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
int r;
assert(link);
assert(link->ndisc_messages > 0);
link->ndisc_messages--;
r = address_configure_handler_internal(rtnl, m, link, "Could not set NDisc address");
if (r <= 0)
@@ -1122,14 +1116,10 @@ int ndisc_start(Link *link) {
return 1;
}
int request_process_ndisc(Request *req) {
Link *link;
static int ndisc_process_request(Request *req, Link *link, void *userdata) {
int r;
assert(req);
assert(req->type == REQUEST_TYPE_NDISC);
link = ASSERT_PTR(req->link);
assert(link);
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return 0;
@@ -1148,7 +1138,6 @@ int request_process_ndisc(Request *req) {
log_link_debug(link, "IPv6 Router Discovery is configured%s.",
r > 0 ? " and started" : "");
return 1;
}
@@ -1163,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");
-2
View File
@@ -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 request_process_ndisc(Request *req);
int link_request_ndisc(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client);
+20 -42
View File
@@ -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);
@@ -193,11 +193,7 @@ static int neighbor_configure_message(Neighbor *neighbor, Link *link, sd_netlink
return 0;
}
static int neighbor_configure(
Neighbor *neighbor,
Link *link,
link_netlink_message_handler_t callback) {
static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
@@ -206,7 +202,7 @@ static int neighbor_configure(
assert(link->ifindex > 0);
assert(link->manager);
assert(link->manager->rtnl);
assert(callback);
assert(req);
log_neighbor_debug(neighbor, "Configuring", link);
@@ -219,31 +215,20 @@ static int neighbor_configure(
if (r < 0)
return r;
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
int request_process_neighbor(Request *req) {
Neighbor *neighbor;
Link *link;
static int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) {
int r;
assert(req);
assert(req->type == REQUEST_TYPE_NEIGHBOR);
neighbor = ASSERT_PTR(req->neighbor);
link = ASSERT_PTR(req->link);
assert(link);
assert(neighbor);
if (!link_is_ready_to_configure(link, false))
return 0;
r = neighbor_configure(neighbor, link, req->netlink_handler);
r = neighbor_configure(neighbor, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure neighbor: %m");
@@ -251,17 +236,11 @@ int request_process_neighbor(Request *req) {
return 1;
}
static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Neighbor *neighbor) {
int r;
assert(m);
assert(link);
assert(link->static_neighbor_messages > 0);
link->static_neighbor_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
@@ -279,13 +258,7 @@ static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_messag
return 1;
}
static int link_request_neighbor(
Link *link,
const Neighbor *neighbor,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
static int link_request_neighbor(Link *link, const Neighbor *neighbor) {
Neighbor *existing;
int r;
@@ -309,8 +282,14 @@ static int link_request_neighbor(
existing->source = neighbor->source;
log_neighbor_debug(existing, "Requesting", link);
r = link_queue_request(link, REQUEST_TYPE_NEIGHBOR, existing, false,
message_counter, netlink_handler, ret);
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;
@@ -329,8 +308,7 @@ int link_request_static_neighbors(Link *link) {
link->static_neighbors_configured = false;
HASHMAP_FOREACH(neighbor, link->network->neighbors_by_section) {
r = link_request_neighbor(link, neighbor, &link->static_neighbor_messages,
static_neighbor_configure_handler, NULL);
r = link_request_neighbor(link, neighbor);
if (r < 0)
return log_link_warning_errno(link, r, "Could not request neighbor: %m");
}
-5
View File
@@ -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 request_process_neighbor(Request *req);
int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
+22 -42
View File
@@ -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);
@@ -425,11 +425,7 @@ static int nexthop_remove(NextHop *nexthop) {
return 0;
}
static int nexthop_configure(
NextHop *nexthop,
Link *link,
link_netlink_message_handler_t callback) {
static int nexthop_configure(NextHop *nexthop, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
@@ -439,7 +435,7 @@ static int nexthop_configure(
assert(link->manager);
assert(link->manager->rtnl);
assert(link->ifindex > 0);
assert(callback);
assert(req);
log_nexthop_debug(nexthop, "Configuring", link);
@@ -489,25 +485,14 @@ static int nexthop_configure(
}
}
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, NextHop *nexthop) {
int r;
assert(m);
assert(link);
assert(link->static_nexthop_messages > 0);
link->static_nexthop_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
@@ -561,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. */
}
}
@@ -569,21 +554,17 @@ 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 request_process_nexthop(Request *req) {
NextHop *nexthop;
Link *link;
static int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) {
int r;
assert(req);
assert(req->type == REQUEST_TYPE_NEXTHOP);
nexthop = ASSERT_PTR(req->nexthop);
link = ASSERT_PTR(req->link);
assert(link);
assert(nexthop);
if (!nexthop_is_ready_to_configure(link, nexthop))
return 0;
r = nexthop_configure(nexthop, link, req->netlink_handler);
r = nexthop_configure(nexthop, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure nexthop");
@@ -591,13 +572,7 @@ int request_process_nexthop(Request *req) {
return 1;
}
static int link_request_nexthop(
Link *link,
NextHop *nexthop,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
static int link_request_nexthop(Link *link, NextHop *nexthop) {
NextHop *existing;
int r;
@@ -625,8 +600,14 @@ static int link_request_nexthop(
existing->source = nexthop->source;
log_nexthop_debug(existing, "Requesting", link);
r = link_queue_request(link, REQUEST_TYPE_NEXTHOP, existing, false,
message_counter, netlink_handler, ret);
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;
@@ -647,8 +628,7 @@ int link_request_static_nexthops(Link *link, bool only_ipv4) {
if (only_ipv4 && nh->family != AF_INET)
continue;
r = link_request_nexthop(link, nh, &link->static_nexthop_messages,
static_nexthop_handler, NULL);
r = link_request_nexthop(link, nh);
if (r < 0)
return log_link_warning_errno(link, r, "Could not request nexthop: %m");
}
-5
View File
@@ -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 request_process_nexthop(Request *req);
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);
+219 -370
View File
@@ -1,107 +1,47 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#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 "netdev.h"
#include "netlink-util.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 "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:
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();
}
}
#include "string-table.h"
static Request *request_free(Request *req) {
if (!req)
return NULL;
if (req->link && req->link->manager)
/* To prevent from triggering assertions in hash functions, remove this request before
* freeing object below. */
ordered_set_remove(req->link->manager->request_queue, req);
if (req->consume_object)
request_free_object(req->type, req->object);
link_unref(req->link);
/* To prevent from triggering assertions in the hash and compare functions, remove this request
* before freeing userdata below. */
if (req->manager)
ordered_set_remove(req->manager->request_queue, req);
if (req->free_func)
req->free_func(req->userdata);
if (req->counter)
(*req->counter)--;
link_unref(req->link); /* link may be NULL, but link_unref() can handle it gracefully. */
return mfree(req);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free);
DEFINE_TRIVIAL_REF_UNREF_FUNC(Request, request, request_free);
DEFINE_TRIVIAL_DESTRUCTOR(request_destroy_callback, Request, request_unref);
void request_detach(Manager *manager, Request *req) {
assert(manager);
void request_drop(Request *req) {
if (!req)
return;
if (req->message_counter)
(*req->message_counter)--;
req = ordered_set_remove(manager->request_queue, req);
if (!req)
return;
request_free(req);
req->manager = NULL;
request_unref(req);
}
static void request_hash_func(const Request *req, struct siphash *state) {
@@ -114,61 +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:
trivial_hash_func(req->set_link_operation_ptr, state);
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) {
@@ -191,46 +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:
return trivial_compare_func(a->set_link_operation_ptr, b->set_link_operation_ptr);
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(
@@ -238,217 +100,204 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
Request,
request_hash_func,
request_compare_func,
request_free);
request_unref);
int netdev_queue_request(
NetDev *netdev,
Request **ret) {
_cleanup_(request_freep) Request *req = NULL;
Request *existing;
int r;
assert(netdev);
assert(netdev->manager);
req = new(Request, 1);
if (!req)
return -ENOMEM;
*req = (Request) {
.netdev = netdev_ref(netdev),
.type = REQUEST_TYPE_NETDEV_INDEPENDENT,
.consume_object = true,
};
existing = ordered_set_get(netdev->manager->request_queue, req);
if (existing) {
/* To prevent from removing the existing request. */
req->netdev = netdev_unref(req->netdev);
if (ret)
*ret = existing;
return 0;
}
r = ordered_set_ensure_put(&netdev->manager->request_queue, &request_hash_ops, req);
if (r < 0)
return r;
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,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
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) {
_cleanup_(request_freep) Request *req = NULL;
_cleanup_(request_unrefp) Request *req = NULL;
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,
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,
REQUEST_TYPE_TC_QDISC,
REQUEST_TYPE_TC_CLASS) ||
netlink_handler);
req = new(Request, 1);
if (!req) {
if (consume_object)
request_free_object(type, object);
return -ENOMEM;
}
*req = (Request) {
.link = link_ref(link),
.type = type,
.object = object,
.consume_object = consume_object,
.message_counter = message_counter,
.netlink_handler = netlink_handler,
};
existing = ordered_set_get(link->manager->request_queue, req);
if (existing) {
/* To prevent from removing the existing request. */
req->link = link_unref(req->link);
if (ret)
*ret = existing;
return 0;
}
r = ordered_set_ensure_put(&link->manager->request_queue, &request_hash_ops, req);
if (r < 0)
return r;
if (req->message_counter)
(*req->message_counter)++;
if (ret)
*ret = req;
TAKE_PTR(req);
return 1;
}
int manager_process_requests(sd_event_source *s, void *userdata) {
Manager *manager = userdata;
int r;
assert(manager);
assert(process);
req = new(Request, 1);
if (!req) {
if (free_func)
free_func(userdata);
return -ENOMEM;
}
*req = (Request) {
.n_ref = 1,
.link = link_ref(link), /* link may be NULL, but link_ref() handles it gracefully. */
.type = type,
.userdata = userdata,
.free_func = free_func,
.hash_func = hash_func,
.compare_func = compare_func,
.process = process,
.netlink_handler = netlink_handler,
};
existing = ordered_set_get(manager->request_queue, req);
if (existing) {
if (ret)
*ret = existing;
return 0;
}
r = ordered_set_ensure_put(&manager->request_queue, &request_hash_ops, req);
if (r < 0)
return r;
req->manager = manager;
req->counter = counter;
if (req->counter)
(*req->counter)++;
if (ret)
*ret = req;
TAKE_PTR(req);
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 = ASSERT_PTR(userdata);
int r;
for (;;) {
bool processed = false;
Request *req;
ORDERED_SET_FOREACH(req, manager->request_queue) {
switch (req->type) {
case REQUEST_TYPE_ACTIVATE_LINK:
r = request_process_activation(req);
_unused_ _cleanup_(request_unrefp) Request *ref = request_ref(req);
_cleanup_(link_unrefp) Link *link = link_ref(req->link);
assert(req->process);
r = req->process(req, link, req->userdata);
if (r == 0)
continue;
processed = true;
request_detach(manager, req);
if (r < 0 && link) {
link_enter_failed(link);
/* link_enter_failed() may remove multiple requests,
* hence we need to exit from the loop. */
break;
case REQUEST_TYPE_ADDRESS:
r = request_process_address(req);
break;
case REQUEST_TYPE_ADDRESS_LABEL:
r = request_process_address_label(req);
break;
case REQUEST_TYPE_BRIDGE_FDB:
r = request_process_bridge_fdb(req);
break;
case REQUEST_TYPE_BRIDGE_MDB:
r = request_process_bridge_mdb(req);
break;
case REQUEST_TYPE_DHCP_SERVER:
r = request_process_dhcp_server(req);
break;
case REQUEST_TYPE_DHCP4_CLIENT:
r = request_process_dhcp4_client(req);
break;
case REQUEST_TYPE_DHCP6_CLIENT:
r = request_process_dhcp6_client(req);
break;
case REQUEST_TYPE_IPV6_PROXY_NDP:
r = request_process_ipv6_proxy_ndp_address(req);
break;
case REQUEST_TYPE_NDISC:
r = request_process_ndisc(req);
break;
case REQUEST_TYPE_NEIGHBOR:
r = request_process_neighbor(req);
break;
case REQUEST_TYPE_NETDEV_INDEPENDENT:
r = request_process_independent_netdev(req);
break;
case REQUEST_TYPE_NETDEV_STACKED:
r = request_process_stacked_netdev(req);
break;
case REQUEST_TYPE_NEXTHOP:
r = request_process_nexthop(req);
break;
case REQUEST_TYPE_RADV:
r = request_process_radv(req);
break;
case REQUEST_TYPE_ROUTE:
r = request_process_route(req);
break;
case REQUEST_TYPE_ROUTING_POLICY_RULE:
r = request_process_routing_policy_rule(req);
break;
case REQUEST_TYPE_SET_LINK:
r = request_process_set_link(req);
break;
case REQUEST_TYPE_TC_QDISC:
r = request_process_qdisc(req);
break;
case REQUEST_TYPE_TC_CLASS:
r = request_process_tclass(req);
break;
case REQUEST_TYPE_UP_DOWN:
r = request_process_link_up_or_down(req);
break;
default:
return -EINVAL;
}
if (r < 0) {
if (req->link)
link_enter_failed(req->link);
} else if (r > 0) {
ordered_set_remove(manager->request_queue, req);
request_free(req);
processed = true;
}
}
/* When at least one request is processed, then another request may be ready now. */
if (!processed)
break;
}
return 0;
}
static int request_netlink_handler(sd_netlink *nl, sd_netlink_message *m, Request *req) {
assert(req);
if (req->counter) {
assert(*req->counter > 0);
(*req->counter)--;
req->counter = NULL; /* To prevent double decrement on free. */
}
if (req->link && IN_SET(req->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
if (req->netlink_handler)
return req->netlink_handler(nl, m, req, req->link, req->userdata);
return 0;
}
int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req) {
int r;
assert(nl);
assert(m);
assert(req);
r = netlink_call_async(nl, NULL, m, request_netlink_handler, request_destroy_callback, req);
if (r < 0)
return r;
request_ref(req);
return 0;
}
static const char *const request_type_table[_REQUEST_TYPE_MAX] = {
[REQUEST_TYPE_ACTIVATE_LINK] = "activate link",
[REQUEST_TYPE_ADDRESS] = "address",
[REQUEST_TYPE_ADDRESS_LABEL] = "address label",
[REQUEST_TYPE_BRIDGE_FDB] = "bridge FDB",
[REQUEST_TYPE_BRIDGE_MDB] = "bridge MDB",
[REQUEST_TYPE_DHCP_SERVER] = "DHCP server",
[REQUEST_TYPE_DHCP4_CLIENT] = "DHCPv4 client",
[REQUEST_TYPE_DHCP6_CLIENT] = "DHCPv6 client",
[REQUEST_TYPE_IPV6_PROXY_NDP] = "IPv6 proxy NDP",
[REQUEST_TYPE_NDISC] = "NDisc",
[REQUEST_TYPE_NEIGHBOR] = "neighbor",
[REQUEST_TYPE_NETDEV_INDEPENDENT] = "independent netdev",
[REQUEST_TYPE_NETDEV_STACKED] = "stacked netdev",
[REQUEST_TYPE_NEXTHOP] = "nexthop",
[REQUEST_TYPE_RADV] = "RADV",
[REQUEST_TYPE_ROUTE] = "route",
[REQUEST_TYPE_ROUTING_POLICY_RULE] = "routing policy rule",
[REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE] = "IPv6LL address generation mode",
[REQUEST_TYPE_SET_LINK_BOND] = "bond configurations",
[REQUEST_TYPE_SET_LINK_BRIDGE] = "bridge configurations",
[REQUEST_TYPE_SET_LINK_BRIDGE_VLAN] = "bridge VLAN configurations",
[REQUEST_TYPE_SET_LINK_CAN] = "CAN interface configurations",
[REQUEST_TYPE_SET_LINK_FLAGS] = "link flags",
[REQUEST_TYPE_SET_LINK_GROUP] = "interface group",
[REQUEST_TYPE_SET_LINK_IPOIB] = "IPoIB configurations",
[REQUEST_TYPE_SET_LINK_MAC] = "MAC address",
[REQUEST_TYPE_SET_LINK_MASTER] = "master interface",
[REQUEST_TYPE_SET_LINK_MTU] = "MTU",
[REQUEST_TYPE_TC_QDISC] = "QDisc",
[REQUEST_TYPE_TC_CLASS] = "TClass",
[REQUEST_TYPE_UP_DOWN] = "bring link up or down",
};
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(request_type, RequestType);
+94 -42
View File
@@ -2,20 +2,18 @@
#pragma once
#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 {
REQUEST_TYPE_ACTIVATE_LINK,
@@ -35,7 +33,17 @@ typedef enum RequestType {
REQUEST_TYPE_RADV,
REQUEST_TYPE_ROUTE,
REQUEST_TYPE_ROUTING_POLICY_RULE,
REQUEST_TYPE_SET_LINK,
REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE, /* Setting IPv6LL address generation mode. */
REQUEST_TYPE_SET_LINK_BOND, /* Setting bond configs. */
REQUEST_TYPE_SET_LINK_BRIDGE, /* Setting bridge configs. */
REQUEST_TYPE_SET_LINK_BRIDGE_VLAN, /* Setting bridge VLAN configs. */
REQUEST_TYPE_SET_LINK_CAN, /* Setting CAN interface configs. */
REQUEST_TYPE_SET_LINK_FLAGS, /* Setting IFF_NOARP or friends. */
REQUEST_TYPE_SET_LINK_GROUP, /* Setting interface group. */
REQUEST_TYPE_SET_LINK_IPOIB, /* Setting IPoIB configs. */
REQUEST_TYPE_SET_LINK_MAC, /* Setting MAC address. */
REQUEST_TYPE_SET_LINK_MASTER, /* Setting IFLA_MASTER. */
REQUEST_TYPE_SET_LINK_MTU, /* Setting MTU. */
REQUEST_TYPE_TC_CLASS,
REQUEST_TYPE_TC_QDISC,
REQUEST_TYPE_UP_DOWN,
@@ -43,44 +51,88 @@ typedef enum RequestType {
_REQUEST_TYPE_INVALID = -EINVAL,
} RequestType;
typedef struct Request {
Link *link;
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;
};
void *userdata;
unsigned *message_counter;
link_netlink_message_handler_t netlink_handler;
} Request;
struct Request {
unsigned n_ref;
void request_drop(Request *req);
Manager *manager; /* must be non-NULL */
Link *link; /* can be NULL */
RequestType type;
/* 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;
/* called in netlink handler, the 'counter' is decremented before this is called.
* If this is specified, then the 'process' function must increment the reference of this
* request, and pass this request to the netlink_call_async(), and set the destroy function
* to the slot. */
request_netlink_handler_t netlink_handler;
};
Request *request_ref(Request *req);
Request *request_unref(Request *req);
DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_unref);
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,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
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);
const char* request_type_to_string(RequestType t) _const_;
+3 -8
View File
@@ -582,15 +582,10 @@ static int radv_is_ready_to_configure(Link *link) {
return true;
}
int request_process_radv(Request *req) {
Link *link;
static int radv_process_request(Request *req, Link *link, void *userdata) {
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_RADV);
link = req->link;
assert(link);
r = radv_is_ready_to_configure(link);
if (r <= 0)
@@ -622,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");
-2
View File
@@ -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 request_process_radv(Request *req);
int link_request_radv(Link *link);
const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
+25 -39
View File
@@ -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);
@@ -1141,9 +1141,6 @@ int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li
assert(link);
assert(error_msg);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set route");
@@ -1154,11 +1151,7 @@ int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li
return 1;
}
static int route_configure(
const Route *route,
Link *link,
link_netlink_message_handler_t callback) {
static int route_configure(const Route *route, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
@@ -1168,7 +1161,7 @@ static int route_configure(
assert(link->manager);
assert(link->manager->rtnl);
assert(link->ifindex > 0);
assert(callback);
assert(req);
log_route_debug(route, "Configuring", link, link->manager);
@@ -1250,13 +1243,7 @@ static int route_configure(
return r;
}
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
static int route_is_ready_to_configure(const Route *route, Link *link) {
@@ -1323,19 +1310,13 @@ static int route_is_ready_to_configure(const Route *route, Link *link) {
return true;
}
int request_process_route(Request *req) {
static int route_process_request(Request *req, Link *link, Route *route) {
_cleanup_(converted_routes_freep) ConvertedRoutes *converted = NULL;
Route *route;
Link *link;
int r;
assert(req);
assert(req->link);
assert(req->route);
assert(req->type == REQUEST_TYPE_ROUTE);
link = req->link;
route = req->route;
assert(link);
assert(route);
r = route_is_ready_to_configure(route, link);
if (r < 0)
@@ -1373,7 +1354,7 @@ int request_process_route(Request *req) {
}
}
r = route_configure(route, link, req->netlink_handler);
r = route_configure(route, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure route: %m");
@@ -1395,7 +1376,7 @@ int link_request_route(
Route *route,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
route_netlink_handler_t netlink_handler,
Request **ret) {
Route *existing;
@@ -1442,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, 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;
@@ -1451,13 +1436,10 @@ int link_request_route(
return 1;
}
static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
int r;
assert(link);
assert(link->static_route_messages > 0);
link->static_route_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Could not set route");
if (r <= 0)
@@ -1482,8 +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, 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) {
@@ -1567,10 +1551,12 @@ 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_drop(ordered_set_get(link->manager->request_queue, &req));
request_detach(link->manager, &req);
route_cancel_requesting(route);
}
+10 -6
View File
@@ -14,8 +14,15 @@
typedef struct Manager Manager;
typedef struct Network Network;
typedef struct Request Request;
typedef struct Route Route;
typedef int (*route_netlink_handler_t)(
sd_netlink *rtnl,
sd_netlink_message *m,
Request *req,
Link *link,
Route *route);
typedef struct Route {
struct Route {
Link *link;
Manager *manager;
Network *network;
@@ -66,10 +73,8 @@ typedef struct Route {
usec_t lifetime_usec;
/* Used when kernel does not support RTA_EXPIRES attribute. */
sd_event_source *expire;
} Route;
};
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);
@@ -92,10 +97,9 @@ int link_request_route(
Route *route,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
route_netlink_handler_t netlink_handler,
Request **ret);
int link_request_static_routes(Link *link, bool only_ipv4);
int request_process_route(Request *req);
int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
+28 -53
View File
@@ -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);
@@ -604,11 +604,7 @@ static int routing_policy_rule_remove(RoutingPolicyRule *rule) {
return 0;
}
static int routing_policy_rule_configure(
RoutingPolicyRule *rule,
Link *link,
link_netlink_message_handler_t callback) {
static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
@@ -618,7 +614,7 @@ static int routing_policy_rule_configure(
assert(link->ifindex > 0);
assert(link->manager);
assert(link->manager->rtnl);
assert(callback);
assert(req);
log_routing_policy_rule_debug(rule, "Configuring", link, link->manager);
@@ -630,13 +626,7 @@ static int routing_policy_rule_configure(
if (r < 0)
return r;
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Link *except) {
@@ -728,21 +718,17 @@ void link_foreignize_routing_policy_rules(Link *link) {
}
}
int request_process_routing_policy_rule(Request *req) {
RoutingPolicyRule *rule;
Link *link;
static int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule) {
int r;
assert(req);
assert(req->type == REQUEST_TYPE_ROUTING_POLICY_RULE);
link = ASSERT_PTR(req->link);
rule = ASSERT_PTR(req->rule);
assert(link);
assert(rule);
if (!link_is_ready_to_configure(link, false))
return 0;
r = routing_policy_rule_configure(rule, link, req->netlink_handler);
r = routing_policy_rule_configure(rule, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure routing policy rule: %m");
@@ -750,19 +736,17 @@ int request_process_routing_policy_rule(Request *req) {
return 1;
}
static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int static_routing_policy_rule_configure_handler(
sd_netlink *rtnl,
sd_netlink_message *m,
Request *req,
Link *link,
RoutingPolicyRule *rule) {
int r;
assert(rtnl);
assert(m);
assert(link);
assert(link->ifname);
assert(link->static_routing_policy_rule_messages > 0);
link->static_routing_policy_rule_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
@@ -780,13 +764,7 @@ static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_net
return 1;
}
static int link_request_routing_policy_rule(
Link *link,
RoutingPolicyRule *rule,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
static int link_request_routing_policy_rule(Link *link, RoutingPolicyRule *rule) {
RoutingPolicyRule *existing;
int r;
@@ -815,8 +793,14 @@ static int link_request_routing_policy_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,
message_counter, netlink_handler, ret);
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;
@@ -828,26 +812,17 @@ static int link_request_static_routing_policy_rule(Link *link, RoutingPolicyRule
int r;
if (IN_SET(rule->family, AF_INET, AF_INET6))
return link_request_routing_policy_rule(link, rule,
&link->static_routing_policy_rule_messages,
static_routing_policy_rule_configure_handler,
NULL);
return link_request_routing_policy_rule(link, rule);
rule->family = AF_INET;
r = link_request_routing_policy_rule(link, rule,
&link->static_routing_policy_rule_messages,
static_routing_policy_rule_configure_handler,
NULL);
r = link_request_routing_policy_rule(link, rule);
if (r < 0) {
rule->family = AF_UNSPEC;
return r;
}
rule->family = AF_INET6;
r = link_request_routing_policy_rule(link, rule,
&link->static_routing_policy_rule_messages,
static_routing_policy_rule_configure_handler,
NULL);
r = link_request_routing_policy_rule(link, rule);
rule->family = AF_UNSPEC;
return r;
}
@@ -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 request_process_routing_policy_rule(Request *req);
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);
+171 -261
View File
@@ -14,23 +14,6 @@
#include "networkd-manager.h"
#include "networkd-queue.h"
#include "networkd-setlink.h"
#include "string-table.h"
static const char *const set_link_operation_table[_SET_LINK_OPERATION_MAX] = {
[SET_LINK_ADDRESS_GENERATION_MODE] = "IPv6LL address generation mode",
[SET_LINK_BOND] = "bond configurations",
[SET_LINK_BRIDGE] = "bridge configurations",
[SET_LINK_BRIDGE_VLAN] = "bridge VLAN configurations",
[SET_LINK_CAN] = "CAN interface configurations",
[SET_LINK_FLAGS] = "link flags",
[SET_LINK_GROUP] = "interface group",
[SET_LINK_IPOIB] = "IPoIB configurations",
[SET_LINK_MAC] = "MAC address",
[SET_LINK_MASTER] = "master interface",
[SET_LINK_MTU] = "MTU",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(set_link_operation, SetLinkOperation);
static int get_link_default_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return link_getlink_handler_internal(rtnl, m, link, "Failed to sync link information");
@@ -54,42 +37,36 @@ static int get_link_update_flag_handler(sd_netlink *rtnl, sd_netlink_message *m,
static int set_link_handler_internal(
sd_netlink *rtnl,
sd_netlink_message *m,
Request *req,
Link *link,
SetLinkOperation op,
bool ignore,
link_netlink_message_handler_t get_link_handler) {
int r;
assert(m);
assert(req);
assert(link);
assert(link->set_link_messages > 0);
assert(op >= 0 && op < _SET_LINK_OPERATION_MAX);
link->set_link_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
goto on_error;
r = sd_netlink_message_get_errno(m);
if (r < 0) {
const char *error_msg;
error_msg = strjoina("Failed to set ", set_link_operation_to_string(op), ignore ? ", ignoring" : "");
error_msg = strjoina("Failed to set ", request_type_to_string(req->type), ignore ? ", ignoring" : "");
log_link_message_warning_errno(link, m, r, error_msg);
if (!ignore)
link_enter_failed(link);
goto on_error;
return 0;
}
log_link_debug(link, "%s set.", set_link_operation_to_string(op));
log_link_debug(link, "%s set.", request_type_to_string(req->type));
if (get_link_handler) {
r = link_call_getlink(link, get_link_handler);
if (r < 0) {
link_enter_failed(link);
goto on_error;
return 0;
}
}
@@ -97,27 +74,12 @@ static int set_link_handler_internal(
link_check_ready(link);
return 1;
on_error:
switch (op) {
case SET_LINK_FLAGS:
assert(link->set_flags_messages > 0);
link->set_flags_messages--;
break;
case SET_LINK_MASTER:
link->master_set = true;
break;
default:
break;
}
return 0;
}
static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
int r;
r = set_link_handler_internal(rtnl, m, link, SET_LINK_ADDRESS_GENERATION_MODE, /* ignore = */ true, NULL);
r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
if (r <= 0)
return r;
@@ -130,49 +92,43 @@ static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m
return 0;
}
static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return set_link_handler_internal(rtnl, m, link, SET_LINK_BOND, /* ignore = */ false, NULL);
static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
}
static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return set_link_handler_internal(rtnl, m, link, SET_LINK_BRIDGE, /* ignore = */ true, NULL);
static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
}
static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return set_link_handler_internal(rtnl, m, link, SET_LINK_BRIDGE_VLAN, /* ignore = */ false, NULL);
static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
}
static int link_set_can_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return set_link_handler_internal(rtnl, m, link, SET_LINK_CAN, /* ignore = */ false, NULL);
static int link_set_can_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
}
static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return set_link_handler_internal(rtnl, m, link, SET_LINK_FLAGS, /* ignore = */ false, get_link_update_flag_handler);
static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_default_handler);
}
static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return set_link_handler_internal(rtnl, m, link, SET_LINK_GROUP, /* ignore = */ false, NULL);
static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
}
static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return set_link_handler_internal(rtnl, m, link, SET_LINK_IPOIB, /* ignore = */ true, NULL);
static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
}
static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return set_link_handler_internal(rtnl, m, link, SET_LINK_MAC, /* ignore = */ true, get_link_default_handler);
static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
}
static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
int r;
assert(m);
assert(link);
assert(link->set_link_messages > 0);
link->set_link_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
r = sd_netlink_message_get_errno(m);
if (r == -EBUSY) {
@@ -189,24 +145,22 @@ static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message
return 0;
}
/* set_link_mac_handler() also decrements set_link_messages, so increment the value once. */
link->set_link_messages++;
return link_set_mac_handler(rtnl, m, link);
return link_set_mac_handler(rtnl, m, req, link, userdata);
}
static int link_set_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return set_link_handler_internal(rtnl, m, link, SET_LINK_MASTER, /* ignore = */ false, get_link_master_handler);
static int link_set_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_master_handler);
}
static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
/* Some devices do not support setting master ifindex. Let's ignore error on unsetting master ifindex. */
return set_link_handler_internal(rtnl, m, link, SET_LINK_MASTER, /* ignore = */ true, get_link_master_handler);
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_master_handler);
}
static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
int r;
r = set_link_handler_internal(rtnl, m, link, SET_LINK_MTU, /* ignore = */ true, get_link_default_handler);
r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
if (r <= 0)
return r;
@@ -222,17 +176,17 @@ static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *l
static int link_configure_fill_message(
Link *link,
sd_netlink_message *req,
SetLinkOperation op,
RequestType type,
void *userdata) {
int r;
switch (op) {
case SET_LINK_ADDRESS_GENERATION_MODE:
switch (type) {
case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE:
r = ipv6ll_addrgen_mode_fill_message(req, PTR_TO_UINT8(userdata));
if (r < 0)
return r;
break;
case SET_LINK_BOND:
case REQUEST_TYPE_SET_LINK_BOND:
r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
if (r < 0)
return r;
@@ -266,7 +220,7 @@ static int link_configure_fill_message(
return r;
break;
case SET_LINK_BRIDGE:
case REQUEST_TYPE_SET_LINK_BRIDGE:
r = sd_rtnl_message_link_set_family(req, AF_BRIDGE);
if (r < 0)
return r;
@@ -369,7 +323,7 @@ static int link_configure_fill_message(
if (r < 0)
return r;
break;
case SET_LINK_BRIDGE_VLAN:
case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN:
r = sd_rtnl_message_link_set_family(req, AF_BRIDGE);
if (r < 0)
return r;
@@ -394,12 +348,12 @@ static int link_configure_fill_message(
return r;
break;
case SET_LINK_CAN:
case REQUEST_TYPE_SET_LINK_CAN:
r = can_set_netlink_message(link, req);
if (r < 0)
return r;
break;
case SET_LINK_FLAGS: {
case REQUEST_TYPE_SET_LINK_FLAGS: {
unsigned ifi_change = 0, ifi_flags = 0;
if (link->network->arp >= 0) {
@@ -428,27 +382,27 @@ static int link_configure_fill_message(
break;
}
case SET_LINK_GROUP:
case REQUEST_TYPE_SET_LINK_GROUP:
r = sd_netlink_message_append_u32(req, IFLA_GROUP, (uint32_t) link->network->group);
if (r < 0)
return r;
break;
case SET_LINK_MAC:
case REQUEST_TYPE_SET_LINK_MAC:
r = netlink_message_append_hw_addr(req, IFLA_ADDRESS, &link->requested_hw_addr);
if (r < 0)
return r;
break;
case SET_LINK_IPOIB:
case REQUEST_TYPE_SET_LINK_IPOIB:
r = ipoib_set_netlink_message(link, req);
if (r < 0)
return r;
break;
case SET_LINK_MASTER:
case REQUEST_TYPE_SET_LINK_MASTER:
r = sd_netlink_message_append_u32(req, IFLA_MASTER, PTR_TO_UINT32(userdata));
if (r < 0)
return r;
break;
case SET_LINK_MTU:
case REQUEST_TYPE_SET_LINK_MTU:
r = sd_netlink_message_append_u32(req, IFLA_MTU, PTR_TO_UINT32(userdata));
if (r < 0)
return r;
@@ -460,44 +414,30 @@ static int link_configure_fill_message(
return 0;
}
static int link_configure(
Link *link,
SetLinkOperation op,
void *userdata,
link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
static int link_configure(Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert(link);
assert(link->manager);
assert(link->manager->rtnl);
assert(link->network);
assert(op >= 0 && op < _SET_LINK_OPERATION_MAX);
assert(callback);
assert(req);
log_link_debug(link, "Setting %s", set_link_operation_to_string(op));
log_link_debug(link, "Setting %s", request_type_to_string(req->type));
if (op == SET_LINK_BOND)
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->master_ifindex);
else if (IN_SET(op, SET_LINK_CAN, SET_LINK_IPOIB))
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->ifindex);
if (req->type == REQUEST_TYPE_SET_LINK_BOND)
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->master_ifindex);
else if (IN_SET(req->type, REQUEST_TYPE_SET_LINK_CAN, REQUEST_TYPE_SET_LINK_IPOIB))
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
else
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
if (r < 0)
return log_link_debug_errno(link, r, "Could not allocate netlink message: %m");
return r;
r = link_configure_fill_message(link, req, op, userdata);
r = link_configure_fill_message(link, m, req->type, req->userdata);
if (r < 0)
return log_link_debug_errno(link, r, "Could not create netlink message: %m");
return r;
r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_debug_errno(link, r, "Could not send netlink message: %m");
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
static bool netdev_is_ready(NetDev *netdev) {
@@ -511,66 +451,63 @@ static bool netdev_is_ready(NetDev *netdev) {
return true;
}
static bool link_is_ready_to_call_set_link(Request *req) {
SetLinkOperation op;
Link *link;
static int link_is_ready_to_set_link(Link *link, Request *req) {
int r;
assert(link);
assert(link->manager);
assert(link->network);
assert(req);
assert(req->link);
assert(req->link->manager);
assert(req->link->network);
link = req->link;
op = PTR_TO_INT(req->set_link_operation_ptr);
if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return false;
switch (op) {
case SET_LINK_BOND:
case SET_LINK_BRIDGE:
switch (req->type) {
case REQUEST_TYPE_SET_LINK_BOND:
case REQUEST_TYPE_SET_LINK_BRIDGE:
if (!link->master_set)
return false;
if (link->network->keep_master && link->master_ifindex <= 0)
return false;
break;
case SET_LINK_BRIDGE_VLAN:
case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN:
if (!link->master_set)
return false;
if (link->network->keep_master && link->master_ifindex <= 0 && !streq_ptr(link->kind, "bridge"))
return false;
break;
case SET_LINK_CAN:
case REQUEST_TYPE_SET_LINK_CAN:
/* Do not check link->set_flgas_messages here, as it is ok even if link->flags
* is outdated, and checking the counter causes a deadlock. */
if (FLAGS_SET(link->flags, IFF_UP)) {
/* The CAN interface must be down to configure bitrate, etc... */
r = link_down_now(link);
if (r < 0) {
link_enter_failed(link);
return false;
}
if (r < 0)
return r;
}
break;
case SET_LINK_MAC:
case REQUEST_TYPE_SET_LINK_MAC:
if (req->netlink_handler == link_set_mac_handler) {
/* This is the second attempt to set hardware address. On the first attempt
* req->netlink_handler points to link_set_mac_allow_retry_handler().
* The first attempt failed as the interface was up. */
r = link_down_now(link);
if (r < 0) {
link_enter_failed(link);
return false;
}
if (r < 0)
return r;
}
break;
case SET_LINK_MASTER: {
case REQUEST_TYPE_SET_LINK_MASTER: {
uint32_t m = 0;
Request req_mac = {
.link = link,
.type = REQUEST_TYPE_SET_LINK,
.set_link_operation_ptr = INT_TO_PTR(SET_LINK_MAC),
.type = REQUEST_TYPE_SET_LINK_MAC,
};
if (link->network->batadv) {
@@ -589,10 +526,8 @@ static bool link_is_ready_to_call_set_link(Request *req) {
if (FLAGS_SET(link->flags, IFF_UP)) {
/* link must be down when joining to bond master. */
r = link_down_now(link);
if (r < 0) {
link_enter_failed(link);
return false;
}
if (r < 0)
return r;
}
} else if (link->network->bridge) {
if (ordered_set_contains(link->manager->request_queue, &req_mac))
@@ -609,11 +544,10 @@ static bool link_is_ready_to_call_set_link(Request *req) {
req->userdata = UINT32_TO_PTR(m);
break;
}
case SET_LINK_MTU: {
case REQUEST_TYPE_SET_LINK_MTU: {
Request req_ipoib = {
.link = link,
.type = REQUEST_TYPE_SET_LINK,
.set_link_operation_ptr = INT_TO_PTR(SET_LINK_IPOIB),
.type = REQUEST_TYPE_SET_LINK_IPOIB,
};
return !ordered_set_contains(link->manager->request_queue, &req_ipoib);
@@ -625,53 +559,44 @@ static bool link_is_ready_to_call_set_link(Request *req) {
return true;
}
int request_process_set_link(Request *req) {
SetLinkOperation op;
static int link_process_set_link(Request *req, Link *link, void *userdata) {
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_SET_LINK);
assert(req->netlink_handler);
assert(link);
op = PTR_TO_INT(req->set_link_operation_ptr);
r = link_is_ready_to_set_link(link, req);
if (r <= 0)
return r;
assert(op >= 0 && op < _SET_LINK_OPERATION_MAX);
if (!link_is_ready_to_call_set_link(req))
return 0;
r = link_configure(req->link, op, req->userdata, req->netlink_handler);
r = link_configure(link, req);
if (r < 0)
return log_link_error_errno(req->link, r, "Failed to set %s: %m",
set_link_operation_to_string(op));
if (op == SET_LINK_FLAGS)
req->link->set_flags_messages++;
return log_link_warning_errno(link, r, "Failed to set %s", request_type_to_string(req->type));
return 1;
}
static int link_request_set_link(
Link *link,
SetLinkOperation op,
link_netlink_message_handler_t netlink_handler,
RequestType type,
request_netlink_handler_t netlink_handler,
Request **ret) {
Request *req;
int r;
assert(link);
assert(op >= 0 && op < _SET_LINK_OPERATION_MAX);
assert(netlink_handler);
r = link_queue_request(link, REQUEST_TYPE_SET_LINK, INT_TO_PTR(op), 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_error_errno(link, r, "Failed to request to set %s: %m",
set_link_operation_to_string(op));
return log_link_warning_errno(link, r, "Failed to request to set %s: %m",
request_type_to_string(type));
log_link_debug(link, "Requested to set %s", set_link_operation_to_string(op));
log_link_debug(link, "Requested to set %s", request_type_to_string(type));
if (ret)
*ret = req;
@@ -707,7 +632,9 @@ int link_request_to_set_addrgen_mode(Link *link) {
return 0;
}
r = link_request_set_link(link, SET_LINK_ADDRESS_GENERATION_MODE, link_set_addrgen_mode_handler, &req);
r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE,
link_set_addrgen_mode_handler,
&req);
if (r < 0)
return r;
@@ -732,7 +659,8 @@ int link_request_to_set_bond(Link *link) {
return 0;
}
return link_request_set_link(link, SET_LINK_BOND, link_set_bond_handler, NULL);
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BOND,
link_set_bond_handler, NULL);
}
int link_request_to_set_bridge(Link *link) {
@@ -752,7 +680,9 @@ int link_request_to_set_bridge(Link *link) {
return 0;
}
return link_request_set_link(link, SET_LINK_BRIDGE, link_set_bridge_handler, NULL);
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE,
link_set_bridge_handler,
NULL);
}
int link_request_to_set_bridge_vlan(Link *link) {
@@ -775,7 +705,9 @@ int link_request_to_set_bridge_vlan(Link *link) {
return 0;
}
return link_request_set_link(link, SET_LINK_BRIDGE_VLAN, link_set_bridge_vlan_handler, NULL);
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE_VLAN,
link_set_bridge_vlan_handler,
NULL);
}
int link_request_to_set_can(Link *link) {
@@ -788,7 +720,9 @@ int link_request_to_set_can(Link *link) {
if (!streq_ptr(link->kind, "can"))
return 0;
return link_request_set_link(link, SET_LINK_CAN, link_set_can_handler, NULL);
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_CAN,
link_set_can_handler,
NULL);
}
int link_request_to_set_flags(Link *link) {
@@ -801,7 +735,9 @@ int link_request_to_set_flags(Link *link) {
link->network->promiscuous < 0)
return 0;
return link_request_set_link(link, SET_LINK_FLAGS, link_set_flags_handler, NULL);
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_FLAGS,
link_set_flags_handler,
NULL);
}
int link_request_to_set_group(Link *link) {
@@ -811,7 +747,9 @@ int link_request_to_set_group(Link *link) {
if (link->network->group < 0)
return 0;
return link_request_set_link(link, SET_LINK_GROUP, link_set_group_handler, NULL);
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_GROUP,
link_set_group_handler,
NULL);
}
int link_request_to_set_mac(Link *link, bool allow_retry) {
@@ -832,7 +770,7 @@ int link_request_to_set_mac(Link *link, bool allow_retry) {
if (hw_addr_equal(&link->hw_addr, &link->requested_hw_addr))
return 0;
return link_request_set_link(link, SET_LINK_MAC,
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MAC,
allow_retry ? link_set_mac_allow_retry_handler : link_set_mac_handler,
NULL);
}
@@ -848,7 +786,9 @@ int link_request_to_set_ipoib(Link *link) {
link->network->ipoib_umcast < 0)
return 0;
return link_request_set_link(link, SET_LINK_IPOIB, link_set_ipoib_handler, NULL);
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_IPOIB,
link_set_ipoib_handler,
NULL);
}
int link_request_to_set_master(Link *link) {
@@ -863,15 +803,19 @@ int link_request_to_set_master(Link *link) {
link->master_set = false;
if (link->network->batadv || link->network->bond || link->network->bridge || link->network->vrf)
return link_request_set_link(link, SET_LINK_MASTER, link_set_master_handler, NULL);
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER,
link_set_master_handler,
NULL);
else
return link_request_set_link(link, SET_LINK_MASTER, link_unset_master_handler, NULL);
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER,
link_unset_master_handler,
NULL);
}
int link_request_to_set_mtu(Link *link, uint32_t mtu) {
Request *req;
const char *origin;
uint32_t min_mtu;
Request *req;
int r;
assert(link);
@@ -907,7 +851,9 @@ int link_request_to_set_mtu(Link *link, uint32_t mtu) {
if (link->mtu == mtu)
return 0;
r = link_request_set_link(link, SET_LINK_MTU, link_set_mtu_handler, &req);
r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_MTU,
link_set_mtu_handler,
&req);
if (r < 0)
return r;
@@ -991,14 +937,16 @@ static int link_up_dsa_slave(Link *link) {
return 1;
}
static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool up, bool on_activate) {
static int link_up_or_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
bool on_activate, up;
int r;
assert(m);
assert(req);
assert(link);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
goto on_error;
on_activate = req->type == REQUEST_TYPE_ACTIVATE_LINK;
up = PTR_TO_INT(req->userdata);
r = sd_netlink_message_get_errno(m);
if (r == -ENETDOWN && up && link_up_dsa_slave(link) > 0)
@@ -1012,82 +960,55 @@ static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message
log_link_message_warning_errno(link, m, r, error_msg);
if (on_activate)
goto on_error;
return 0;
}
r = link_call_getlink(link, get_link_update_flag_handler);
if (r < 0) {
link_enter_failed(link);
goto on_error;
return 0;
}
link->set_flags_messages++;
if (on_activate) {
link->activated = true;
link_check_ready(link);
}
return 1;
on_error:
assert(link->set_flags_messages > 0);
link->set_flags_messages--;
return 0;
}
static int link_activate_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ true, /* on_activate = */ true);
}
static int link_activate_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ false, /* on_activate = */ true);
}
static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ true, /* on_activate = */ false);
}
static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ false, /* on_activate = */ false);
}
static const char *up_or_down(bool up) {
return up ? "up" : "down";
}
static int link_up_or_down(Link *link, bool up, link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
static int link_up_or_down(Link *link, bool up, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
assert(link);
assert(link->manager);
assert(link->manager->rtnl);
assert(callback);
assert(req);
log_link_debug(link, "Bringing link %s", up_or_down(up));
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
if (r < 0)
return r;
r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP);
r = sd_rtnl_message_link_set_flags(m, up ? IFF_UP : 0, IFF_UP);
if (r < 0)
return r;
r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
static bool link_is_ready_to_activate(Link *link) {
assert(link);
if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return false;
if (link->set_link_messages > 0)
@@ -1096,23 +1017,17 @@ static bool link_is_ready_to_activate(Link *link) {
return true;
}
int request_process_activation(Request *req) {
Link *link;
bool up;
static int link_process_activation(Request *req, Link *link, void *userdata) {
bool up = PTR_TO_INT(userdata);
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_ACTIVATE_LINK);
assert(req->netlink_handler);
link = req->link;
up = PTR_TO_INT(req->userdata);
assert(link);
if (!link_is_ready_to_activate(link))
return 0;
r = link_up_or_down(link, up, req->netlink_handler);
r = link_up_or_down(link, up, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to activate link: %m");
@@ -1120,7 +1035,6 @@ int request_process_activation(Request *req) {
}
int link_request_to_activate(Link *link) {
Request *req;
bool up;
int r;
@@ -1151,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,
up ? link_activate_up_handler : link_activate_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;
}
@@ -1192,22 +1107,17 @@ static bool link_is_ready_to_bring_up_or_down(Link *link, bool up) {
return true;
}
int request_process_link_up_or_down(Request *req) {
Link *link;
bool up;
static int link_process_up_or_down(Request *req, Link *link, void *userdata) {
bool up = PTR_TO_INT(userdata);
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_UP_DOWN);
link = req->link;
up = PTR_TO_INT(req->userdata);
assert(link);
if (!link_is_ready_to_bring_up_or_down(link, up))
return 0;
r = link_up_or_down(link, up, req->netlink_handler);
r = link_up_or_down(link, up, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to bring link %s: %m", up_or_down(up));
@@ -1215,19 +1125,19 @@ int request_process_link_up_or_down(Request *req) {
}
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,
up ? link_up_handler : link_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;
}
+1 -25
View File
@@ -2,29 +2,9 @@
#pragma once
#include <inttypes.h>
#include <stdbool.h>
typedef struct Link Link;
typedef struct Request Request;
typedef enum SetLinkOperation {
SET_LINK_ADDRESS_GENERATION_MODE, /* Setting IPv6LL address generation mode. */
SET_LINK_BOND, /* Setting bond configs. */
SET_LINK_BRIDGE, /* Setting bridge configs. */
SET_LINK_BRIDGE_VLAN, /* Setting bridge VLAN configs. */
SET_LINK_CAN, /* Setting CAN interface configs. */
SET_LINK_FLAGS, /* Setting IFF_NOARP or friends. */
SET_LINK_GROUP, /* Setting interface group. */
SET_LINK_IPOIB, /* Setting IPoIB configs. */
SET_LINK_MAC, /* Setting MAC address. */
SET_LINK_MASTER, /* Setting IFLA_MASTER. */
SET_LINK_MTU, /* Setting MTU. */
_SET_LINK_OPERATION_MAX,
_SET_LINK_OPERATION_INVALID = -EINVAL,
} SetLinkOperation;
/* SetLinkOperation is casted to int, then stored in void* with INT_TO_PTR(). */
assert_cc(sizeof(SetLinkOperation) <= sizeof(void*));
assert_cc(sizeof(SetLinkOperation) <= sizeof(int));
int link_request_to_set_addrgen_mode(Link *link);
int link_request_to_set_bond(Link *link);
@@ -40,12 +20,8 @@ int link_request_to_set_mtu(Link *link, uint32_t mtu);
int link_configure_mtu(Link *link);
int request_process_set_link(Request *req);
int request_process_activation(Request *req);
int link_request_to_activate(Link *link);
int request_process_link_up_or_down(Request *req);
int link_request_to_bring_up_or_down(Link *link, bool up);
int link_down_now(Link *link);
+19 -23
View File
@@ -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);
@@ -293,15 +293,11 @@ int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *ki
return -ENOENT;
}
static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, QDisc *qdisc) {
int r;
assert(m);
assert(link);
assert(link->tc_messages > 0);
link->tc_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
@@ -319,7 +315,7 @@ static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return 1;
}
static int qdisc_configure(QDisc *qdisc, Link *link) {
static int qdisc_configure(QDisc *qdisc, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
@@ -328,6 +324,7 @@ static int qdisc_configure(QDisc *qdisc, Link *link) {
assert(link->manager);
assert(link->manager->rtnl);
assert(link->ifindex > 0);
assert(req);
log_qdisc_debug(qdisc, link, "Configuring");
@@ -346,12 +343,7 @@ static int qdisc_configure(QDisc *qdisc, Link *link) {
return r;
}
r = netlink_call_async(link->manager->rtnl, NULL, m, qdisc_handler, link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) {
@@ -367,19 +359,17 @@ static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) {
return link_find_tclass(link, qdisc->parent, NULL) >= 0;
}
int request_process_qdisc(Request *req) {
QDisc *qdisc;
Link *link;
static int qdisc_process_request(Request *req, Link *link, QDisc *qdisc) {
int r;
assert(req);
assert_se(link = req->link);
assert_se(qdisc = req->qdisc);
assert(link);
assert(qdisc);
if (!qdisc_is_ready_to_configure(qdisc, link))
return 0;
r = qdisc_configure(qdisc, link);
r = qdisc_configure(qdisc, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure QDisc: %m");
@@ -410,8 +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, NULL, 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)
-5
View File
@@ -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 request_process_qdisc(Request *req);
int link_request_qdisc(Link *link, QDisc *qdisc);
void network_drop_invalid_qdisc(Network *network);
+19 -23
View File
@@ -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);
@@ -255,15 +255,11 @@ static void log_tclass_debug(TClass *tclass, Link *link, const char *str) {
strna(tclass_get_tca_kind(tclass)));
}
static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, TClass *tclass) {
int r;
assert(m);
assert(link);
assert(link->tc_messages > 0);
link->tc_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
@@ -281,7 +277,7 @@ static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return 1;
}
static int tclass_configure(TClass *tclass, Link *link) {
static int tclass_configure(TClass *tclass, Link *link, Request *req) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r;
@@ -290,6 +286,7 @@ static int tclass_configure(TClass *tclass, Link *link) {
assert(link->manager);
assert(link->manager->rtnl);
assert(link->ifindex > 0);
assert(req);
log_tclass_debug(tclass, link, "Configuring");
@@ -308,12 +305,7 @@ static int tclass_configure(TClass *tclass, Link *link) {
return r;
}
r = netlink_call_async(link->manager->rtnl, NULL, m, tclass_handler, link_netlink_destroy_callback, link);
if (r < 0)
return r;
link_ref(link);
return 0;
return request_call_netlink_async(link->manager->rtnl, m, req);
}
static bool tclass_is_ready_to_configure(TClass *tclass, Link *link) {
@@ -326,19 +318,17 @@ 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 request_process_tclass(Request *req) {
TClass *tclass;
Link *link;
static int tclass_process_request(Request *req, Link *link, TClass *tclass) {
int r;
assert(req);
assert_se(link = req->link);
assert_se(tclass = req->tclass);
assert(link);
assert(tclass);
if (!tclass_is_ready_to_configure(tclass, link))
return 0;
r = tclass_configure(tclass, link);
r = tclass_configure(tclass, link, req);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to configure TClass: %m");
@@ -369,8 +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, NULL, 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)
-5
View File
@@ -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 request_process_tclass(Request *req);
int link_request_tclass(Link *link, TClass *tclass);
void network_drop_invalid_tclass(Network *network);