[netctl] Support custom MAC address on new interfaces

Message ID 20200320184114.GA3253@Mindship-03
State New
Headers show
Series [netctl] Support custom MAC address on new interfaces | expand

Commit Message

Emil Velikov via arch-projects March 20, 2020, 6:41 p.m. UTC
Connection types bond, bridge, dummy, vlan, and macvlan create their own
interface. Previously, only macvlan offered control over the MAC address of
the created interface. Now, this functionality is available to all these
connection types.
---
 docs/netctl.profile.5.txt   |  9 ++++++---
 src/lib/connections/bond    |  2 +-
 src/lib/connections/bridge  |  5 ++++-
 src/lib/connections/dummy   |  2 +-
 src/lib/connections/macvlan |  5 +----
 src/lib/connections/vlan    |  2 +-
 src/lib/interface           | 12 ++++++++----
 7 files changed, 22 insertions(+), 15 deletions(-)

Patch

diff --git a/docs/netctl.profile.5.txt b/docs/netctl.profile.5.txt
index 0662a67..839bb9a 100644
--- a/docs/netctl.profile.5.txt
+++ b/docs/netctl.profile.5.txt
@@ -83,6 +83,12 @@  GENERAL OPTIONS
     profile. If this variable is not specified, it defaults to the value
     of 'Interface='.
 
+'MACAddress='::
+    Optional MAC address for newly created interfaces. When set to the
+    name of an existing interface, the address of that interface is used.
+    The connection types that create an interface and are able to set a
+    MAC address are +bond+, +bridge+, +dummy+, +vlan+, and +macvlan+.
+
 'After=()'::
     An array of profile names that should be started before this profile
     is started. This is only an ordering dependency and is not intended
@@ -544,9 +550,6 @@  following are understood for connections of the `macvlan' type:
     Either `bridge', `vepa', `private', or `passthru'. See *ip*(8) for
     details.
 
-'MACAddress='::
-    Optional static MAC address for the `macvlan' type link.
-
 
 SPECIAL QUOTING RULES
 ---------------------
diff --git a/src/lib/connections/bond b/src/lib/connections/bond
index 64b0285..3f7daf4 100644
--- a/src/lib/connections/bond
+++ b/src/lib/connections/bond
@@ -11,7 +11,7 @@  bond_up() {
         return 1
     fi
 
-    interface_add bond "$Interface" "" ${Mode:+mode "$Mode"}
+    interface_add bond "$Interface" "$MACAddress" "" ${Mode:+mode "$Mode"}
     bring_interface_up "$Interface"
     for slave in "${BindsToInterfaces[@]}"; do
         ip link set dev "$slave" master "$Interface"
diff --git a/src/lib/connections/bridge b/src/lib/connections/bridge
index 7d05576..7f922fa 100644
--- a/src/lib/connections/bridge
+++ b/src/lib/connections/bridge
@@ -11,8 +11,11 @@  bridge_up() {
             report_error "Interface '$Interface' already exists and is not a bridge"
             return 1
         fi
+        if [[ "$MACAddress" ]]; then
+            report_error "Setting a MAC address on existing bridge interface '$Interface' is unsupported"
+        fi
     else
-        interface_add bridge "$Interface"
+        interface_add bridge "$Interface" "$MACAddress"
     fi
 
     for member in "${BindsToInterfaces[@]}"; do
diff --git a/src/lib/connections/dummy b/src/lib/connections/dummy
index 8726d86..7dd8e88 100644
--- a/src/lib/connections/dummy
+++ b/src/lib/connections/dummy
@@ -11,7 +11,7 @@  dummy_up() {
         return 1
     fi
 
-    interface_add dummy "$Interface"
+    interface_add dummy "$Interface" "$MACAddress"
     bring_interface_up "$Interface"
     ip_set
 }
diff --git a/src/lib/connections/macvlan b/src/lib/connections/macvlan
index 25a97fb..eadb477 100644
--- a/src/lib/connections/macvlan
+++ b/src/lib/connections/macvlan
@@ -15,10 +15,7 @@  macvlan_up() {
         return 1
     else
         bring_interface_up "$BindsToInterfaces"
-        interface_add macvlan "$Interface" "$BindsToInterfaces" mode "$Mode"
-        if [[ $MACAddress ]]; then
-            ip link set dev "$Interface" address "$MACAddress" || return 1
-        fi
+        interface_add macvlan "$Interface" "$MACAddress" "$BindsToInterfaces" mode "$Mode" || return 1
     fi
     ethernet_up
 }
diff --git a/src/lib/connections/vlan b/src/lib/connections/vlan
index 037c971..20251ec 100644
--- a/src/lib/connections/vlan
+++ b/src/lib/connections/vlan
@@ -15,7 +15,7 @@  vlan_up() {
         return 1
     else
         bring_interface_up "$BindsToInterfaces"
-        interface_add vlan "$Interface" "$BindsToInterfaces" id "$VLANID"
+        interface_add vlan "$Interface" "$MACAddress" "$BindsToInterfaces" id "$VLANID"
     fi
 
     ethernet_up
diff --git a/src/lib/interface b/src/lib/interface
index 2ebf81e..1a51c07 100644
--- a/src/lib/interface
+++ b/src/lib/interface
@@ -20,11 +20,15 @@  is_interface() {
 ## Add an interface
 # $1: interface type
 # $2: interface name
-# $3: interface link (optional)
-# $4...: additional arguments
+# $3: interface MAC address (optional)
+# $4: interface link (optional)
+# $5...: additional type related arguments
 interface_add() {
-    local type="$1" name="$2" link="$3"
-    do_debug ip link add ${link:+link "$link"} name "$name" type "$type" "${@:4}" $LinkOptions || return
+    local type="$1" name="$2" address="$3" link="$4"
+    if [[ -e "/sys/class/net/$address/address" ]]; then
+        address=$(< "/sys/class/net/$address/address")
+    fi
+    do_debug ip link add ${link:+link "$link"} name "$name" ${address:+address "$address"} type "$type" "${@:5}" $LinkOptions || return
     load_interface_config "$name"
 }