platform: don't wait for udev before announcing links

This commit is contained in:
Dan Williams
2015-04-13 16:29:37 -05:00
parent 3006df940c
commit 388b7830f3
8 changed files with 114 additions and 96 deletions

View File

@@ -887,19 +887,6 @@ type_to_string (NMLinkType type)
}
}
static gboolean
link_is_announceable (NMPlatform *platform, struct rtnl_link *rtnllink)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
/* 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))))
return TRUE;
return FALSE;
}
#define DEVTYPE_PREFIX "DEVTYPE="
static char *
@@ -1058,15 +1045,17 @@ init_link (NMPlatform *platform, NMPlatformLink *info, struct rtnl_link *rtnllin
udev_device = g_hash_table_lookup (priv->udev_devices, GINT_TO_POINTER (info->ifindex));
if (udev_device) {
info->driver = udev_get_driver (udev_device, info->ifindex);
if (!info->driver)
info->driver = g_intern_string (rtnl_link_get_type (rtnllink));
if (!info->driver)
info->driver = ethtool_get_driver (info->name);
if (!info->driver)
info->driver = "unknown";
info->udi = g_udev_device_get_sysfs_path (udev_device);
info->initialized = TRUE;
}
if (!info->driver)
info->driver = g_intern_string (rtnl_link_get_type (rtnllink));
if (!info->driver)
info->driver = ethtool_get_driver (info->name);
if (!info->driver)
info->driver = "unknown";
return TRUE;
}
@@ -1624,22 +1613,6 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor
if (!init_link (platform, &device, rtnl_link))
return;
/* 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
* themselves when appropriate.
*/
switch (change_type) {
case NM_PLATFORM_SIGNAL_ADDED:
case NM_PLATFORM_SIGNAL_CHANGED:
if (!device.driver)
return;
break;
default:
break;
}
/* Link deletion or setting down is sometimes accompanied by address
* and/or route deletion.
*
@@ -2067,15 +2040,12 @@ event_notification (struct nl_msg *msg, gpointer user_data)
return NL_OK;
nl_cache_remove (cached_object);
/* Don't announce removed interfaces that are not recognized by
* udev. They were either not yet discovered or they have been
* already removed and announced.
*/
if (event == RTM_DELLINK) {
if (!link_is_announceable (platform, (struct rtnl_link *) cached_object))
return NL_OK;
}
announce_object (platform, cached_object, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_EXTERNAL);
if (event == RTM_DELLINK) {
int ifindex = rtnl_link_get_ifindex ((struct rtnl_link *) cached_object);
g_hash_table_remove (priv->udev_devices, GINT_TO_POINTER (ifindex));
}
return NL_OK;
case RTM_NEWLINK:
@@ -2303,12 +2273,8 @@ link_get_all (NMPlatform *platform)
struct nl_object *object;
for (object = nl_cache_get_first (priv->link_cache); object; object = nl_cache_get_next (object)) {
struct rtnl_link *rtnl_link = (struct rtnl_link *) object;
if (link_is_announceable (platform, rtnl_link)) {
if (init_link (platform, &device, rtnl_link))
g_array_append_val (links, device);
}
if (init_link (platform, &device, (struct rtnl_link *) object))
g_array_append_val (links, device);
}
return links;
@@ -2321,13 +2287,7 @@ _nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *l)
auto_nl_object struct rtnl_link *rtnllink = NULL;
rtnllink = rtnl_link_get (priv->link_cache, ifindex);
if (rtnllink) {
if (link_is_announceable (platform, rtnllink)) {
if (init_link (platform, l, rtnllink))
return TRUE;
}
}
return FALSE;
return (rtnllink && init_link (platform, l, rtnllink));
}
static struct nl_object *
@@ -2386,13 +2346,6 @@ link_get (NMPlatform *platform, int ifindex)
return NULL;
}
/* physical interfaces must be found by udev before they can be used */
if (!link_is_announceable (platform, rtnllink)) {
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
rtnl_link_put (rtnllink);
return NULL;
}
return rtnllink;
}
@@ -4432,7 +4385,6 @@ udev_device_added (NMPlatform *platform,
auto_nl_object struct rtnl_link *rtnllink = NULL;
const char *ifname;
int ifindex;
gboolean was_announceable = FALSE;
ifname = g_udev_device_get_name (udev_device);
if (!ifname) {
@@ -4457,15 +4409,15 @@ udev_device_added (NMPlatform *platform,
}
rtnllink = rtnl_link_get (priv->link_cache, ifindex);
if (rtnllink)
was_announceable = link_is_announceable (platform, rtnllink);
if (!rtnllink) {
warning ("(%s): udev-add: interface not known via netlink; ignoring...", ifname);
return;
}
g_hash_table_insert (priv->udev_devices, GINT_TO_POINTER (ifindex),
g_object_ref (udev_device));
/* Announce devices only if they also have been discovered via Netlink. */
if (rtnllink && link_is_announceable (platform, rtnllink))
announce_object (platform, (struct nl_object *) rtnllink, was_announceable ? NM_PLATFORM_SIGNAL_CHANGED : NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_EXTERNAL);
announce_object (platform, (struct nl_object *) rtnllink, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_EXTERNAL);
}
static void
@@ -4473,9 +4425,7 @@ udev_device_removed (NMPlatform *platform,
GUdevDevice *udev_device)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
auto_nl_object struct rtnl_link *rtnllink = NULL;
int ifindex = 0;
gboolean was_announceable = FALSE;
if (g_udev_device_get_property (udev_device, "IFINDEX"))
ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX");
@@ -4500,15 +4450,7 @@ udev_device_removed (NMPlatform *platform,
if (ifindex <= 0)
return;
rtnllink = rtnl_link_get (priv->link_cache, ifindex);
if (rtnllink)
was_announceable = link_is_announceable (platform, rtnllink);
g_hash_table_remove (priv->udev_devices, GINT_TO_POINTER (ifindex));
/* Announce device removal if it is no longer announceable. */
if (was_announceable && !link_is_announceable (platform, rtnllink))
announce_object (platform, (struct nl_object *) rtnllink, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_EXTERNAL);
}
static void
@@ -4553,8 +4495,6 @@ constructed (GObject *_object)
NMPlatform *platform = NM_PLATFORM (_object);
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
const char *udev_subsys[] = { "net", NULL };
GUdevEnumerator *enumerator;
GList *devices, *iter;
int channel_flags;
gboolean status;
int nle;
@@ -4614,6 +4554,24 @@ constructed (GObject *_object)
g_signal_connect (priv->udev_client, "uevent", G_CALLBACK (handle_udev_event), platform);
priv->udev_devices = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
/* request all IPv6 addresses (hopeing that there is at least one), to check for
* the IFA_FLAGS attribute. */
nle = nl_rtgen_request (priv->nlh_event, RTM_GETADDR, AF_INET6, NLM_F_DUMP);
if (nle < 0)
nm_log_warn (LOGD_PLATFORM, "Netlink error: requesting RTM_GETADDR failed with %s", nl_geterror (nle));
priv->wifi_data = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) wifi_utils_deinit);
G_OBJECT_CLASS (nm_linux_platform_parent_class)->constructed (_object);
}
static void
setup_devices (NMPlatform *platform)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
GUdevEnumerator *enumerator;
GList *devices, *iter;
/* And read initial device list */
enumerator = g_udev_enumerator_new (priv->udev_client);
g_udev_enumerator_add_match_subsystem (enumerator, "net");
@@ -4631,16 +4589,6 @@ constructed (GObject *_object)
}
g_list_free (devices);
g_object_unref (enumerator);
/* request all IPv6 addresses (hopeing that there is at least one), to check for
* the IFA_FLAGS attribute. */
nle = nl_rtgen_request (priv->nlh_event, RTM_GETADDR, AF_INET6, NLM_F_DUMP);
if (nle < 0)
nm_log_warn (LOGD_PLATFORM, "Netlink error: requesting RTM_GETADDR failed with %s", nl_geterror (nle));
priv->wifi_data = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) wifi_utils_deinit);
G_OBJECT_CLASS (nm_linux_platform_parent_class)->constructed (_object);
}
static void
@@ -4678,6 +4626,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
object_class->constructed = constructed;
object_class->finalize = nm_linux_platform_finalize;
platform_class->setup_devices = setup_devices;
platform_class->sysctl_set = sysctl_set;
platform_class->sysctl_get = sysctl_get;