summaryrefslogtreecommitdiff
path: root/src/network/networkd-link.c
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2014-06-14 18:52:46 +0200
committerTom Gundersen <teg@jklm.no>2014-06-14 19:01:46 +0200
commit4f561e8e4364e36345940d4376a9750a829f382f (patch)
tree4042ab75d827fc31799c68265e338c2226d739a2 /src/network/networkd-link.c
parent5c8f858d207992469bd65356e3e44d37fcefa4b0 (diff)
networkd: link - flush all pending NEWLINK events before trying to match
We could still have an old interface name and/or mac address when libudev tells us that the device is initialized, as the up-to-date info could still be on its way from the kernel.
Diffstat (limited to 'src/network/networkd-link.c')
-rw-r--r--src/network/networkd-link.c54
1 files changed, 44 insertions, 10 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 452fcd43c2..f496978cba 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1751,7 +1751,8 @@ static int link_configure(Link *link) {
return link_enter_enslave(link);
}
-int link_initialized(Link *link, struct udev_device *device) {
+static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
+ Link *link = userdata;
Network *network;
int r;
@@ -1762,12 +1763,9 @@ int link_initialized(Link *link, struct udev_device *device) {
if (link->state != LINK_STATE_INITIALIZING)
return 0;
- if (device)
- link->udev_device = udev_device_ref(device);
+ log_debug_link(link, "link state is up-to-date");
- log_debug_link(link, "udev initialized link");
-
- r = network_get(link->manager, device, link->ifname, &link->mac, &network);
+ r = network_get(link->manager, link->udev_device, link->ifname, &link->mac, &network);
if (r == -ENOENT) {
link_enter_unmanaged(link);
return 0;
@@ -1785,6 +1783,38 @@ int link_initialized(Link *link, struct udev_device *device) {
return 0;
}
+int link_initialized(Link *link, struct udev_device *device) {
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
+ int r;
+
+ assert(link);
+ assert(link->manager);
+ assert(link->manager->rtnl);
+ assert(device);
+
+ if (link->state != LINK_STATE_INITIALIZING)
+ return 0;
+
+ log_debug_link(link, "udev initialized link");
+
+ link->udev_device = udev_device_ref(device);
+
+ /* udev has initialized the link, but we don't know if we have yet processed
+ the NEWLINK messages with the latest state. Do a GETLINK, when it returns
+ we know that the pending NEWLINKs have already been processed and that we
+ are up-to-date */
+
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK, link->ifindex);
+ if (r < 0)
+ return r;
+
+ r = sd_rtnl_call_async(link->manager->rtnl, req, link_initialized_and_synced, link, 0, NULL);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
Manager *m = userdata;
Link *link = NULL;
@@ -1972,11 +2002,15 @@ int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
log_debug_link(link, "udev initializing link...");
return 0;
}
- }
- r = link_initialized(link, device);
- if (r < 0)
- return r;
+ r = link_initialized(link, device);
+ if (r < 0)
+ return r;
+ } else {
+ r = link_initialized_and_synced(m->rtnl, NULL, link);
+ if (r < 0)
+ return r;
+ }
return 0;
}