appear, which affects older name derivation algorithms, too.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>net.ifname-policy=<replaceable>policy1</replaceable>[,<replaceable>policy2</replaceable>,…][,<replaceable>MAC</replaceable>]</varname></term>
+ <listitem>
+ <para>Specifies naming policies applied when renaming network interfaces. Takes a list of
+ policies and an optional MAC address separated with comma. Each policy value must be one of
+ the policies understood by the <varname>NamePolicy=</varname> setting in .link files, e.g.
+ <literal>onboard</literal> or <literal>path</literal>. See
+ <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for more details. When the MAC address is specified, the policies are applied to the
+ interface which has the address. When no MAC address is specified, the policies are applied
+ to all interfaces. This kernel command line argument can be specified multiple times. This
+ argument is not directly read from <command>systemd-udevd</command>, but read and converted
+ to a .link file by <command>systemd-network-generator</command>. So, to make this argument
+ take effect, <filename>systemd-network-generator.service</filename> must be enabled and
+ started before starting <filename>systemd-udevd.service</filename>. See
+ <citerefentry><refentrytitle>systemd-network-generator.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for more details about the service.</para>
+ <para>Example:
+ <programlisting>net.ifname-policy=keep,kernel,path,slot,onboard,01:23:45:67:89:ab
+net.ifname-policy=keep,kernel,path,slot,onboard,mac</programlisting>
+ This is mostly equivalent to creating the following .link files:
+ <programlisting># 91-name-policy-with-mac.link
+[Match]
+MACAddress=01:23:45:67:89:ab
+
+[Link]
+NamePolicy=keep kernel path slot onboard
+AlternativeNamePolicy=path slot onboard</programlisting>
+ and
+ <programlisting># 92-name-policy-for-all.link
+[Match]
+OriginalName=*
+
+[Link]
+NamePolicy=keep kernel path slot onboard mac
+AlternativeNamePolicy=path slot onboard mac</programlisting>
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
<!-- when adding entries here, consider also adding them in kernel-command-line.xml -->
</refsect1>
#include "hostname-util.h"
#include "log.h"
#include "macro.h"
+#include "netif-naming-scheme.h"
#include "network-generator.h"
#include "parse-util.h"
#include "proc-cmdline.h"
# .link
ifname=<interface>:<MAC>
+ net.ifname-policy=policy1[,policy2,...][,<MAC>] # This is an original rule, not supported by other tools.
# .netdev
vlan=<vlanname>:<phydevice>
if (!link)
return NULL;
+ free(link->filename);
free(link->ifname);
+ strv_free(link->policies);
+ strv_free(link->alt_policies);
return mfree(link);
}
Link **ret) {
_cleanup_(link_freep) Link *link = NULL;
- _cleanup_free_ char *ifname = NULL;
+ _cleanup_free_ char *ifname = NULL, *filename = NULL;
int r;
assert(context);
+ assert(mac);
- if (!ifname_valid(name))
- return -EINVAL;
+ if (name) {
+ if (!ifname_valid(name))
+ return -EINVAL;
- ifname = strdup(name);
- if (!ifname)
- return -ENOMEM;
+ ifname = strdup(name);
+ if (!ifname)
+ return -ENOMEM;
+
+ filename = strdup(name);
+ if (!filename)
+ return -ENOMEM;
+ }
+
+ if (!filename) {
+ filename = strdup(hw_addr_is_null(mac) ? "default" :
+ HW_ADDR_TO_STR_FULL(mac, HW_ADDR_TO_STRING_NO_COLON));
+ if (!filename)
+ return -ENOMEM;
+ }
link = new(Link, 1);
if (!link)
return -ENOMEM;
*link = (Link) {
+ .filename = TAKE_PTR(filename),
.ifname = TAKE_PTR(ifname),
.mac = *mac,
};
- r = hashmap_ensure_put(&context->links_by_name, &string_hash_ops, link->ifname, link);
+ r = hashmap_ensure_put(&context->links_by_filename, &string_hash_ops, link->filename, link);
if (r < 0)
return r;
return 0;
}
-Link *link_get(Context *context, const char *ifname) {
- return hashmap_get(context->links_by_name, ifname);
+Link *link_get(Context *context, const char *filename) {
+ assert(context);
+ assert(filename);
+ return hashmap_get(context->links_by_filename, filename);
}
static int network_set_dhcp_type(Context *context, const char *ifname, const char *dhcp_type) {
return link_new(context, name, &mac, NULL);
}
+static int parse_cmdline_ifname_policy(Context *context, const char *key, const char *value) {
+ _cleanup_strv_free_ char **policies = NULL, **alt_policies = NULL;
+ struct hw_addr_data mac = HW_ADDR_NULL;
+ Link *link;
+ int r;
+
+ /* net.ifname-policy=policy1[,policy2,...][,<MAC>] */
+
+ if (proc_cmdline_value_missing(key, value))
+ return -EINVAL;
+
+ for (const char *q = value; ; ) {
+ _cleanup_free_ char *word = NULL;
+ NamePolicy p;
+
+ r = extract_first_word(&q, &word, ",", 0);
+ if (r == 0)
+ break;
+ if (r < 0)
+ return r;
+
+ p = name_policy_from_string(word);
+ if (p < 0) {
+ r = parse_hw_addr(word, &mac);
+ if (r < 0)
+ return r;
+
+ if (hw_addr_is_null(&mac))
+ return -EINVAL;
+
+ if (!isempty(q))
+ return -EINVAL;
+
+ break;
+ }
+
+ if (alternative_names_policy_from_string(word) >= 0) {
+ r = strv_extend(&alt_policies, word);
+ if (r < 0)
+ return r;
+ }
+
+ r = strv_consume(&policies, TAKE_PTR(word));
+ if (r < 0)
+ return r;
+ }
+
+ if (strv_isempty(policies))
+ return -EINVAL;
+
+ r = link_new(context, NULL, &mac, &link);
+ if (r < 0)
+ return r;
+
+ link->policies = TAKE_PTR(policies);
+ link->alt_policies = TAKE_PTR(alt_policies);
+ return 0;
+}
+
int parse_cmdline_item(const char *key, const char *value, void *data) {
Context *context = data;
return parse_cmdline_bond(context, key, value);
if (streq(key, "ifname"))
return parse_cmdline_ifname(context, key, value);
+ if (streq(key, "net.ifname-policy"))
+ return parse_cmdline_ifname_policy(context, key, value);
return 0;
}
hashmap_free_with_destructor(context->networks_by_name, network_free);
hashmap_free_with_destructor(context->netdevs_by_name, netdev_free);
- hashmap_free_with_destructor(context->links_by_name, link_free);
+ hashmap_free_with_destructor(context->links_by_filename, link_free);
}
static int address_dump(Address *address, FILE *f) {
if (!hw_addr_is_null(&link->mac))
fprintf(f, "MACAddress=%s\n", HW_ADDR_TO_STR(&link->mac));
+ else
+ fputs("OriginalName=*\n", f);
- fprintf(f,
- "\n[Link]\n"
- "Name=%s\n",
- link->ifname);
+ fputs("\n[Link]\n", f);
+
+ if (!isempty(link->ifname))
+ fprintf(f, "Name=%s\n", link->ifname);
+
+ if (!strv_isempty(link->policies)) {
+ fputs("NamePolicy=", f);
+ fputstrv(f, link->policies, " ", NULL);
+ fputc('\n', f);
+ }
+
+ if (!strv_isempty(link->alt_policies)) {
+ fputs("AlternativeNamesPolicy=", f);
+ fputstrv(f, link->alt_policies, " ", NULL);
+ fputc('\n', f);
+ }
}
int network_format(Network *network, char **ret) {