1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-22 13:33:56 +03:00

Merge pull request #11449 from keszybz/udev-link-naming-again

Make udev link re-renaming conditional
This commit is contained in:
Lennart Poettering 2019-01-17 20:06:55 +01:00 committed by GitHub
commit 8274a4132c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 297 additions and 248 deletions

22
NEWS
View File

@ -22,6 +22,23 @@ CHANGES WITH 241 in spe:
* $DBUS_SESSION_BUS_ADDRESS environment variable is set by pam_systemd
again.
* A new network device NamePolicy "keep" is implemented for link files,
and used by default in 99-default.link (the fallback configuration
provided by systemd). With this policy, if the network device name
was already set by userspace, the device will not be renamed again.
This matches the naming scheme that was implemented before
systemd-240. If naming-scheme < 240 is specified, the "keep" policy
is also enabled by default, even if not specified. Effectively, this
means that if naming-scheme >= 240 is specified, network devices will
be renamed according to the configuration, even if they have been
renamed already, if "keep" is not specified as the naming policy in
the .link file. The 99-default.link file provided by systemd includes
"keep" for backwards compatibility, but it is recommended for user
installed .link files to *not* include it.
The "kernel" policy, which keeps kernel names declared to be
"persistent", now works again as documented.
* kernel-install script now optionally takes a path to an initrd file,
and passes it to all plugins.
@ -509,6 +526,11 @@ CHANGES WITH 240:
* $DBUS_SESSION_BUS_ADDRESS environment variable is not set by
pam_systemd anymore.
* The naming scheme for network devices was changed to always rename
devices, even if they were already renamed by userspace. The "kernel"
policy was changed to only apply as a fallback, if no other naming
policy took effect.
* The requirements to build systemd is bumped to meson-0.46 and
python-3.5.

View File

