network: introduce link_request_to_create_stacked_netdev()
This will be used in later commits.
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include "netdevsim.h"
|
||||
#include "netlink-util.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-queue.h"
|
||||
#include "nlmon.h"
|
||||
#include "path-lookup.h"
|
||||
#include "siphash24.h"
|
||||
@@ -654,6 +655,140 @@ int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t callb
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool netdev_is_ready_to_create(NetDev *netdev, Link *link) {
|
||||
Request req;
|
||||
|
||||
assert(netdev);
|
||||
assert(link);
|
||||
|
||||
if (netdev->state != NETDEV_STATE_LOADING)
|
||||
return false;
|
||||
if (!IN_SET(link->state, LINK_STATE_INITIALIZED, 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;
|
||||
|
||||
req = (Request) {
|
||||
.link = link,
|
||||
.type = REQUEST_TYPE_SET_LINK,
|
||||
.set_link_operation = SET_LINK_MTU,
|
||||
};
|
||||
|
||||
if (ordered_set_contains(link->manager->request_queue, &req))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int request_process_create_stacked_netdev(Request *req) {
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(req->link);
|
||||
assert(req->type == REQUEST_TYPE_CREATE_STACKED_NETDEV);
|
||||
assert(req->netdev);
|
||||
assert(req->netlink_handler);
|
||||
|
||||
if (!netdev_is_ready_to_create(req->netdev, req->link))
|
||||
return 0;
|
||||
|
||||
r = netdev_join(req->netdev, req->link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(req->link, r, "Failed to create stacked netdev '%s': %m", req->netdev->ifname);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_create_stacked_netdev_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
|
||||
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 create stacked netdev");
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
assert(link);
|
||||
assert(link->create_stacked_netdev_messages > 0);
|
||||
|
||||
link->create_stacked_netdev_messages--;
|
||||
|
||||
if (link_create_stacked_netdev_handler_internal(rtnl, m, link) <= 0)
|
||||
return 0;
|
||||
|
||||
if (link->create_stacked_netdev_messages == 0) {
|
||||
link->stacked_netdevs_created = true;
|
||||
log_link_debug(link, "Stacked netdevs created.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_create_stacked_netdev_after_configured_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
assert(link);
|
||||
assert(link->create_stacked_netdev_after_configured_messages > 0);
|
||||
|
||||
link->create_stacked_netdev_after_configured_messages--;
|
||||
|
||||
if (link_create_stacked_netdev_handler_internal(rtnl, m, link) <= 0)
|
||||
return 0;
|
||||
|
||||
if (link->create_stacked_netdev_after_configured_messages == 0) {
|
||||
link->stacked_netdevs_after_configured_created = true;
|
||||
log_link_debug(link, "Stacked netdevs created.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_request_to_crate_stacked_netdev(Link *link, NetDev *netdev) {
|
||||
NetDevCreateType create_type;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(netdev);
|
||||
|
||||
create_type = netdev_get_create_type(netdev);
|
||||
if (!IN_SET(create_type, NETDEV_CREATE_STACKED, NETDEV_CREATE_AFTER_CONFIGURED))
|
||||
return -EINVAL;
|
||||
|
||||
if (netdev->state != NETDEV_STATE_LOADING || netdev->ifindex > 0)
|
||||
/* Already created (or removed?) */
|
||||
return 0;
|
||||
|
||||
if (create_type == NETDEV_CREATE_STACKED) {
|
||||
link->stacked_netdevs_created = false;
|
||||
r = link_queue_request(link, REQUEST_TYPE_CREATE_STACKED_NETDEV, netdev, false,
|
||||
&link->create_stacked_netdev_messages,
|
||||
link_create_stacked_netdev_handler,
|
||||
NULL);
|
||||
} else {
|
||||
link->stacked_netdevs_after_configured_created = false;
|
||||
r = link_queue_request(link, REQUEST_TYPE_CREATE_STACKED_NETDEV, netdev, false,
|
||||
&link->create_stacked_netdev_after_configured_messages,
|
||||
link_create_stacked_netdev_after_configured_handler,
|
||||
NULL);
|
||||
}
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to request to create stacked netdev '%s': %m",
|
||||
netdev->ifname);
|
||||
|
||||
log_link_debug(link, "Requested to create stacked netdev '%s'", netdev->ifname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int netdev_load_one(Manager *manager, const char *filename) {
|
||||
_cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL;
|
||||
const char *dropin_dirname;
|
||||
|
||||
@@ -112,6 +112,7 @@ typedef enum NetDevCreateType {
|
||||
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Condition Condition;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef struct NetDev {
|
||||
Manager *manager;
|
||||
@@ -207,6 +208,9 @@ int netdev_get_mac(const char *ifname, struct ether_addr **ret);
|
||||
int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t cb);
|
||||
int netdev_join_after_configured(NetDev *netdev, Link *link, link_netlink_message_handler_t callback);
|
||||
|
||||
int request_process_create_stacked_netdev(Request *req);
|
||||
int link_request_to_crate_stacked_netdev(Link *link, NetDev *netdev);
|
||||
|
||||
const char *netdev_kind_to_string(NetDevKind d) _const_;
|
||||
NetDevKind netdev_kind_from_string(const char *d) _pure_;
|
||||
|
||||
|
||||
@@ -154,6 +154,11 @@ bool link_is_ready_to_configure(Link *link, bool allow_unmanaged) {
|
||||
if (link->set_link_messages > 0)
|
||||
return false;
|
||||
|
||||
/* TODO: enable this check when link_request_to_create_stacked_netdev() is used.
|
||||
if (!link->stacked_netdevs_created)
|
||||
return false;
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@ typedef struct Link {
|
||||
unsigned sr_iov_messages;
|
||||
unsigned enslaving;
|
||||
unsigned set_link_messages;
|
||||
unsigned create_stacked_netdev_messages;
|
||||
unsigned create_stacked_netdev_after_configured_messages;
|
||||
|
||||
Set *addresses;
|
||||
Set *addresses_foreign;
|
||||
@@ -138,6 +140,8 @@ typedef struct Link {
|
||||
bool can_configured:1;
|
||||
bool activated:1;
|
||||
bool entering_to_join_netdev:1;
|
||||
bool stacked_netdevs_created:1;
|
||||
bool stacked_netdevs_after_configured_created:1;
|
||||
|
||||
sd_dhcp_server *dhcp_server;
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ static void request_free_object(RequestType type, void *object) {
|
||||
case REQUEST_TYPE_BRIDGE_MDB:
|
||||
bridge_mdb_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_CREATE_STACKED_NETDEV:
|
||||
break;
|
||||
case REQUEST_TYPE_DHCP_SERVER:
|
||||
break;
|
||||
case REQUEST_TYPE_IPV6_PROXY_NDP:
|
||||
@@ -93,6 +95,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_CREATE_STACKED_NETDEV:
|
||||
/* 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);
|
||||
@@ -145,6 +148,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_CREATE_STACKED_NETDEV:
|
||||
return trivial_compare_func(a->object, b->object);
|
||||
case REQUEST_TYPE_DHCP_SERVER:
|
||||
return 0;
|
||||
@@ -255,6 +259,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
|
||||
case REQUEST_TYPE_BRIDGE_MDB:
|
||||
r = request_process_bridge_mdb(req);
|
||||
break;
|
||||
case REQUEST_TYPE_CREATE_STACKED_NETDEV:
|
||||
r = request_process_create_stacked_netdev(req);
|
||||
break;
|
||||
case REQUEST_TYPE_DHCP_SERVER:
|
||||
r = request_process_dhcp_server(req);
|
||||
break;
|
||||
|
||||
@@ -11,6 +11,7 @@ typedef struct AddressLabel AddressLabel;
|
||||
typedef struct BridgeFDB BridgeFDB;
|
||||
typedef struct BridgeMDB BridgeMDB;
|
||||
typedef struct Neighbor Neighbor;
|
||||
typedef struct NetDev NetDev;
|
||||
typedef struct NextHop NextHop;
|
||||
typedef struct Route Route;
|
||||
typedef struct RoutingPolicyRule RoutingPolicyRule;
|
||||
@@ -25,6 +26,7 @@ typedef enum RequestType {
|
||||
REQUEST_TYPE_ADDRESS_LABEL,
|
||||
REQUEST_TYPE_BRIDGE_FDB,
|
||||
REQUEST_TYPE_BRIDGE_MDB,
|
||||
REQUEST_TYPE_CREATE_STACKED_NETDEV,
|
||||
REQUEST_TYPE_DHCP_SERVER,
|
||||
REQUEST_TYPE_IPV6_PROXY_NDP,
|
||||
REQUEST_TYPE_NEIGHBOR,
|
||||
@@ -53,6 +55,7 @@ typedef struct Request {
|
||||
Route *route;
|
||||
RoutingPolicyRule *rule;
|
||||
SetLinkOperation set_link_operation;
|
||||
NetDev *netdev;
|
||||
void *object;
|
||||
};
|
||||
void *userdata;
|
||||
|
||||
Reference in New Issue
Block a user