chiark / gitweb /
networkd: tie links to rtnl rather than udev
authorTom Gundersen <teg@jklm.no>
Tue, 15 Apr 2014 12:21:44 +0000 (14:21 +0200)
committerTom Gundersen <teg@jklm.no>
Sat, 19 Apr 2014 16:41:58 +0000 (18:41 +0200)
This essentially swaps the roles of rtnl and udev in networkd. After this
change libudev is only used for waiting for udev to initialize devices and
to get udev-specific information needed for some [Match] attributes.

This in particular simplifies the code in containers where udev is not really
useful, but also simplifies things and reduces round-trips in the non-container
case.

src/libsystemd-network/network-internal.c
src/libsystemd-network/network-internal.h
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd-netdev.c
src/network/networkd-network.c
src/network/networkd.c
src/network/networkd.h
src/network/test-network.c
src/udev/net/link-config.c

index 3686267..52e614c 100644 (file)
@@ -79,7 +79,7 @@ bool net_match_config(const struct ether_addr *match_mac,
                       Condition *match_virt,
                       Condition *match_kernel,
                       Condition *match_arch,
-                      const char *dev_mac,
+                      const struct ether_addr *dev_mac,
                       const char *dev_path,
                       const char *dev_parent_driver,
                       const char *dev_driver,
@@ -98,7 +98,7 @@ bool net_match_config(const struct ether_addr *match_mac,
         if (match_arch && !condition_test_architecture(match_arch))
                 return 0;
 
-        if (match_mac && (!dev_mac || memcmp(match_mac, ether_aton(dev_mac), ETH_ALEN)))
+        if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
                 return 0;
 
         if (match_path && (!dev_path || fnmatch(match_path, dev_path, 0)))
index 65cd0d7..836472a 100644 (file)
@@ -37,7 +37,7 @@ bool net_match_config(const struct ether_addr *match_mac,
                       Condition *match_virt,
                       Condition *match_kernel,
                       Condition *match_arch,
-                      const char *dev_mac,
+                      const struct ether_addr *dev_mac,
                       const char *dev_path,
                       const char *dev_parent_driver,
                       const char *dev_driver,
index f179af3..319f290 100644 (file)
@@ -24,7 +24,9 @@
 
 #include "networkd.h"
 #include "libudev-private.h"
+#include "udev-util.h"
 #include "util.h"
+#include "virt.h"
 #include "bus-util.h"
 #include "network-internal.h"
 
 static int ipv4ll_address_update(Link *link, bool deprecate);
 static bool ipv4ll_is_bound(sd_ipv4ll *ll);
 
-int link_new(Manager *manager, struct udev_device *device, Link **ret) {
+static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
         _cleanup_link_free_ Link *link = NULL;
-        const char *ifname;
-        int r;
+        uint16_t type;
+        char *ifname;
+        int r, ifindex;
 
         assert(manager);
         assert(manager->links);
-        assert(device);
+        assert(message);
         assert(ret);
 
+        r = sd_rtnl_message_get_type(message, &type);
+        if (r < 0)
+                return r;
+        else if (type != RTM_NEWLINK)
+                return -EINVAL;
+
+        r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
+        if (r < 0)
+                return r;
+        else if (ifindex <= 0)
+                return -EINVAL;
+
+        r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &ifname);
+        if (r < 0)
+                return r;
+
         link = new0(Link, 1);
         if (!link)
                 return -ENOMEM;
 
         link->manager = manager;
-        link->state = _LINK_STATE_INVALID;
-
-        link->ifindex = udev_device_get_ifindex(device);
-        if (link->ifindex <= 0)
-                return -EINVAL;
+        link->state = LINK_STATE_INITIALIZING;
+        link->ifindex = ifindex;
+        link->ifname = strdup(ifname);
+        if (!link->ifname)
+                return -ENOMEM;
 
         r = asprintf(&link->state_file, "/run/systemd/network/links/%"PRIu64,
                      link->ifindex);
         if (r < 0)
                 return -ENOMEM;
 
-        ifname = udev_device_get_sysname(device);
-        link->ifname = strdup(ifname);
-
         r = hashmap_put(manager->links, &link->ifindex, link);
         if (r < 0)
                 return r;
 
-        link->udev_device = udev_device_ref(device);
-
         *ret = link;
         link = NULL;
 
@@ -1036,7 +1050,6 @@ static int link_update_flags(Link *link, unsigned flags) {
         int r;
 
         assert(link);
-        assert(link->network);
 
         if (link->state == LINK_STATE_FAILED)
                 return 0;
@@ -1060,13 +1073,12 @@ static int link_update_flags(Link *link, unsigned flags) {
 
         link->flags = flags;
 
-        if (flags_added & generic_flags)
-                log_debug_link(link, "link flags gained: %#.8x",
-                               flags_added & generic_flags);
-
-        if (flags_removed & generic_flags)
-                log_debug_link(link, "link flags lost: %#.8x",
-                                flags_removed & generic_flags);
+        if (!link->network)
+                /* not currently managing this link
+                   we track state changes, but don't log them
+                   they will be logged if and when a network is
+                   applied */
+                return 0;
 
         if (flags_added & IFF_UP)
                 log_info_link(link, "link is up");
@@ -1083,6 +1095,14 @@ static int link_update_flags(Link *link, unsigned flags) {
         else if (flags_removed & IFF_RUNNING)
                 log_debug_link(link, "link is not running");
 
+        if (flags_added & generic_flags)
+                log_debug_link(link, "ignored link flags gained: %#.8x",
+                               flags_added & generic_flags);
+
+        if (flags_removed & generic_flags)
+                log_debug_link(link, "ignored link flags lost: %#.8x",
+                                flags_removed & generic_flags);
+
         if (carrier_gained) {
                 log_info_link(link, "gained carrier");
 
@@ -1180,10 +1200,12 @@ static int link_enslaved(Link *link) {
         assert(link->state == LINK_STATE_ENSLAVING);
         assert(link->network);
 
-        r = link_up(link);
-        if (r < 0) {
-                link_enter_failed(link);
-                return r;
+        if (!(link->flags & IFF_UP)) {
+                r = link_up(link);
+                if (r < 0) {
+                        link_enter_failed(link);
+                        return r;
+                }
         }
 
         if (!link->network->dhcp && !link->network->ipv4ll)
@@ -1231,7 +1253,7 @@ static int link_enter_enslave(Link *link) {
 
         assert(link);
         assert(link->network);
-        assert(link->state == _LINK_STATE_INVALID);
+        assert(link->state == LINK_STATE_INITIALIZING);
 
         link->state = LINK_STATE_ENSLAVING;
 
@@ -1323,95 +1345,11 @@ static int link_enter_enslave(Link *link) {
         return 0;
 }
 
-static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
-                                void *userdata) {
-        Link *link = userdata;
-        int r;
-
-        assert(link);
-        assert(link->ifname);
-
-        if (link->state == LINK_STATE_FAILED)
-                return 1;
-
-        r = sd_rtnl_message_get_errno(m);
-        if (r < 0) {
-                log_struct_link(LOG_ERR, link,
-                                "MESSAGE=%s: could not get state: %s",
-                                link->ifname, strerror(-r),
-                                "ERRNO=%d", -r,
-                                NULL);
-                link_enter_failed(link);
-                return 1;
-        }
-
-        link_update(link, m);
-
-        return 1;
-}
-
-static int link_getlink(Link *link) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
-        int r;
-
-        assert(link);
-        assert(link->manager);
-        assert(link->manager->rtnl);
-
-        log_debug_link(link, "requesting link status");
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
-                                     RTM_GETLINK, link->ifindex);
-        if (r < 0) {
-                log_error_link(link, "Could not allocate RTM_GETLINK message");
-                return r;
-        }
-
-        r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
-                               link, 0, NULL);
-        if (r < 0) {
-                log_error_link(link,
-                               "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        return 0;
-}
-
 static int link_configure(Link *link) {
         int r;
 
         assert(link);
-        assert(link->state == _LINK_STATE_INVALID);
-
-        r = link_getlink(link);
-        if (r < 0)
-                return r;
-
-        return link_enter_enslave(link);
-}
-
-int link_add(Manager *m, struct udev_device *device, Link **ret) {
-        Link *link = NULL;
-        Network *network;
-        int r;
-
-        assert(m);
-        assert(device);
-
-        r = link_new(m, device, &link);
-        if (r < 0)
-                return r;
-
-        *ret = link;
-
-        r = network_get(m, device, &network);
-        if (r < 0)
-                return r == -ENOENT ? 0 : r;
-
-        r = network_apply(m, network, link);
-        if (r < 0)
-                return r;
+        assert(link->state == LINK_STATE_INITIALIZING);
 
         if (link->network->ipv4ll) {
                 uint8_t seed[8];
@@ -1419,11 +1357,13 @@ int link_add(Manager *m, struct udev_device *device, Link **ret) {
                 if (r < 0)
                         return r;
 
-                r = net_get_unique_predictable_data(link->udev_device, seed);
-                if (r >= 0) {
-                        r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
-                        if (r < 0)
-                                return r;
+                if (link->udev_device) {
+                        r = net_get_unique_predictable_data(link->udev_device, seed);
+                        if (r >= 0) {
+                                r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
+                                if (r < 0)
+                                        return r;
+                        }
                 }
 
                 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
@@ -1463,10 +1403,84 @@ int link_add(Manager *m, struct udev_device *device, Link **ret) {
                 }
         }
 
+        return link_enter_enslave(link);
+}
+
+int link_initialized(Link *link, struct udev_device *device) {
+        Network *network;
+        unsigned flags;
+        int r;
+
+        assert(link);
+        assert(link->ifname);
+        assert(link->manager);
+
+        if (link->state != LINK_STATE_INITIALIZING)
+                return 0;
+
+        if (device)
+                link->udev_device = udev_device_ref(device);
+
+        log_debug_link(link, "link initialized");
+
+        r = network_get(link->manager, device, link->ifname, &link->mac, &network);
+        if (r < 0)
+                return r == -ENOENT ? 0 : r;
+
+        r = network_apply(link->manager, network, link);
+        if (r < 0)
+                return r;
+
         r = link_configure(link);
         if (r < 0)
                 return r;
 
+        /* re-trigger all state updates */
+        flags = link->flags;
+        link->flags = 0;
+        r = link_update_flags(link, flags);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
+        Link *link;
+        _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+        char ifindex_str[2 + DECIMAL_STR_MAX(int)];
+        int r;
+
+        assert(m);
+        assert(message);
+        assert(ret);
+
+        r = link_new(m, message, ret);
+        if (r < 0)
+                return r;
+
+        link = *ret;
+
+        log_info_link(link, "link added");
+
+        if (detect_container(NULL) <= 0) {
+                /* not in a container, udev will be around */
+                sprintf(ifindex_str, "n%"PRIu64, link->ifindex);
+                device = udev_device_new_from_device_id(m->udev, ifindex_str);
+                if (!device) {
+                        log_warning_link(link, "could not find udev device");
+                        return -errno;
+                }
+
+                if (udev_device_get_is_initialized(device) <= 0)
+                        /* not yet ready */
+                        return 0;
+        }
+
+        r = link_initialized(link, device);
+        if (r < 0)
+                return r;
+
         return 0;
 }
 
@@ -1476,14 +1490,12 @@ int link_update(Link *link, sd_rtnl_message *m) {
         int r;
 
         assert(link);
-        assert(link->network);
         assert(m);
 
         if (link->state == LINK_STATE_FAILED)
                 return 0;
 
-        if (link->network->dhcp && link->network->dhcp_mtu &&
-            !link->original_mtu) {
+        if (!link->original_mtu) {
                 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
                 if (r >= 0)
                         log_debug_link(link, "saved original MTU: %"
@@ -1591,6 +1603,7 @@ finish:
 }
 
 static const char* const link_state_table[_LINK_STATE_MAX] = {
+        [LINK_STATE_INITIALIZING] = "configuring",
         [LINK_STATE_ENSLAVING] = "configuring",
         [LINK_STATE_SETTING_ADDRESSES] = "configuring",
         [LINK_STATE_SETTING_ROUTES] = "configuring",
index d903d0d..4c1987d 100644 (file)
@@ -29,6 +29,8 @@
 #include "mkdir.h"
 #include "virt.h"
 
+#include "sd-rtnl.h"
+
 const char* const network_dirs[] = {
         "/etc/systemd/network",
         "/run/systemd/network",
@@ -96,18 +98,14 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 return r;
 
-        m->udev = udev_new();
-        if (!m->udev)
-                return -ENOMEM;
-
         /* udev does not initialize devices inside containers,
          * so we rely on them being already initialized before
          * entering the container */
-        if (detect_container(NULL) > 0) {
-                m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "kernel");
-                if (!m->udev_monitor)
+        if (detect_container(NULL) <= 0) {
+                m->udev = udev_new();
+                if (!m->udev)
                         return -ENOMEM;
-        } else {
+
                 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
                 if (!m->udev_monitor)
                         return -ENOMEM;
@@ -182,15 +180,30 @@ bool manager_should_reload(Manager *m) {
         return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
 }
 
-static int manager_process_link(Manager *m, struct udev_device *device) {
+static int manager_udev_process_link(Manager *m, struct udev_device *device) {
         Link *link = NULL;
         int r;
 
         assert(m);
         assert(device);
 
-        link_get(m, udev_device_get_ifindex(device), &link);
+        if (!streq_ptr(udev_device_get_action(device), "add"))
+                return 0;
+
+        r = link_get(m, udev_device_get_ifindex(device), &link);
+        if (r < 0)
+                return r;
+
+        if (!link)
+                return 0;
+
+        r = link_initialized(link, device);
+        if (r < 0)
+                return r;
 
+        return 0;
+}
+/*
         if (streq_ptr(udev_device_get_action(device), "remove")) {
                 log_debug("%s: link removed", udev_device_get_sysname(device));
 
@@ -215,45 +228,87 @@ static int manager_process_link(Manager *m, struct udev_device *device) {
 
         return 0;
 }
+*/
+static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
+        Manager *m = userdata;
+        Link *link = NULL;
+        char *name;
+        int r, ifindex;
 
-int manager_udev_enumerate_links(Manager *m) {
-        _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
-        struct udev_list_entry *item = NULL, *first = NULL;
-        int r;
-
+        assert(rtnl);
+        assert(message);
         assert(m);
 
-        e = udev_enumerate_new(m->udev);
-        if (!e)
-                return -ENOMEM;
+        r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
+        if (r < 0 || ifindex <= 0) {
+                log_warning("rtnl: received link message without valid ifindex");
+                return 0;
+        }
+
+        link_get(m, ifindex, &link);
+        if (!link) {
+                /* link is new, so add it */
+                r = link_add(m, message, &link);
+                if (r < 0) {
+                        log_debug("could not add new link");
+                        return 0;
+                }
+        }
 
-        r = udev_enumerate_add_match_subsystem(e, "net");
+        r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
         if (r < 0)
-                return r;
+                log_warning("rtnl: received link message without valid ifname");
+        else {
+                NetDev *netdev;
 
-        /* udev does not initialize devices inside containers,
-         * so we rely on them being already initialized before
-         * entering the container */
-        if (detect_container(NULL) <= 0) {
-                r = udev_enumerate_add_match_is_initialized(e);
-                if (r < 0)
-                        return r;
+                r = netdev_get(m, name, &netdev);
+                if (r >= 0) {
+                        r = netdev_set_ifindex(netdev, message);
+                        if (r < 0) {
+                                log_debug("could not set ifindex on netdev");
+                                return 0;
+                        }
+                }
         }
 
-        r = udev_enumerate_scan_devices(e);
+        r = link_update(link, message);
+        if (r < 0)
+                return 0;
+
+        return 1;
+}
+
+int manager_rtnl_enumerate_links(Manager *m) {
+        _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
+        sd_rtnl_message *link;
+        int r, k;
+
+        assert(m);
+        assert(m->rtnl);
+
+        r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_message_request_dump(req, true);
         if (r < 0)
                 return r;
 
-        first = udev_enumerate_get_list_entry(e);
-        udev_list_entry_foreach(item, first) {
-                _cleanup_udev_device_unref_ struct udev_device *d = NULL;
-                int k;
+        r = sd_rtnl_call(m->rtnl, req, 0, &reply);
+        if (r < 0)
+                return r;
 
-                d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
-                if (!d)
-                        return -ENOMEM;
+        for (link = reply; link; link = sd_rtnl_message_next(link)) {
+                uint16_t type;
+
+                k = sd_rtnl_message_get_type(link, &type);
+                if (k < 0)
+                        return k;
+
+                if (type != RTM_NEWLINK)
+                        continue;
 
-                k = manager_process_link(m, d);
+                k = manager_rtnl_process_link(m->rtnl, link, m);
                 if (k < 0)
                         r = k;
         }
@@ -270,13 +325,18 @@ static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t
         if (!device)
                 return -ENOMEM;
 
-        manager_process_link(m, device);
+        manager_udev_process_link(m, device);
         return 0;
 }
 
 int manager_udev_listen(Manager *m) {
         int r;
 
+        if (detect_container(NULL) > 0)
+                return 0;
+
+        assert(m->udev_monitor);
+
         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
         if (r < 0) {
                 log_error("Could not add udev monitor filter: %s", strerror(-r));
@@ -300,56 +360,6 @@ int manager_udev_listen(Manager *m) {
         return 0;
 }
 
-static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
-        Manager *m = userdata;
-        Link *link;
-        char *name;
-        int r, ifindex;
-
-        assert(rtnl);
-        assert(message);
-        assert(m);
-
-        r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
-        if (r < 0 || ifindex <= 0) {
-                log_warning("received RTM_NEWLINK message without valid ifindex");
-                return 0;
-        }
-
-        r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
-        if (r < 0)
-                log_warning("received RTM_NEWLINK message without valid ifname");
-        else {
-                NetDev *netdev;
-
-                r = netdev_get(m, name, &netdev);
-                if (r >= 0) {
-                        netdev_set_ifindex(netdev, message);
-                        r = sd_rtnl_message_rewind(message);
-                        if (r < 0) {
-                                log_debug("could not rewind rtnl message");
-                                return 0;
-                        }
-                }
-        }
-
-        r = link_get(m, ifindex, &link);
-        if (r < 0) {
-                log_debug("received RTM_NEWLINK message for untracked ifindex %d", ifindex);
-                return 0;
-        }
-
-        /* only track the status of links we want to manage */
-        if (link->network) {
-                r = link_update(link, message);
-                if (r < 0)
-                        return 0;
-        } else
-                log_debug("%s: received RTM_NEWLINK message for unmanaged link", link->ifname);
-
-        return 1;
-}
-
 int manager_rtnl_listen(Manager *m) {
         int r;
 
index 92548d9..b7fc48d 100644 (file)
@@ -161,67 +161,6 @@ static int netdev_enter_ready(NetDev *netdev) {
 
         return 0;
 }
-
-static int netdev_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
-                                void *userdata) {
-        NetDev *netdev = userdata;
-        int r;
-
-        assert(netdev);
-
-        if (netdev->state == NETDEV_STATE_FAILED)
-                return 1;
-
-        r = sd_rtnl_message_get_errno(m);
-        if (r < 0) {
-                log_struct_netdev(LOG_ERR, netdev,
-                                "MESSAGE=%s: could not get link: %s",
-                                netdev->name, strerror(-r),
-                                "ERRNO=%d", -r,
-                                NULL);
-                return 1;
-        }
-
-        netdev_set_ifindex(netdev, m);
-
-        return 1;
-}
-
-static int netdev_getlink(NetDev *netdev) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
-        int r;
-
-        assert(netdev->manager);
-        assert(netdev->manager->rtnl);
-        assert(netdev->name);
-
-        log_debug_netdev(netdev, "requesting netdev status");
-
-        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
-                                     RTM_GETLINK, 0);
-        if (r < 0) {
-                log_error_netdev(netdev, "Could not allocate RTM_GETLINK message");
-                return r;
-        }
-
-        r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->name);
-        if (r < 0) {
-                log_error_netdev(netdev, "Colud not append ifname to message: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_call_async(netdev->manager->rtnl, req, netdev_getlink_handler,
-                               netdev, 0, NULL);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                               "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        return 0;
-}
-
 static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
         NetDev *netdev = userdata;
         int r;
@@ -230,9 +169,8 @@ static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userda
 
         r = sd_rtnl_message_get_errno(m);
         if (r == -EEXIST)
-                r = netdev_getlink(netdev);
-
-        if (r < 0) {
+                log_debug_netdev(netdev, "netdev exists, using existing");
+        else if (r < 0) {
                 log_warning_netdev(netdev, "netdev failed: %s", strerror(-r));
                 netdev_enter_failed(netdev);
 
@@ -410,6 +348,12 @@ int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
                 return r;
         }
 
+        r = sd_rtnl_message_exit_container(message);
+        if (r < 0) {
+                log_error_netdev(netdev, "Could not exit container");
+                return r;
+        }
+
         kind = netdev_kind_to_string(netdev->kind);
         if (!kind) {
                 log_error_netdev(netdev, "Could not get kind");
index bdf71e8..048017e 100644 (file)
@@ -184,28 +184,28 @@ void network_free(Network *network) {
         free(network);
 }
 
-int network_get(Manager *manager, struct udev_device *device, Network **ret) {
+int network_get(Manager *manager, struct udev_device *device,
+                const char *ifname, const struct ether_addr *address,
+                Network **ret) {
         Network *network;
 
         assert(manager);
-        assert(device);
         assert(ret);
 
         LIST_FOREACH(networks, network, manager->networks) {
                 if (net_match_config(network->match_mac, network->match_path,
-                                        network->match_driver, network->match_type,
-                                        network->match_name, network->match_host,
-                                        network->match_virt, network->match_kernel,
-                                        network->match_arch,
-                                        udev_device_get_sysattr_value(device, "address"),
-                                        udev_device_get_property_value(device, "ID_PATH"),
-                                        udev_device_get_driver(udev_device_get_parent(device)),
-                                        udev_device_get_property_value(device, "ID_NET_DRIVER"),
-                                        udev_device_get_devtype(device),
-                                        udev_device_get_sysname(device))) {
-                        log_debug("%s: found matching network '%s'",
-                                        udev_device_get_sysname(device),
-                                        network->filename);
+                                     network->match_driver, network->match_type,
+                                     network->match_name, network->match_host,
+                                     network->match_virt, network->match_kernel,
+                                     network->match_arch,
+                                     address,
+                                     udev_device_get_property_value(device, "ID_PATH"),
+                                     udev_device_get_driver(udev_device_get_parent(device)),
+                                     udev_device_get_property_value(device, "ID_NET_DRIVER"),
+                                     udev_device_get_devtype(device),
+                                     ifname)) {
+                        log_debug("%s: found matching network '%s'", ifname,
+                                  network->filename);
                         *ret = network;
                         return 0;
                 }
index f0e6ad5..6b3bf12 100644 (file)
@@ -87,7 +87,7 @@ int main(int argc, char *argv[]) {
                 goto out;
         }
 
-        r = manager_udev_enumerate_links(m);
+        r = manager_rtnl_enumerate_links(m);
         if (r < 0) {
                 log_error("Could not enumerate links: %s", strerror(-r));
                 goto out;
index 36902e3..4a62fb8 100644 (file)
@@ -185,6 +185,7 @@ struct Route {
 };
 
 typedef enum LinkState {
+        LINK_STATE_INITIALIZING,
         LINK_STATE_ENSLAVING,
         LINK_STATE_SETTING_ADDRESSES,
         LINK_STATE_SETTING_ROUTES,
@@ -246,10 +247,10 @@ void manager_free(Manager *m);
 int manager_load_config(Manager *m);
 bool manager_should_reload(Manager *m);
 
-int manager_udev_enumerate_links(Manager *m);
-int manager_udev_listen(Manager *m);
+int manager_rtnl_enumerate_links(Manager *m);
 
 int manager_rtnl_listen(Manager *m);
+int manager_udev_listen(Manager *m);
 int manager_bus_listen(Manager *m);
 
 int manager_update_resolv_conf(Manager *m);
@@ -292,7 +293,9 @@ void network_free(Network *network);
 DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free);
 #define _cleanup_network_free_ _cleanup_(network_freep)
 
-int network_get(Manager *manager, struct udev_device *device, Network **ret);
+int network_get(Manager *manager, struct udev_device *device,
+                const char *ifname, const struct ether_addr *mac,
+                Network **ret);
 int network_apply(Manager *manager, Network *network, Link *link);
 
 int config_parse_bridge(const char *unit, const char *filename, unsigned line,
@@ -362,13 +365,14 @@ int config_parse_label(const char *unit, const char *filename, unsigned line,
 
 /* Link */
 
-int link_new(Manager *manager, struct udev_device *device, Link **ret);
 void link_free(Link *link);
 int link_get(Manager *m, int ifindex, Link **ret);
-int link_add(Manager *manager, struct udev_device *device, Link **ret);
+int link_add(Manager *manager, sd_rtnl_message *message, Link **ret);
 
 int link_update(Link *link, sd_rtnl_message *message);
 
+int link_initialized(Link *link, struct udev_device *device);
+
 int link_save(Link *link);
 
 const char* link_state_to_string(LinkState s) _const_;
index 9c372c7..38d57cc 100644 (file)
 
 #include "networkd.h"
 
-static void test_link(Manager *manager, struct udev_device *loopback) {
-        Link *link = NULL;
-
-        assert_se(link_new(manager, loopback, &link) >= 0);
-        assert_se(link);
-}
-
 static void test_load_config(Manager *manager) {
 /*  TODO: should_reload, is false if the config dirs do not exist, so
  *        so we can't do this test here, move it to a test for paths_check_timestamps
@@ -41,10 +34,11 @@ static void test_load_config(Manager *manager) {
 
 static void test_network_get(Manager *manager, struct udev_device *loopback) {
         Network *network;
+        const struct ether_addr mac = {};
 
         /* let's assume that the test machine does not have a .network file
            that applies to the loopback device... */
-        assert_se(network_get(manager, loopback, &network) == -ENOENT);
+        assert_se(network_get(manager, loopback, "lo", &mac, &network) == -ENOENT);
         assert_se(!network);
 }
 
@@ -66,11 +60,9 @@ int main(void) {
 
         test_network_get(manager, loopback);
 
-        test_link(manager, loopback);
-
         assert_se(manager_udev_listen(manager) >= 0);
-        assert_se(manager_udev_enumerate_links(manager) >= 0);
         assert_se(manager_rtnl_listen(manager) >= 0);
+        assert_se(manager_rtnl_enumerate_links(manager) >= 0);
 
         udev_device_unref(loopback);
         udev_unref(udev);
index 0c563b2..8215c40 100644 (file)
@@ -238,7 +238,7 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device, link_confi
                 if (net_match_config(link->match_mac, link->match_path, link->match_driver,
                                      link->match_type, NULL, link->match_host,
                                      link->match_virt, link->match_kernel, link->match_arch,
-                                     udev_device_get_sysattr_value(device, "address"),
+                                     ether_aton(udev_device_get_sysattr_value(device, "address")),
                                      udev_device_get_property_value(device, "ID_PATH"),
                                      udev_device_get_driver(udev_device_get_parent(device)),
                                      udev_device_get_property_value(device, "ID_NET_DRIVER"),