@ -50,27 +50,21 @@
same name pointing to <filename>/dev/null</filename> disables the
configuration file entirely (it is "masked").</para>
<para>The link file contains a <literal>[Match]</literal> section,
which determines if a given link file may be applied to a given
device, as well as a <literal>[Link]</literal> section specifying
how the device should be configured. The first (in lexical order)
of the link files that matches a given device is applied. Note
that a default file <filename>99-default.link</filename> is
shipped by the system. Any user-supplied
<filename>.link</filename> should hence have a lexically earlier
name to be considered at all.</para>
<para>The link file contains a [Match] section, which determines if a given link file may be applied to a
given device, as well as a [Link] section specifying how the device should be configured. The first (in
lexical order) of the link files that matches a given device is applied. Note that a default file
<filename>99-default.link</filename> is shipped by the system. Any user-supplied
<filename>.link</filename> should hence have a lexically earlier name to be considered at all.</para>
<para>See
<citerefentry><refentrytitle>udevadm</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for diagnosing problems with <filename>.link</filename> files.</para>
<para>See <citerefentry><refentrytitle>udevadm</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
diagnosing problems with <filename>.link</filename> files.</para>
</refsect1>
<refsect1>
<title>[Match] Section Options</title>
<para>A link file is said to match a device if each of the entries
in the <literal>[Match]</literal> section matches, or if the
section is empty. The following keys are accepted:</para>
<para>A link file is said to match a device if each of the entries in the [Match] section matches, or if
the section is empty. The following keys are accepted:</para>
<variablelist class='network-directives'>
<varlistentry>
@ -100,18 +94,15 @@
<listitem>
<para>A whitespace-separated list of shell-style globs matching
the persistent path, as exposed by the udev property
<literal>ID_PATH</literal>.</para>
<varname>ID_PATH</varname>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Driver=</varname></term>
<listitem>
<para>A whitespace-separated list of shell-style globs matching
the driver currently bound to the device,
as exposed by the udev property <literal>DRIVER</literal>
of its parent device, or if that is not set, the
driver as exposed by <literal>ethtool -i</literal>
of the device itself.</para>
<para>A whitespace-separated list of shell-style globs matching the driver currently bound to the
device, as exposed by the udev property <varname>DRIVER</varname> of its parent device, or if that
is not set, the driver as exposed by <command>ethtool -i</command> of the device itself.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -119,14 +110,14 @@
<listitem>
<para>A whitespace-separated list of shell-style globs matching
the device type, as exposed by the udev
property <literal>DEVTYPE</literal>.</para>
property <varname>DEVTYPE</varname>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Host=</varname></term>
<listitem>
<para>Matches against the hostname or machine
ID of the host. See <literal>ConditionHost=</literal> in
ID of the host. See <varname>ConditionHost=</varname> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para>
</listitem>
@ -137,7 +128,7 @@
<para>Checks whether the system is executed in
a virtualized environment and optionally test
whether it is a specific implementation. See
<literal>ConditionVirtualization=</literal> in
<varname>ConditionVirtualization=</varname> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para>
</listitem>
@ -147,7 +138,7 @@
<listitem>
<para>Checks whether a specific kernel command line option
is set (or if prefixed with the exclamation mark unset). See
<literal>ConditionKernelCommandLine=</literal> in
<varname>ConditionKernelCommandLine=</varname> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para>
</listitem>
@ -157,7 +148,7 @@
<listitem>
<para>Checks whether the kernel version (as reported by <command>uname -r</command>) matches a certain
expression (or if prefixed with the exclamation mark does not match it). See
<literal>ConditionKernelVersion=</literal> in
<varname>ConditionKernelVersion=</varname> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.
</para>
@ -167,7 +158,7 @@
<term><varname>Architecture=</varname></term>
<listitem>
<para>Checks whether the system is running on a specific
architecture. See <literal>ConditionArchitecture=</literal>
architecture. See <varname>ConditionArchitecture=</varname>
in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para>
@ -180,7 +171,7 @@
<refsect1>
<title>[Link] Section Options</title>
<para>The <literal>[Link]</literal> section accepts the following
<para>The [Link] section accepts the following
keys:</para>
<variablelist class='network-directives'>
@ -193,8 +184,7 @@
<varlistentry>
<term><varname>Alias=</varname></term>
<listitem>
<para>The <literal>ifalias</literal> is set to this
value.</para>
<para>The <varname>ifalias</varname> interface property is set to this value.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -206,7 +196,7 @@
<variablelist>
<varlistentry>
<term><literal>persistent</literal></term>
<term><option>persistent</option></term>
<listitem>
<para>If the hardware has a persistent MAC address, as
most hardware should, and if it is used by the kernel,
@ -220,7 +210,7 @@
</listitem>
</varlistentry>
<varlistentry>
<term><literal>random</literal></term>
<term><option>random</option></term>
<listitem>
<para>If the kernel is using a random MAC address,
nothing is done. Otherwise, a new address is randomly
@ -231,7 +221,7 @@
</listitem>
</varlistentry>
<varlistentry>
<term><literal>none</literal></term>
<term><option>none</option></term>
<listitem>
<para>Keeps the MAC address assigned by the kernel.</para>
</listitem>
@ -243,28 +233,23 @@
<term><varname>MACAddress=</varname></term>
<listitem>
<para>The MAC address to use, if no
<literal>MACAddressPolicy=</literal>
<varname>MACAddressPolicy=</varname>
is specified.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>NamePolicy=</varname></term>
<listitem>
<para>An ordered, space-separated list of policies by which
the interface name should be set.
<literal>NamePolicy</literal> may be disabled by specifying
<literal>net.ifnames=0</literal> on the kernel command line.
Each of the policies may fail, and the first successful one
is used. The name is 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>. If the name has already been set by
userspace, no renaming is performed. The available policies
are:</para>
<para>An ordered, space-separated list of policies by which the interface name should be set.
<varname>NamePolicy=</varname> may be disabled by specifying <option>net.ifnames=0</option> on the
kernel command line. Each of the policies may fail, and the first successful one is used. The name
is not set directly, but is exported to udev as the property <option>ID_NET_NAME</option>, which
is, by default, used by a udev rule to set <varname>NAME</varname>. The available policies are:
</para>
<variablelist>
<varlistentry>
<term><literal>kernel</literal></term>
<term><option>kernel</option></term>
<listitem>
<para>If the kernel claims that the name it has set
for a device is predictable, then no renaming is
@ -272,46 +257,53 @@
</listitem>
</varlistentry>
<varlistentry>
<term><literal>database</literal></term>
<term><option>database</option></term>
<listitem>
<para>The name is set based on entries in the udev's
Hardware Database with the key
<literal>ID_NET_NAME_FROM_DATABASE</literal>.
<varname>ID_NET_NAME_FROM_DATABASE</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>onboard</literal></term>
<term><option>onboard</option></term>
<listitem>
<para>The name is set based on information given by
the firmware for on-board devices, as exported by the
udev property <literal>ID_NET_NAME_ONBOARD</literal>.
udev property <varname>ID_NET_NAME_ONBOARD</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>slot</literal></term>
<term><option>slot</option></term>
<listitem>
<para>The name is set based on information given by
the firmware for hot-plug devices, as exported by the
udev property <literal>ID_NET_NAME_SLOT</literal>.
udev property <varname>ID_NET_NAME_SLOT</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>path</literal></term>
<term><option>path</option></term>
<listitem>
<para>The name is set based on the device's physical
location, as exported by the udev property
<literal>ID_NET_NAME_PATH</literal>.</para>
<varname>ID_NET_NAME_PATH</varname>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>mac</literal></term>
<term><option>mac</option></term>
<listitem>
<para>The name is set based on the device's persistent
MAC address, as exported by the udev property
<literal>ID_NET_NAME_MAC</literal>.</para>
<varname>ID_NET_NAME_MAC</varname>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>keep</option></term>
<listitem>
<para>If the device already had a name given by userspace (as part of creation of the device
or a rename), keep it.</para>
</listitem>
</varlistentry>
</variablelist>
@ -356,9 +348,8 @@
<varlistentry>
<term><varname>Duplex=</varname></term>
<listitem>
<para>The duplex mode to set for the device. The accepted
values are <literal>half</literal> and
<literal>full</literal>.</para>
<para>The duplex mode to set for the device. The accepted values are <option>half</option> and
<option>full</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -382,58 +373,58 @@
<variablelist>
<varlistentry>
<term><literal>phy</literal></term>
<term><option>phy</option></term>
<listitem>
<para>Wake on PHY activity.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>unicast</literal></term>
<term><option>unicast</option></term>
<listitem>
<para>Wake on unicast messages.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>multicast</literal></term>
<term><option>multicast</option></term>
<listitem>
<para>Wake on multicast messages.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>broadcast</literal></term>
<term><option>broadcast</option></term>
<listitem>
<para>Wake on broadcast messages.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>arp</literal></term>
<term><option>arp</option></term>
<listitem>
<para>Wake on ARP.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>magic</literal></term>
<term><option>magic</option></term>
<listitem>
<para>Wake on receipt of a magic packet.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>secureon</literal></term>
<term><option>secureon</option></term>
<listitem>
<para>Enable secureon(tm) password for MagicPacket(tm).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>off</literal></term>
<term><option>off</option></term>
<listitem>
<para>Never wake.</para>
</listitem>
</varlistentry>
</variablelist>
<para>Defaults to <literal>off</literal>.</para>
<para>Defaults to <option>off</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -444,32 +435,32 @@
<variablelist>
<varlistentry>
<term><literal>tp</literal></term>
<term><option>tp</option></term>
<listitem>
<para>An Ethernet interface using Twisted-Pair cable as the medium.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>aui</literal></term>
<term><option>aui</option></term>
<listitem>
<para>Attachment Unit Interface (AUI). Normally used with hubs.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>bnc</literal></term>
<term><option>bnc</option></term>
<listitem>
<para>An Ethernet interface using BNC connectors and co-axial cable.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>mii</literal></term>
<term><option>mii</option></term>
<listitem>
<para>An Ethernet interface using a Media Independent Interface (MII).</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>fibre</literal></term>
<term><option>fibre</option></term>
<listitem>
<para>An Ethernet interface using Optical Fibre as the medium.</para>
</listitem>
@ -496,47 +487,46 @@
<entry>Duplex Mode</entry>
</row></thead>
<tbody>
<row><entry><literal>10baset-half</literal></entry>
<row><entry><option>10baset-half</option></entry>
<entry>10</entry><entry>half</entry></row>
<row><entry><literal>10baset-full</literal></entry>
<row><entry><option>10baset-full</option></entry>
<entry>10</entry><entry>full</entry></row>
<row><entry><literal>100baset-half</literal></entry>
<row><entry><option>100baset-half</option></entry>
<entry>100</entry><entry>half</entry></row>
<row><entry><literal>100baset-full</literal></entry>
<row><entry><option>100baset-full</option></entry>
<entry>100</entry><entry>full</entry></row>
<row><entry><literal>1000baset-half</literal></entry>
<row><entry><option>1000baset-half</option></entry>
<entry>1000</entry><entry>half</entry></row>
<row><entry><literal>1000baset-full</literal></entry>
<row><entry><option>1000baset-full</option></entry>
<entry>1000</entry><entry>full</entry></row>
<row><entry><literal>10000baset-full</literal></entry>
<row><entry><option>10000baset-full</option></entry>
<entry>10000</entry><entry>full</entry></row>
<row><entry><literal>2500basex-full</literal></entry>
<row><entry><option>2500basex-full</option></entry>
<entry>2500</entry><entry>full</entry></row>
<row><entry><literal>1000basekx-full</literal></entry>
<row><entry><option>1000basekx-full</option></entry>
<entry>1000</entry><entry>full</entry></row>
<row><entry><literal>10000basekx4-full</literal></entry>
<row><entry><option>10000basekx4-full</option></entry>
<entry>10000</entry><entry>full</entry></row>
<row><entry><literal>10000basekr-full</literal></entry>
<row><entry><option>10000basekr-full</option></entry>
<entry>10000</entry><entry>full</entry></row>
<row><entry><literal>10000baser-fec</literal></entry>
<row><entry><option>10000baser-fec</option></entry>
<entry>10000</entry><entry>full</entry></row>
<row><entry><literal>20000basemld2-full</literal></entry>
<row><entry><option>20000basemld2-full</option></entry>
<entry>20000</entry><entry>full</entry></row>
<row><entry><literal>20000basekr2-full</literal></entry>
<row><entry><option>20000basekr2-full</option></entry>
<entry>20000</entry><entry>full</entry></row>
</tbody>
</tgroup>

