From 3300e10c69940bbd68c2d41f6ea2e53b609923ad Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Fri, 21 Nov 2014 15:02:37 +0100 Subject: [PATCH] platform: don't wait for udev device initializaton if there's no udev There's no udev running in containers, it only starts if /sys is writable. If a hardware device is added to the container's namespace NM would not announce it. This also removes the software link special case -- the software links will now wait for udev initialization (in case udev is there) as well. There's no reason to treat them differently anymore. This makes it possible to use udev properties of the software links. https://bugzilla.gnome.org/show_bug.cgi?id=740526 (cherry picked from commit 4a0586955767537b7494f931ccaa93bbf59c36f9) --- src/platform/nm-fake-platform.c | 30 +++++++++++++++++-- src/platform/nm-linux-platform.c | 50 +++++-------------------------- src/platform/tests/test-address.c | 2 +- src/platform/tests/test-cleanup.c | 2 +- src/platform/tests/test-link.c | 8 ++--- src/platform/tests/test-route.c | 2 +- 6 files changed, 43 insertions(+), 51 deletions(-) diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 5fb802f1a3..33a2a7143e 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -49,6 +49,11 @@ typedef struct { int vlan_id; } NMFakePlatformLink; +typedef struct { + int ifindex; + NMPlatform *platform; +} NMFakePlatformLinkData; + #define NM_FAKE_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_FAKE_PLATFORM, NMFakePlatformPrivate)) G_DEFINE_TYPE (NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM) @@ -174,6 +179,23 @@ _nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *l) return !!device; } +static gboolean +_link_announce (NMFakePlatformLinkData *data) +{ + NMFakePlatformLink *device = link_get (data->platform, data->ifindex); + + if (device) + g_signal_emit_by_name (data->platform, + NM_PLATFORM_SIGNAL_LINK_CHANGED, + device->link.ifindex, + device, + NM_PLATFORM_SIGNAL_ADDED, + NM_PLATFORM_REASON_INTERNAL); + g_free (data); + + return FALSE; +} + static gboolean link_add (NMPlatform *platform, const char *name, NMLinkType type, const void *address, size_t address_len) { @@ -184,8 +206,12 @@ link_add (NMPlatform *platform, const char *name, NMLinkType type, const void *a g_array_append_val (priv->links, device); - if (device.link.ifindex) - g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, device.link.ifindex, &device, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL); + if (device.link.ifindex) { + NMFakePlatformLinkData *data = g_new (NMFakePlatformLinkData, 1); + data->ifindex = device.link.ifindex; + data->platform = platform; + g_idle_add ((GSourceFunc) _link_announce, data); + } return TRUE; } diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 9a49c0fcd1..0fe133cdce 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -780,41 +780,6 @@ link_type_from_udev (NMPlatform *platform, int ifindex, const char *ifname, int return_type (NM_LINK_TYPE_UNKNOWN, "unknown"); } -static gboolean -link_is_software (struct rtnl_link *rtnllink) -{ - const char *type; - - /* FIXME: replace somehow with NMLinkType or nm_platform_is_software(), but - * solve the infinite callstack problems that getting the type of a TUN/TAP - * device causes. - */ - - if ( rtnl_link_get_arptype (rtnllink) == ARPHRD_INFINIBAND - && strchr (rtnl_link_get_name (rtnllink), '.')) - return TRUE; - - type = rtnl_link_get_type (rtnllink); - if (type == NULL) - return FALSE; - - if (!strcmp (type, "dummy") || - !strcmp (type, "gre") || - !strcmp (type, "gretap") || - !strcmp (type, "macvlan") || - !strcmp (type, "macvtap") || - !strcmp (type, "tun") || - !strcmp (type, "veth") || - !strcmp (type, "vlan") || - !strcmp (type, "vxlan") || - !strcmp (type, "bridge") || - !strcmp (type, "bond") || - !strcmp (type, "team")) - return TRUE; - - return FALSE; -} - static const char * ethtool_get_driver (const char *ifname) { @@ -837,10 +802,6 @@ link_is_announceable (NMPlatform *platform, struct rtnl_link *rtnllink) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - /* Software devices are always visible outside the platform */ - if (link_is_software (rtnllink)) - return TRUE; - /* Hardware devices must be found by udev so rules get run and tags set */ if (g_hash_table_lookup (priv->udev_devices, GINT_TO_POINTER (rtnl_link_get_ifindex (rtnllink)))) @@ -1585,7 +1546,7 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor if (!init_link (platform, &device, rtnl_link)) return; - /* Skip hardware devices not yet discovered by udev. They will be + /* Skip devices not yet discovered by udev. They will be * announced by udev_device_added(). This doesn't apply to removed * devices, as those come either from udev_device_removed(), * event_notification() or link_delete() which block the announcment @@ -1594,7 +1555,7 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor switch (change_type) { case NM_PLATFORM_SIGNAL_ADDED: case NM_PLATFORM_SIGNAL_CHANGED: - if (!link_is_software (rtnl_link) && !device.driver) + if (!device.driver) return; break; default: @@ -4557,7 +4518,12 @@ setup (NMPlatform *platform) /* And read initial device list */ enumerator = g_udev_enumerator_new (priv->udev_client); g_udev_enumerator_add_match_subsystem (enumerator, "net"); - g_udev_enumerator_add_match_is_initialized (enumerator); + + /* Demand that the device is initialized (udev rules ran, + * device has a stable name now) in case udev is running + * (not in a container). */ + if (access ("/sys", W_OK) == 0) + g_udev_enumerator_add_match_is_initialized (enumerator); devices = g_udev_enumerator_execute (enumerator); for (iter = devices; iter; iter = g_list_next (iter)) { diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c index 10867eaf91..08f2f1f250 100644 --- a/src/platform/tests/test-address.c +++ b/src/platform/tests/test-address.c @@ -256,7 +256,7 @@ setup_tests (void) nm_platform_link_delete (nm_platform_link_get_ifindex (DEVICE_NAME)); g_assert (!nm_platform_link_exists (DEVICE_NAME)); g_assert (nm_platform_dummy_add (DEVICE_NAME)); - accept_signal (link_added); + wait_signal (link_added); free_signal (link_added); g_test_add_func ("/address/internal/ip4", test_ip4_address); diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c index 0d0f3f63ad..796ca874e5 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/platform/tests/test-cleanup.c @@ -36,7 +36,7 @@ test_cleanup_internal (void) /* Create and set up device */ g_assert (nm_platform_dummy_add (DEVICE_NAME)); - accept_signal (link_added); + wait_signal (link_added); free_signal (link_added); g_assert (nm_platform_link_set_up (nm_platform_link_get_ifindex (DEVICE_NAME))); ifindex = nm_platform_link_get_ifindex (DEVICE_NAME); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 9874e34729..8a2f2a84d1 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -115,7 +115,7 @@ software_add (NMLinkType link_type, const char *name) /* Don't call link_callback for the bridge interface */ parent_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, PARENT_NAME); if (nm_platform_bridge_add (PARENT_NAME, NULL, 0)) - accept_signal (parent_added); + wait_signal (parent_added); free_signal (parent_added); { @@ -148,7 +148,7 @@ test_slave (int master, int type, SignalData *master_changed) g_assert (ifindex > 0); link_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, link_callback, ifindex); link_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, ifindex); - accept_signal (link_added); + wait_signal (link_added); /* Set the slave up to see whether master's IFF_LOWER_UP is set correctly. * @@ -263,7 +263,7 @@ test_software (NMLinkType link_type, const char *link_typename) link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME); g_assert (software_add (link_type, DEVICE_NAME)); no_error (); - accept_signal (link_added); + wait_signal (link_added); g_assert (nm_platform_link_exists (DEVICE_NAME)); ifindex = nm_platform_link_get_ifindex (DEVICE_NAME); g_assert (ifindex >= 0); @@ -405,7 +405,7 @@ test_internal (void) /* Add device */ g_assert (nm_platform_dummy_add (DEVICE_NAME)); no_error (); - accept_signal (link_added); + wait_signal (link_added); /* Try to add again */ g_assert (!nm_platform_dummy_add (DEVICE_NAME)); diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index 4b72cebd08..6289d1994c 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -321,7 +321,7 @@ setup_tests (void) nm_platform_link_delete (nm_platform_link_get_ifindex (DEVICE_NAME)); g_assert (!nm_platform_link_exists (DEVICE_NAME)); g_assert (nm_platform_dummy_add (DEVICE_NAME)); - accept_signal (link_added); + wait_signal (link_added); free_signal (link_added); g_assert (nm_platform_link_set_up (nm_platform_link_get_ifindex (DEVICE_NAME)));