chiark / gitweb /
udev: link_setup - respect kernel name assign policy
authorTom Gundersen <teg@jklm.no>
Tue, 15 Jul 2014 15:57:43 +0000 (17:57 +0200)
committerTom Gundersen <teg@jklm.no>
Fri, 8 Aug 2014 11:30:15 +0000 (13:30 +0200)
Newer kernels export meta-information about the origin of an ifname. Respect this
from the ifname rename logic. We do not rename any interfaces that was originally
named by userspace, nor once which have already been renamed from userspace.

Moreover, we optionally do not (the default) rename interfaces which the kernel
claims to have named in a predictable way.

man/systemd.link.xml
network/99-default.link
src/shared/missing.h
src/udev/net/link-config.c
src/udev/net/link-config.h

index 05effc3b713c1a1e7c0ff6beb1e6dfcc311ab9d6..6075b39b790d1bc88783b7ea2fbae5cdab3bda74 100644 (file)
                                         not set directly, but is exported to udev as
                                         the property <literal>ID_NET_NAME</literal>,
                                         which is, by default, used by a udev rule to set
-                                        <literal>NAME</literal>. The available policies
-                                        are:</para>
+                                        <literal>NAME</literal>. If the name has already
+                                        been set by userspace, no renaming is performed.
+                                        The available policies are:</para>
 
                                         <variablelist>
+                                                <varlistentry>
+                                                        <term><literal>kernel</literal></term>
+                                                        <listitem>
+                                                                <para>If the kernel claims that the name it
+                                                                has set for a device is predictable, then
+                                                                no renaming is performed.
+                                                                </para>
+                                                        </listitem>
+                                                </varlistentry>
                                                 <varlistentry>
                                                         <term><literal>database</literal></term>
                                                         <listitem>
index 53215f633bb9fdca81d72aabadc07c769926dc25..79538f9b29bddd8c9f32b973b4c3f8693bf80b2f 100644 (file)
@@ -1,3 +1,3 @@
 [Link]
-NamePolicy=database onboard slot path
+NamePolicy=kernel database onboard slot path
 MACAddressPolicy=persistent
index e20f9bdfd35192b1af0f7ff6a080c87be5146149..195edfc672b124c59bcf39701825945d0d795bd1 100644 (file)
@@ -525,3 +525,23 @@ static inline int setns(int fd, int nstype) {
 #ifndef BOND_XMIT_POLICY_ENCAP34
 #define BOND_XMIT_POLICY_ENCAP34 4
 #endif
+
+#ifndef NET_ADDR_RANDOM
+#  define NET_ADDR_RANDOM 1
+#endif
+
+#ifndef NET_NAME_ENUM
+#  define NET_NAME_ENUM 1
+#endif
+
+#ifndef NET_NAME_PREDICTABLE
+#  define NET_NAME_PREDICTABLE 2
+#endif
+
+#ifndef NET_NAME_USER
+#  define NET_NAME_USER 3
+#endif
+
+#ifndef NET_NAME_RENAMED
+#  define NET_NAME_RENAMED 4
+#endif
index 946715ce5a106911819982898beab5329b813a52..b44aeaf6db0dd071e5beab0d3e0daade3031cb98 100644 (file)
 ***/
 
 #include <netinet/ether.h>
-#include <net/if.h>
+#include <linux/netdevice.h>
 
 #include "sd-id128.h"
 
+#include "missing.h"
 #include "link-config.h"
 #include "ethtool-util.h"
 
@@ -283,8 +284,33 @@ static bool mac_is_random(struct udev_device *device) {
         if (r < 0)
                 return false;
 
-        /* check for NET_ADDR_RANDOM */
-        return type == 1;
+        return type == NET_ADDR_RANDOM;
+}
+
+static bool should_rename(struct udev_device *device, bool respect_predictable) {
+        const char *s;
+        unsigned type;
+        int r;
+
+        s = udev_device_get_sysattr_value(device, "name_assign_type");
+        if (!s)
+                return true; /* if we don't know, assume we should rename */
+        r = safe_atou(s, &type);
+        if (r < 0)
+                return true;
+
+        switch (type) {
+        case NET_NAME_USER:
+        case NET_NAME_RENAMED:
+                return false; /* these were already named by userspace, do not touch again */
+        case NET_NAME_PREDICTABLE:
+                if (respect_predictable)
+                        return false; /* the kernel claims to have given a predictable name */
+                /* fall through */
+        case NET_NAME_ENUM:
+        default:
+                return true; /* the name is known to be bad, or of an unknown type */
+        }
 }
 
 static int get_mac(struct udev_device *device, bool want_random, struct ether_addr *mac) {
@@ -315,6 +341,7 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_dev
         const char *new_name = NULL;
         struct ether_addr generated_mac;
         struct ether_addr *mac = NULL;
+        bool respect_predictable = false;
         int r, ifindex;
 
         assert(ctx);
@@ -350,8 +377,12 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_dev
         if (ctx->enable_name_policy && config->name_policy) {
                 NamePolicy *policy;
 
-                for (policy = config->name_policy; !new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
+                for (policy = config->name_policy; !respect_predictable && !new_name &&
+                                                   *policy != _NAMEPOLICY_INVALID; policy++) {
                         switch (*policy) {
+                                case NAMEPOLICY_KERNEL:
+                                        respect_predictable = true;
+                                        break;
                                 case NAMEPOLICY_DATABASE:
                                         new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE");
                                         break;
@@ -373,12 +404,14 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_dev
                 }
         }
 
-        if (new_name)
-                *name = new_name; /* a name was set by a policy */
-        else if (config->name)
-                *name = config->name; /* a name was set manually in the config */
-        else
-                *name = NULL;
+        if (should_rename(device, respect_predictable)) {
+                if (!new_name)
+                        /* if not set by policy, fall back manually set name */
+                        new_name = config->name;
+        } else
+                new_name = NULL;
+
+        *name = new_name;
 
         switch (config->mac_policy) {
                 case MACPOLICY_PERSISTENT:
@@ -444,6 +477,7 @@ DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
 DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy, "Failed to parse MAC address policy");
 
 static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
+        [NAMEPOLICY_KERNEL] = "kernel",
         [NAMEPOLICY_DATABASE] = "database",
         [NAMEPOLICY_ONBOARD] = "onboard",
         [NAMEPOLICY_SLOT] = "slot",
index 24fdb87e4c5c013e5eb9e15cfd56a2d4a6c1b4da..5f3d4ad142e2dc24d964e3828680bad27374b1c6 100644 (file)
@@ -39,6 +39,7 @@ typedef enum MACPolicy {
 } MACPolicy;
 
 typedef enum NamePolicy {
+        NAMEPOLICY_KERNEL,
         NAMEPOLICY_DATABASE,
         NAMEPOLICY_ONBOARD,
         NAMEPOLICY_SLOT,