diff --git a/man/NetworkManager.xml b/man/NetworkManager.xml
index aa54fe152..ceb810e3b 100644
--- a/man/NetworkManager.xml
+++ b/man/NetworkManager.xml
@@ -358,6 +358,33 @@
+
+ UDEV PROPERTIES
+
+
+ udev7
+ device manager is used for the network device discovery. The following
+ property influences how NetworkManager manages the devices:
+
+
+
+
+ NM_UNMANAGED
+
+ No default connection will be created and automatic activation
+ will not be attempted when this property of a device is set to a
+ true value ("1" or "true"). You will still be able to attach a
+ connection to the device manually or observe externally added
+ configuration such as addresses or routes.
+
+ Create an udev rule that sets this property to prevent NetworkManager
+ from interfering with virtual Ethernet device interfaces that are
+ managed by virtualization tools.
+
+
+
+
+
DEBUGGING
@@ -386,6 +413,7 @@
nm-settings5,
nm-applet1,
nm-connection-editor1
+ udev7
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 4da0f315f..9ccb7e44d 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -1795,7 +1795,7 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
const char *iface, *driver, *type_desc;
const GSList *unmanaged_specs;
- gboolean user_unmanaged, sleeping;
+ gboolean user_unmanaged, sleeping, platform_unmanaged;
gboolean enabled = FALSE;
RfKillType rtype;
GSList *iter, *remove = NULL;
@@ -1871,6 +1871,9 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
user_unmanaged = nm_device_spec_match_list (device, unmanaged_specs);
nm_device_set_initial_unmanaged_flag (device, NM_UNMANAGED_USER, user_unmanaged);
+ if (nm_platform_link_get_unmanaged (nm_device_get_ifindex (device), &platform_unmanaged))
+ nm_device_set_initial_unmanaged_flag (device, NM_UNMANAGED_DEFAULT, platform_unmanaged);
+
sleeping = manager_sleeping (self);
nm_device_set_initial_unmanaged_flag (device, NM_UNMANAGED_INTERNAL, sleeping);
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 941d742a1..7194707b2 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -299,6 +299,12 @@ link_get_type_name (NMPlatform *platform, int ifindex)
return type_to_type_name (link_get_type (platform, ifindex));
}
+static gboolean
+link_get_unmanaged (NMPlatform *platform, int ifindex, gboolean *managed)
+{
+ return FALSE;
+}
+
static void
link_changed (NMPlatform *platform, NMFakePlatformLink *device)
{
@@ -1384,6 +1390,7 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
platform_class->link_get_name = link_get_name;
platform_class->link_get_type = link_get_type;
platform_class->link_get_type_name = link_get_type_name;
+ platform_class->link_get_unmanaged = link_get_unmanaged;
platform_class->link_set_up = link_set_up;
platform_class->link_set_down = link_set_down;
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index f219898d8..3a0bbe4d1 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -2395,6 +2395,20 @@ link_get_type_name (NMPlatform *platform, int ifindex)
return type;
}
+static gboolean
+link_get_unmanaged (NMPlatform *platform, int ifindex, gboolean *managed)
+{
+ NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+ GUdevDevice *udev_device = g_hash_table_lookup (priv->udev_devices, GINT_TO_POINTER (ifindex));
+
+ if (g_udev_device_get_property (udev_device, "NM_UNMANAGED")) {
+ *managed = g_udev_device_get_property_as_boolean (udev_device, "NM_UNMANAGED");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static guint32
link_get_flags (NMPlatform *platform, int ifindex)
{
@@ -4571,6 +4585,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_get_name = link_get_name;
platform_class->link_get_type = link_get_type;
platform_class->link_get_type_name = link_get_type_name;
+ platform_class->link_get_unmanaged = link_get_unmanaged;
platform_class->link_refresh = link_refresh;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 9500a7542..d51c142e0 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -652,6 +652,25 @@ nm_platform_link_get_type_name (int ifindex)
return klass->link_get_type_name (platform, ifindex);
}
+/**
+ * nm_platform_link_get_unmanaged:
+ * @ifindex: Interface index.
+ * @managed: Management status in case %TRUE is returned
+ *
+ * Returns: %TRUE if platform overrides whether the device ought
+ * to be managed by default. %FALSE with @managed unmodified
+ * otherwise.
+ */
+gboolean
+nm_platform_link_get_unmanaged (int ifindex, gboolean *managed)
+{
+ reset_error ();
+
+ g_return_val_if_fail (klass->link_get_unmanaged, FALSE);
+
+ return klass->link_get_unmanaged (platform, ifindex, managed);
+}
+
/**
* nm_platform_link_is_software:
* @ifindex: Interface index.
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index c2dca4e58..bc7b84c9f 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -351,6 +351,7 @@ typedef struct {
const char *(*link_get_name) (NMPlatform *, int ifindex);
NMLinkType (*link_get_type) (NMPlatform *, int ifindex);
const char *(*link_get_type_name) (NMPlatform *, int ifindex);
+ gboolean (*link_get_unmanaged) (NMPlatform *, int ifindex, gboolean *managed);
gboolean (*link_refresh) (NMPlatform *, int ifindex);
@@ -498,6 +499,7 @@ int nm_platform_link_get_ifindex (const char *name);
const char *nm_platform_link_get_name (int ifindex);
NMLinkType nm_platform_link_get_type (int ifindex);
const char *nm_platform_link_get_type_name (int ifindex);
+gboolean nm_platform_link_get_unmanaged (int ifindex, gboolean *managed);
gboolean nm_platform_link_is_software (int ifindex);
gboolean nm_platform_link_supports_slaves (int ifindex);