platform: give the platform an opportunity to override default-unmanaged

Some out of tree drivers add Ethernet devices that are supposed to be managed
by other their tooling, e.g. VirtualBox or VMWare.

Rather than hardcoding their drivers (at least VirtualBox doesn't even set a
"driver" property in sysfs) or hardcoding a logic that identifies such devices
let's just add a possibility to blacklist them in udev. This makes it possible
for whoever who ships such a driver to ship rules that prevent NetworkManager
from managing the device itself.

Furthermore it makes it possible for the user with special needs leverage the
flexibility of udev rules to override the defaults. In the end the user can
decide to let NetworkManager manage default-unmanaged interfaces such as VEth
or turn on default-unmanaged for devices on a particular bus.

An udev rule for VirtualBox would look like this:

  SUBSYSTEM=="net", ENV{INTERFACE}=="vboxnet[0-9]*", ENV{NM_UNMANAGED}="1"
This commit is contained in:
Lubomir Rintel
2015-01-22 16:41:15 +01:00
parent 4a05869557
commit 85ee1f4a9c
6 changed files with 75 additions and 1 deletions

View File

@@ -358,6 +358,33 @@
</variablelist> </variablelist>
</refsect1> </refsect1>
<refsect1>
<title>UDEV PROPERTIES</title>
<para>
<citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry>
device manager is used for the network device discovery. The following
property influences how NetworkManager manages the devices:
</para>
<variablelist>
<varlistentry>
<term><varname>NM_UNMANAGED</varname></term>
<listitem><para>
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.
</para><para>
Create an udev rule that sets this property to prevent NetworkManager
from interfering with virtual Ethernet device interfaces that are
managed by virtualization tools.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1> <refsect1>
<title>DEBUGGING</title> <title>DEBUGGING</title>
<para> <para>
@@ -386,6 +413,7 @@
<citerefentry><refentrytitle>nm-settings</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>nm-settings</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>nm-applet</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>nm-applet</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>nm-connection-editor</refentrytitle><manvolnum>1</manvolnum></citerefentry> <citerefentry><refentrytitle>nm-connection-editor</refentrytitle><manvolnum>1</manvolnum></citerefentry>
<citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para> </para>
</refsect1> </refsect1>
</refentry> </refentry>

View File

@@ -1795,7 +1795,7 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
const char *iface, *driver, *type_desc; const char *iface, *driver, *type_desc;
const GSList *unmanaged_specs; const GSList *unmanaged_specs;
gboolean user_unmanaged, sleeping; gboolean user_unmanaged, sleeping, platform_unmanaged;
gboolean enabled = FALSE; gboolean enabled = FALSE;
RfKillType rtype; RfKillType rtype;
GSList *iter, *remove = NULL; 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); user_unmanaged = nm_device_spec_match_list (device, unmanaged_specs);
nm_device_set_initial_unmanaged_flag (device, NM_UNMANAGED_USER, user_unmanaged); 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); sleeping = manager_sleeping (self);
nm_device_set_initial_unmanaged_flag (device, NM_UNMANAGED_INTERNAL, sleeping); nm_device_set_initial_unmanaged_flag (device, NM_UNMANAGED_INTERNAL, sleeping);

View File

@@ -299,6 +299,12 @@ link_get_type_name (NMPlatform *platform, int ifindex)
return type_to_type_name (link_get_type (platform, 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 static void
link_changed (NMPlatform *platform, NMFakePlatformLink *device) 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_name = link_get_name;
platform_class->link_get_type = link_get_type; platform_class->link_get_type = link_get_type;
platform_class->link_get_type_name = link_get_type_name; 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_up = link_set_up;
platform_class->link_set_down = link_set_down; platform_class->link_set_down = link_set_down;

View File

@@ -2395,6 +2395,20 @@ link_get_type_name (NMPlatform *platform, int ifindex)
return type; 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 static guint32
link_get_flags (NMPlatform *platform, int ifindex) 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_name = link_get_name;
platform_class->link_get_type = link_get_type; platform_class->link_get_type = link_get_type;
platform_class->link_get_type_name = link_get_type_name; platform_class->link_get_type_name = link_get_type_name;
platform_class->link_get_unmanaged = link_get_unmanaged;
platform_class->link_refresh = link_refresh; platform_class->link_refresh = link_refresh;

View File

@@ -652,6 +652,25 @@ nm_platform_link_get_type_name (int ifindex)
return klass->link_get_type_name (platform, 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: * nm_platform_link_is_software:
* @ifindex: Interface index. * @ifindex: Interface index.

View File

@@ -351,6 +351,7 @@ typedef struct {
const char *(*link_get_name) (NMPlatform *, int ifindex); const char *(*link_get_name) (NMPlatform *, int ifindex);
NMLinkType (*link_get_type) (NMPlatform *, int ifindex); NMLinkType (*link_get_type) (NMPlatform *, int ifindex);
const char *(*link_get_type_name) (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); 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); const char *nm_platform_link_get_name (int ifindex);
NMLinkType nm_platform_link_get_type (int ifindex); NMLinkType nm_platform_link_get_type (int ifindex);
const char *nm_platform_link_get_type_name (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_is_software (int ifindex);
gboolean nm_platform_link_supports_slaves (int ifindex); gboolean nm_platform_link_supports_slaves (int ifindex);