]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: introduce link_request_to_create_stacked_netdev()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 25 May 2021 07:02:38 +0000 (16:02 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 7 Jun 2021 21:33:27 +0000 (06:33 +0900)
This will be used in later commits.

src/network/netdev/netdev.c
src/network/netdev/netdev.h
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-queue.c
src/network/networkd-queue.h

index 81d9260c123968ad3d7e6b9baf6805cd9e62ca1f..a0b6706aad96989b12d9b6feb8fb013e395461c1 100644 (file)
@@ -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;
index 08070abd0a6e0031811341ea64488091665b9300..edc1a77af19cd02d1e458b4227c4e9795c3d2a32 100644 (file)
@@ -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_;
 
index 5a1dba18d3369dcde3a6d5532ffe01d3d4ccd696..97bbe97305c218be580f85ddea6f50a4af2f02da 100644 (file)
@@ -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;
 }
 
index 7da331139316a8e1a8031489c6cad203ba200466..0d60ac682c12c59c1c0c76adc0ca8aed4474655b 100644 (file)
@@ -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;
 
index f05fb2221e902c474ada4e9ca5c32b51a2342867..3a17a06b2c2d72b7eb3e0c254f26522461759d8d 100644 (file)
@@ -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;
index 5d7c85b8a4527a92074a04110f448613cbdea4d7..697fbf3bfd14a70c513ae8c688790e54e7915929 100644 (file)
@@ -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;