View File

@ -8,5 +8,5 @@
# (at your option) any later version.
[Link]
NamePolicy=kernel database onboard slot path
NamePolicy=keep kernel database onboard slot path
MACAddressPolicy=persistent

View File

@ -11,6 +11,7 @@
#include "network-internal.h"
#include "siphash24.h"
#include "sparse-endian.h"
#include "stdio-util.h"
#include "virt.h"
#define SYSTEMD_PEN 43793
@ -169,10 +170,10 @@ int dhcp_identifier_set_iaid(
if (detect_container() <= 0) {
/* not in a container, udev will be around */
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
char ifindex_str[1 + DECIMAL_STR_MAX(int)];
int r;
sprintf(ifindex_str, "n%d", ifindex);
xsprintf(ifindex_str, "n%d", ifindex);
if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) {
r = sd_device_get_is_initialized(device);
if (r < 0)

View File

@ -41,6 +41,8 @@ libudev_core_sources = '''
net/link-config.h
net/ethtool-util.c
net/ethtool-util.h
net/naming-scheme.c
net/naming-scheme.h
'''.split()
if conf.get('HAVE_KMOD') == 1

View File

@ -14,6 +14,7 @@
#include "link-config.h"
#include "log.h"
#include "missing_network.h"
#include "naming-scheme.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "parse-util.h"
@ -186,6 +187,22 @@ static bool enable_name_policy(void) {
return proc_cmdline_get_bool("net.ifnames", &b) <= 0 || b;
}
static int link_name_type(sd_device *device, unsigned *type) {
const char *s;
int r;
r = sd_device_get_sysattr_value(device, "name_assign_type", &s);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to query name_assign_type: %m");
r = safe_atou(s, type);
if (r < 0)
return log_device_warning_errno(device, r, "Failed to parse name_assign_type \"%s\": %m", s);
log_device_debug(device, "Device has name_assign_type=%d", *type);
return 0;
}
int link_config_load(link_config_ctx *ctx) {
_cleanup_strv_free_ char **files;
char **f;
@ -296,31 +313,6 @@ static bool mac_is_random(sd_device *device) {
return type == NET_ADDR_RANDOM;
}
static bool should_rename(sd_device *device, bool respect_predictable) {
const char *s;
unsigned type;
int r;
/* if we can't get the assign type, assume we should rename */
if (sd_device_get_sysattr_value(device, "name_assign_type", &s) < 0)
return true;
r = safe_atou(s, &type);
if (r < 0)
return true;
switch (type) {
case NET_NAME_PREDICTABLE:
/* the kernel claims to have given a predictable name */
if (respect_predictable)
return false;
_fallthrough_;
default:
/* the name is known to be bad, or of an unknown type */
return true;
}
}
static int get_mac(sd_device *device, bool want_random,
struct ether_addr *mac) {
int r;
@ -347,12 +339,12 @@ static int get_mac(sd_device *device, bool want_random,
int link_config_apply(link_config_ctx *ctx, link_config *config,
sd_device *device, const char **name) {
bool respect_predictable = false;
struct ether_addr generated_mac;
struct ether_addr *mac = NULL;
const char *new_name = NULL;
const char *old_name;
unsigned speed;
unsigned speed, name_type = NET_NAME_UNKNOWN;
NamePolicy policy;
int r, ifindex;
assert(ctx);
@ -405,38 +397,63 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
if (r < 0)
return log_device_warning_errno(device, r, "Could not find ifindex: %m");
if (ctx->enable_name_policy && config->name_policy) {
NamePolicy *policy;
for (policy = config->name_policy;
!new_name && *policy != _NAMEPOLICY_INVALID; policy++) {
switch (*policy) {
case NAMEPOLICY_KERNEL:
respect_predictable = true;
break;
case NAMEPOLICY_DATABASE:
(void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name);
break;
case NAMEPOLICY_ONBOARD:
(void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name);
break;
case NAMEPOLICY_SLOT:
(void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name);
break;
case NAMEPOLICY_PATH:
(void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name);
break;
case NAMEPOLICY_MAC:
(void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name);
break;
default:
break;
}
}
(void) link_name_type(device, &name_type);
if (IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED)
&& !naming_scheme_has(NAMING_ALLOW_RERENAMES)) {
log_device_debug(device, "Device already has a name given by userspace, not renaming.");
goto no_rename;
}
if (!new_name && should_rename(device, respect_predictable))
if (ctx->enable_name_policy && config->name_policy)
for (NamePolicy *p = config->name_policy; !new_name && *p != _NAMEPOLICY_INVALID; p++) {
policy = *p;
switch (policy) {
case NAMEPOLICY_KERNEL:
if (name_type != NET_NAME_PREDICTABLE)
continue;
/* The kernel claims to have given a predictable name, keep it. */
log_device_debug(device, "Policy *%s*: keeping predictable kernel name",
name_policy_to_string(policy));
goto no_rename;
case NAMEPOLICY_KEEP:
if (!IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED))
continue;
log_device_debug(device, "Policy *%s*: keeping existing userspace name",
name_policy_to_string(policy));
goto no_rename;
case NAMEPOLICY_DATABASE:
(void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name);
break;
case NAMEPOLICY_ONBOARD:
(void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name);
break;
case NAMEPOLICY_SLOT:
(void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name);
break;
case NAMEPOLICY_PATH:
(void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name);
break;
case NAMEPOLICY_MAC:
(void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name);
break;
default:
assert_not_reached("invalid policy");
}
}
if (new_name)
log_device_debug(device, "Policy *%s* yields \"%s\".", name_policy_to_string(policy), new_name);
else if (config->name) {
new_name = config->name;
log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", new_name);
} else
log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming.");
no_rename:
switch (config->mac_policy) {
case MACPOLICY_PERSISTENT:
@ -495,7 +512,7 @@ int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret) {
static const char* const mac_policy_table[_MACPOLICY_MAX] = {
[MACPOLICY_PERSISTENT] = "persistent",
[MACPOLICY_RANDOM] = "random",
[MACPOLICY_NONE] = "none"
[MACPOLICY_NONE] = "none",
};
DEFINE_STRING_TABLE_LOOKUP(mac_policy, MACPolicy);
@ -504,11 +521,12 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_policy, mac_policy, MACPolicy,
static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
[NAMEPOLICY_KERNEL] = "kernel",
[NAMEPOLICY_KEEP] = "keep",
[NAMEPOLICY_DATABASE] = "database",
[NAMEPOLICY_ONBOARD] = "onboard",
[NAMEPOLICY_SLOT] = "slot",
[NAMEPOLICY_PATH] = "path",
[NAMEPOLICY_MAC] = "mac"
[NAMEPOLICY_MAC] = "mac",
};
DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);

View File

@ -22,6 +22,7 @@ typedef enum MACPolicy {
typedef enum NamePolicy {
NAMEPOLICY_KERNEL,
NAMEPOLICY_KEEP,
NAMEPOLICY_DATABASE,
NAMEPOLICY_ONBOARD,
NAMEPOLICY_SLOT,

View File

@ -0,0 +1,64 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h"
#include "naming-scheme.h"
#include "proc-cmdline.h"
#include "string-util.h"
static const NamingScheme naming_schemes[] = {
{ "v238", NAMING_V238 },
{ "v239", NAMING_V239 },
{ "v240", NAMING_V240 },
/* … add more schemes here, as the logic to name devices is updated … */
};
static const NamingScheme* naming_scheme_from_name(const char *name) {
size_t i;
if (streq(name, "latest"))
return naming_schemes + ELEMENTSOF(naming_schemes) - 1;
for (i = 0; i < ELEMENTSOF(naming_schemes); i++)
if (streq(naming_schemes[i].name, name))
return naming_schemes + i;
return NULL;
}
const NamingScheme* naming_scheme(void) {
static const NamingScheme *cache = NULL;
_cleanup_free_ char *buffer = NULL;
const char *e, *k;
if (cache)
return cache;
/* Acquire setting from the kernel command line */
(void) proc_cmdline_get_key("net.naming-scheme", 0, &buffer);
/* Also acquire it from an env var */
e = getenv("NET_NAMING_SCHEME");
if (e) {
if (*e == ':') {
/* If prefixed with ':' the kernel cmdline takes precedence */
k = buffer ?: e + 1;
} else
k = e; /* Otherwise the env var takes precedence */
} else
k = buffer;
if (k) {
cache = naming_scheme_from_name(k);
if (cache) {
log_info("Using interface naming scheme '%s'.", cache->name);
return cache;
}
log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k);
}
cache = naming_scheme_from_name(DEFAULT_NET_NAMING_SCHEME);
assert(cache);
log_info("Using default interface naming scheme '%s'.", cache->name);
return cache;
}

View File

@ -0,0 +1,48 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <stdbool.h>
#include "macro.h"
/* So here's the deal: net_id is supposed to be an excercise in providing stable names for network devices. However, we
* also want to keep updating the naming scheme used in future versions of net_id. These two goals of course are
* contradictory: on one hand we want things to not change and on the other hand we want them to improve. Our way out
* of this dilemma is to introduce the "naming scheme" concept: each time we improve the naming logic we define a new
* flag for it. Then, we keep a list of schemes, each identified by a name associated with the flags it implements. Via
* a kernel command line and environment variable we then allow the user to pick the scheme they want us to follow:
* installers could "freeze" the used scheme at the moment of installation this way.
*
* Developers: each time you tweak the naming logic here, define a new flag below, and condition the tweak with
* it. Each time we do a release we'll then add a new scheme entry and include all newly defined flags.
*
* Note that this is only half a solution to the problem though: not only udev/net_id gets updated all the time, the
* kernel gets too. And thus a kernel that previously didn't expose some sysfs attribute we look for might eventually
* do, and thus affect our naming scheme too. Thus, enforcing a naming scheme will make interfacing more stable across
* OS versions, but not fully stabilize them. */
typedef enum NamingSchemeFlags {
/* First, the individual features */
NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/
NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */
NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df887797c9e05074a562ddacdcdf5e */
NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Allow zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
NAMING_ALLOW_RERENAMES = 1 << 4, /* Allow re-renaming of devices, see #9006 */
/* And now the masks that combine the features above */
NAMING_V238 = 0,
NAMING_V239 = NAMING_V238 | NAMING_SR_IOV_V | NAMING_NPAR_ARI,
NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES,
_NAMING_SCHEME_FLAGS_INVALID = -1,
} NamingSchemeFlags;
typedef struct NamingScheme {
const char *name;
NamingSchemeFlags flags;
} NamingScheme;
const NamingScheme* naming_scheme(void);
static inline bool naming_scheme_has(NamingSchemeFlags flags) {
return FLAGS_SET(naming_scheme()->flags, flags);
}

View File

@ -106,6 +106,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "naming-scheme.h"
#include "parse-util.h"
#include "proc-cmdline.h"
#include "stdio-util.h"
@ -116,48 +117,6 @@
#define ONBOARD_INDEX_MAX (16*1024-1)
/* So here's the deal: net_id is supposed to be an excercise in providing stable names for network devices. However, we
* also want to keep updating the naming scheme used in future versions of net_id. These two goals of course are
* contradictory: on one hand we want things to not change and on the other hand we want them to improve. Our way out
* of this dilemma is to introduce the "naming scheme" concept: each time we improve the naming logic we define a new
* flag for it. Then, we keep a list of schemes, each identified by a name associated with the flags it implements. Via
* a kernel command line and environment variable we then allow the user to pick the scheme they want us to follow:
* installers could "freeze" the used scheme at the moment of installation this way.
*
* Developers: each time you tweak the naming logic here, define a new flag below, and condition the tweak with
* it. Each time we do a release we'll then add a new scheme entry and include all newly defined flags.
*
* Note that this is only half a solution to the problem though: not only udev/net_id gets updated all the time, the
* kernel gets too. And thus a kernel that previously didn't expose some sysfs attribute we look for might eventually
* do, and thus affect our naming scheme too. Thus, enforcing a naming scheme will make interfacing more stable across
* OS versions, but not fully stabilize them. */
typedef enum NamingSchemeFlags {
/* First, the individual features */
NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/
NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */
NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df887797c9e05074a562ddacdcdf5e */
NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Allow zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
/* And now the masks that combine the features above */
NAMING_V238 = 0,
NAMING_V239 = NAMING_V238|NAMING_SR_IOV_V|NAMING_NPAR_ARI,
NAMING_V240 = NAMING_V239|NAMING_INFINIBAND|NAMING_ZERO_ACPI_INDEX,
_NAMING_SCHEME_FLAGS_INVALID = -1,
} NamingSchemeFlags;
typedef struct NamingScheme {
const char *name;
NamingSchemeFlags flags;
} NamingScheme;
static const NamingScheme naming_schemes[] = {
{ "v238", NAMING_V238 },
{ "v239", NAMING_V239 },
{ "v240", NAMING_V240 },
/* … add more schemes here, as the logic to name devices is updated … */
};
enum netname_type{
NET_UNDEF,
NET_PCI,
@ -193,62 +152,6 @@ struct virtfn_info {
char suffix[IFNAMSIZ];
};
static const NamingScheme* naming_scheme_from_name(const char *name) {
size_t i;
if (streq(name, "latest"))
return naming_schemes + ELEMENTSOF(naming_schemes) - 1;
for (i = 0; i < ELEMENTSOF(naming_schemes); i++)
if (streq(naming_schemes[i].name, name))
return naming_schemes + i;
return NULL;
}
static const NamingScheme* naming_scheme(void) {
static const NamingScheme *cache = NULL;
_cleanup_free_ char *buffer = NULL;
const char *e, *k;
if (cache)
return cache;
/* Acquire setting from the kernel command line */
(void) proc_cmdline_get_key("net.naming-scheme", 0, &buffer);
/* Also acquire it from an env var */
e = getenv("NET_NAMING_SCHEME");
if (e) {
if (*e == ':') {
/* If prefixed with ':' the kernel cmdline takes precedence */
k = buffer ?: e + 1;
} else
k = e; /* Otherwise the env var takes precedence */
} else
k = buffer;
if (k) {
cache = naming_scheme_from_name(k);
if (cache) {
log_info("Using interface naming scheme '%s'.", cache->name);
return cache;
}
log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k);
}
cache = naming_scheme_from_name(DEFAULT_NET_NAMING_SCHEME);
assert(cache);
log_info("Using default interface naming scheme '%s'.", cache->name);
return cache;
}
static bool naming_scheme_has(NamingSchemeFlags flags) {
return FLAGS_SET(naming_scheme()->flags, flags);
}
/* skip intermediate virtio devices */
static sd_device *skip_virtio(sd_device *dev) {
sd_device *parent;

View File

@ -139,7 +139,7 @@ int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const
key, val ? "=" : "", strempty(val));
if (test)
printf("%s=%s\n", key, val);
printf("%s=%s\n", key, strempty(val));
return 0;
}