summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.netdev.xml20
-rw-r--r--src/network/netdev/batadv.c1
-rw-r--r--src/network/netdev/bridge.c1
-rw-r--r--src/network/netdev/netdev-gperf.gperf4
-rw-r--r--src/network/netdev/netdev.c101
-rw-r--r--src/network/netdev/netdev.h4
-rw-r--r--src/network/netdev/veth.c2
7 files changed, 87 insertions, 46 deletions
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index 9cbd99a0ef..bd493a8c53 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -254,16 +254,22 @@
<varlistentry>
<term><varname>MACAddress=</varname></term>
<listitem>
- <para>The MAC address to use for the device. For <literal>tun</literal> or <literal>tap</literal>
- devices, setting <varname>MACAddress=</varname> in the [NetDev] section is not
- supported. Please specify it in the [Link] section of the corresponding
+ <para>Specifies the MAC address to use for the device, or takes the special value
+ <literal>none</literal>. When <literal>none</literal>, <command>systemd-networkd</command>
+ does not request the MAC address for the device, and the kernel will assign a random MAC
+ address. For <literal>tun</literal>, <literal>tap</literal>, or <literal>l2tp</literal>
+ devices, the <varname>MACAddress=</varname> setting in the [NetDev] section is not
+ supported and will be ignored. Please specify it in the [Link] section of the corresponding
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- file. If this option is not set, <literal>bridge</literal> and <literal>vlan</literal> devices
- inherit the MAC address of the first slave device or the physical interface, respectively. For other
- kind of netdevs, if this option is not set, then the MAC address is generated based on the interface
- name and the
+ file. If this option is not set, <literal>vlan</literal> device inherits the MAC address of
+ the master interface. For other kind of netdevs, if this option is not set, then the MAC
+ address is generated based on the interface name and the
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
+ <para>Note, even if <literal>none</literal> is specified, <command>systemd-udevd</command>
+ will assign the persistent MAC address for the device, as <filename>99-default.link</filename>
+ has <varname>MACAddressPolicy=persistent</varname>. So, it is also necessary to create a
+ custom .link file for the device, if the MAC address assignment is not desired.</para>
</listitem>
</varlistentry>
</variablelist>
diff --git a/src/network/netdev/batadv.c b/src/network/netdev/batadv.c
index f42f572a36..15f3aee3a6 100644
--- a/src/network/netdev/batadv.c
+++ b/src/network/netdev/batadv.c
@@ -203,4 +203,5 @@ const NetDevVTable batadv_vtable = {
.post_create = netdev_batadv_post_create,
.create_type = NETDEV_CREATE_MASTER,
.iftype = ARPHRD_ETHER,
+ .generate_mac = true,
};
diff --git a/src/network/netdev/bridge.c b/src/network/netdev/bridge.c
index 2d60e441ec..64d65493ca 100644
--- a/src/network/netdev/bridge.c
+++ b/src/network/netdev/bridge.c
@@ -278,4 +278,5 @@ const NetDevVTable bridge_vtable = {
.post_create = netdev_bridge_post_create,
.create_type = NETDEV_CREATE_MASTER,
.iftype = ARPHRD_ETHER,
+ .generate_mac = true,
};
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index d0f493b4ef..316592005f 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -49,7 +49,7 @@ NetDev.Description, config_parse_string,
NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname)
NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind)
NetDev.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(NetDev, mtu)
-NetDev.MACAddress, config_parse_hw_addr, ETH_ALEN, offsetof(NetDev, hw_addr)
+NetDev.MACAddress, config_parse_netdev_hw_addr, ETH_ALEN, offsetof(NetDev, hw_addr)
VLAN.Id, config_parse_vlanid, 0, offsetof(VLan, id)
VLAN.Protocol, config_parse_vlanprotocol, 0, offsetof(VLan, protocol)
VLAN.GVRP, config_parse_tristate, 0, offsetof(VLan, gvrp)
@@ -111,7 +111,7 @@ L2TPSession.PeerSessionId, config_parse_l2tp_session_id,
L2TPSession.Layer2SpecificHeader, config_parse_l2tp_session_l2spec, 0, 0
L2TPSession.Name, config_parse_l2tp_session_name, 0, 0
Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer)
-Peer.MACAddress, config_parse_hw_addr, ETH_ALEN, offsetof(Veth, hw_addr_peer)
+Peer.MACAddress, config_parse_netdev_hw_addr, ETH_ALEN, offsetof(Veth, hw_addr_peer)
VXCAN.Peer, config_parse_ifname, 0, offsetof(VxCan, ifname_peer)
VXLAN.VNI, config_parse_uint32, 0, offsetof(VxLan, vni)
VXLAN.Id, config_parse_uint32, 0, offsetof(VxLan, vni) /* deprecated */
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c
index 2fd2659ddb..5d88cbdf5f 100644
--- a/src/network/netdev/netdev.c
+++ b/src/network/netdev/netdev.c
@@ -128,41 +128,6 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
-int config_parse_netdev_kind(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- NetDevKind k, *kind = data;
-
- assert(rvalue);
- assert(data);
-
- k = netdev_kind_from_string(rvalue);
- if (k < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, k, "Failed to parse netdev kind, ignoring assignment: %s", rvalue);
- return 0;
- }
-
- if (*kind != _NETDEV_KIND_INVALID && *kind != k) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Specified netdev kind is different from the previous value '%s', ignoring assignment: %s",
- netdev_kind_to_string(*kind), rvalue);
- return 0;
- }
-
- *kind = k;
-
- return 0;
-}
-
bool netdev_is_managed(NetDev *netdev) {
if (!netdev || !netdev->manager || !netdev->ifname)
return false;
@@ -435,6 +400,9 @@ int netdev_generate_hw_addr(NetDev *netdev, const char *name, struct hw_addr_dat
assert(name);
assert(hw_addr);
+ if (hw_addr_equal(hw_addr, &HW_ADDR_NONE))
+ return 0;
+
if (hw_addr->length == 0) {
uint64_t result;
@@ -502,7 +470,7 @@ static int netdev_create(NetDev *netdev, Link *link, link_netlink_message_handle
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m");
- if (netdev->hw_addr.length > 0) {
+ if (netdev->hw_addr.length > 0 && !hw_addr_equal(&netdev->hw_addr, &HW_ADDR_NULL)) {
r = netlink_message_append_hw_addr(m, IFLA_ADDRESS, &netdev->hw_addr);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m");
@@ -886,3 +854,64 @@ int netdev_load(Manager *manager, bool reload) {
return 0;
}
+
+int config_parse_netdev_kind(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ NetDevKind k, *kind = data;
+
+ assert(filename);
+ assert(rvalue);
+ assert(data);
+
+ k = netdev_kind_from_string(rvalue);
+ if (k < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, k, "Failed to parse netdev kind, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ if (*kind != _NETDEV_KIND_INVALID && *kind != k) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Specified netdev kind is different from the previous value '%s', ignoring assignment: %s",
+ netdev_kind_to_string(*kind), rvalue);
+ return 0;
+ }
+
+ *kind = k;
+
+ return 0;
+}
+
+int config_parse_netdev_hw_addr(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ struct hw_addr_data *hw_addr = data;
+
+ assert(rvalue);
+ assert(data);
+
+ if (streq(rvalue, "none")) {
+ *hw_addr = HW_ADDR_NONE;
+ return 0;
+ }
+
+ return config_parse_hw_addr(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata);
+}
diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h
index d480d125a6..ed8a2e33c5 100644
--- a/src/network/netdev/netdev.h
+++ b/src/network/netdev/netdev.h
@@ -10,6 +10,9 @@
#include "networkd-link.h"
#include "time-util.h"
+/* Special hardware address value to suppress generating persistent hardware address for the netdev. */
+#define HW_ADDR_NONE ((struct hw_addr_data) { .length = 1, })
+
#define NETDEV_COMMON_SECTIONS "Match\0NetDev\0"
/* This is the list of known sections. We need to ignore them in the initial parsing phase. */
#define NETDEV_OTHER_SECTIONS \
@@ -215,6 +218,7 @@ static inline NetDevCreateType netdev_get_create_type(NetDev *netdev) {
}
CONFIG_PARSER_PROTOTYPE(config_parse_netdev_kind);
+CONFIG_PARSER_PROTOTYPE(config_parse_netdev_hw_addr);
/* gperf */
const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
diff --git a/src/network/netdev/veth.c b/src/network/netdev/veth.c
index f1c05c6205..d7870d7628 100644
--- a/src/network/netdev/veth.c
+++ b/src/network/netdev/veth.c
@@ -31,7 +31,7 @@ static int netdev_veth_fill_message_create(NetDev *netdev, Link *link, sd_netlin
return log_netdev_error_errno(netdev, r, "Failed to add netlink interface name: %m");
}
- if (v->hw_addr_peer.length > 0) {
+ if (v->hw_addr_peer.length > 0 && !hw_addr_equal(&v->hw_addr_peer, &HW_ADDR_NULL)) {
r = netlink_message_append_hw_addr(m, IFLA_ADDRESS, &v->hw_addr_peer);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m");