mirror of
https://github.com/systemd/systemd.git
synced 2025-02-04 21:47:31 +03:00
network: netdev: use request queue to create independent netdevs
This commit is contained in:
parent
efa7b8adde
commit
5d4a925af0
@ -623,20 +623,21 @@ int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t callb
|
||||
|
||||
static int netdev_is_ready_to_create(NetDev *netdev, Link *link) {
|
||||
assert(netdev);
|
||||
assert(link);
|
||||
|
||||
if (netdev->state != NETDEV_STATE_LOADING)
|
||||
return false;
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
return false;
|
||||
if (link) {
|
||||
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
return false;
|
||||
|
||||
if (netdev_get_create_type(netdev) == NETDEV_CREATE_AFTER_CONFIGURED &&
|
||||
link->state != LINK_STATE_CONFIGURED)
|
||||
return false;
|
||||
if (netdev_get_create_type(netdev) == NETDEV_CREATE_AFTER_CONFIGURED &&
|
||||
link->state != LINK_STATE_CONFIGURED)
|
||||
return false;
|
||||
|
||||
if (link->set_link_messages > 0)
|
||||
return false;
|
||||
if (link->set_link_messages > 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NETDEV_VTABLE(netdev)->is_ready_to_create)
|
||||
return NETDEV_VTABLE(netdev)->is_ready_to_create(netdev, link);
|
||||
@ -751,6 +752,44 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int request_process_independent_netdev(Request *req) {
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(req->type == REQUEST_TYPE_NETDEV_INDEPENDENT);
|
||||
assert(req->netdev);
|
||||
|
||||
r = netdev_is_ready_to_create(req->netdev, NULL);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = netdev_create(req->netdev, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int netdev_request(NetDev *netdev) {
|
||||
int r;
|
||||
|
||||
assert(netdev);
|
||||
|
||||
if (!IN_SET(netdev_get_create_type(netdev), NETDEV_CREATE_MASTER, NETDEV_CREATE_INDEPENDENT) &&
|
||||
!netdev_is_stacked_and_independent(netdev))
|
||||
return 0;
|
||||
|
||||
r = netdev_is_ready_to_create(netdev, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
/* If the netdev has no dependency, then create it now. */
|
||||
return netdev_create(netdev, NULL, NULL);
|
||||
|
||||
/* Otherwise, wait for the dependencies being resolved. */
|
||||
return netdev_queue_request(netdev, NULL);
|
||||
}
|
||||
|
||||
int netdev_load_one(Manager *manager, const char *filename) {
|
||||
_cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL;
|
||||
const char *dropin_dirname;
|
||||
@ -861,20 +900,11 @@ int netdev_load_one(Manager *manager, const char *filename) {
|
||||
|
||||
log_netdev_debug(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
|
||||
|
||||
if (IN_SET(netdev_get_create_type(netdev), NETDEV_CREATE_MASTER, NETDEV_CREATE_INDEPENDENT)) {
|
||||
r = netdev_create(netdev, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (netdev_is_stacked_and_independent(netdev)) {
|
||||
r = netdev_create(netdev, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
netdev = NULL;
|
||||
r = netdev_request(netdev);
|
||||
if (r < 0)
|
||||
return log_netdev_warning_errno(netdev, r, "Failed to request to create: %m");
|
||||
|
||||
TAKE_PTR(netdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -210,6 +210,7 @@ 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 netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t cb);
|
||||
|
||||
int request_process_independent_netdev(Request *req);
|
||||
int request_process_stacked_netdev(Request *req);
|
||||
int link_request_stacked_netdev(Link *link, NetDev *netdev);
|
||||
|
||||
|
@ -657,12 +657,14 @@ static int netdev_tunnel_is_ready_to_create(NetDev *netdev, Link *link) {
|
||||
Tunnel *t;
|
||||
|
||||
assert(netdev);
|
||||
assert(link);
|
||||
|
||||
t = TUNNEL(netdev);
|
||||
|
||||
assert(t);
|
||||
|
||||
if (t->independent)
|
||||
return true;
|
||||
|
||||
return tunnel_get_local_address(t, link, NULL) >= 0;
|
||||
}
|
||||
|
||||
|
@ -427,12 +427,14 @@ static int netdev_vxlan_is_ready_to_create(NetDev *netdev, Link *link) {
|
||||
VxLan *v;
|
||||
|
||||
assert(netdev);
|
||||
assert(link);
|
||||
|
||||
v = VXLAN(netdev);
|
||||
|
||||
assert(v);
|
||||
|
||||
if (v->independent)
|
||||
return true;
|
||||
|
||||
return vxlan_get_local_address(v, link, NULL, NULL) >= 0;
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ static void request_free_object(RequestType type, void *object) {
|
||||
case REQUEST_TYPE_NEIGHBOR:
|
||||
neighbor_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_NETDEV_INDEPENDENT:
|
||||
case REQUEST_TYPE_NETDEV_STACKED:
|
||||
netdev_unref(object);
|
||||
break;
|
||||
@ -101,10 +102,12 @@ void request_drop(Request *req) {
|
||||
|
||||
static void request_hash_func(const Request *req, struct siphash *state) {
|
||||
assert(req);
|
||||
assert(req->link);
|
||||
assert(state);
|
||||
|
||||
siphash24_compress(&req->link->ifindex, sizeof(req->link->ifindex), state);
|
||||
siphash24_compress_boolean(req->link, state);
|
||||
if (req->link)
|
||||
siphash24_compress(&req->link->ifindex, sizeof(req->link->ifindex), state);
|
||||
|
||||
siphash24_compress(&req->type, sizeof(req->type), state);
|
||||
|
||||
switch (req->type) {
|
||||
@ -116,6 +119,7 @@ static void request_hash_func(const Request *req, struct siphash *state) {
|
||||
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. */
|
||||
@ -165,13 +169,17 @@ static int request_compare_func(const struct Request *a, const struct Request *b
|
||||
|
||||
assert(a);
|
||||
assert(b);
|
||||
assert(a->link);
|
||||
assert(b->link);
|
||||
|
||||
r = CMP(a->link->ifindex, b->link->ifindex);
|
||||
r = CMP(!!a->link, !!b->link);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (a->link) {
|
||||
r = CMP(a->link->ifindex, b->link->ifindex);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = CMP(a->type, b->type);
|
||||
if (r != 0)
|
||||
return r;
|
||||
@ -184,6 +192,7 @@ static int request_compare_func(const struct Request *a, const struct Request *b
|
||||
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:
|
||||
@ -222,6 +231,48 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||
request_compare_func,
|
||||
request_free);
|
||||
|
||||
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(
|
||||
Link *link,
|
||||
RequestType type,
|
||||
@ -342,6 +393,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
|
||||
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;
|
||||
@ -369,9 +423,10 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (r < 0)
|
||||
link_enter_failed(req->link);
|
||||
if (r > 0) {
|
||||
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;
|
||||
|
@ -28,6 +28,7 @@ typedef enum RequestType {
|
||||
REQUEST_TYPE_IPV6_PROXY_NDP,
|
||||
REQUEST_TYPE_NDISC,
|
||||
REQUEST_TYPE_NEIGHBOR,
|
||||
REQUEST_TYPE_NETDEV_INDEPENDENT,
|
||||
REQUEST_TYPE_NETDEV_STACKED,
|
||||
REQUEST_TYPE_NEXTHOP,
|
||||
REQUEST_TYPE_RADV,
|
||||
@ -66,6 +67,10 @@ typedef struct Request {
|
||||
|
||||
void request_drop(Request *req);
|
||||
|
||||
int netdev_queue_request(
|
||||
NetDev *netdev,
|
||||
Request **ret);
|
||||
|
||||
int link_queue_request(
|
||||
Link *link,
|
||||
RequestType type,
|
||||
|
Loading…
x
Reference in New Issue
Block a user