[pve-devel] [PATCH common] support for predictable network interface device names
Igor Vlasenko
ivlasenko at gmail.com
Thu May 12 10:42:29 CEST 2016
On Wed, May 11, 2016 at 10:56 PM, Igor Vlasenko <ivlasenko at gmail.com> wrote:
> This is an improved version of my previous patch
> [ support for udev-style physical interface names (like enp3s0),
> http://pve.proxmox.com/pipermail/pve-devel/2016-May/020958.html ]
> thanks to Wolfgang.
Yesterday I finished coding just before going to sleep, so I was a bit
muddleheaded and
left a few mistakes :( Here I fixed them and added a test case to verify.
Signed-off-by: Igor Vlasenko <viy at altlinux.org>
---
src/Makefile | 1 +
src/PVE/INotify.pm | 10 +++--
src/PVE/Network.pm | 7 ++-
src/PVE/NetworkInterfaces.pm | 50 ++++++++++++++++++++++
src/PVE/Tools.pm | 11 +++++
.../t.is_physical_interface.pl | 50 ++++++++++++++++++++++
6 files changed, 123 insertions(+), 6 deletions(-)
create mode 100644 src/PVE/NetworkInterfaces.pm
create mode 100644 test/etc_network_interfaces/t.is_physical_interface.pl
diff --git a/src/Makefile b/src/Makefile
index a07e2e4..02265e0 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -10,6 +10,7 @@ LIB_SOURCES= \
Daemon.pm \
SectionConfig.pm \
Network.pm \
+ NetworkInterfaces.pm \
ProcFSTools.pm \
CLIHandler.pm \
RESTHandler.pm \
diff --git a/src/PVE/INotify.pm b/src/PVE/INotify.pm
index 74a0fe1..ce83c16 100644
--- a/src/PVE/INotify.pm
+++ b/src/PVE/INotify.pm
@@ -14,6 +14,7 @@ use Fcntl qw(:DEFAULT :flock);
use PVE::SafeSyslog;
use PVE::Exception qw(raise_param_exc);
use PVE::Tools;
+use PVE::NetworkInterfaces;
use Storable qw(dclone);
use Linux::Inotify2;
use base 'Exporter';
@@ -800,7 +801,8 @@ sub __read_etc_network_interfaces {
if ($proc_net_dev) {
while (defined ($line = <$proc_net_dev>)) {
- if ($line =~ m/^\s*(eth\d+):.*/) {
+ if ($line =~ m/^\s*([^:]+):.*/
+ and PVE::NetworkInterfaces::is_physical_interface($1)) {
$ifaces->{$1}->{exists} = 1;
}
}
@@ -973,7 +975,7 @@ sub __read_etc_network_interfaces {
$ifaces->{$1}->{exists} = 0;
$d->{exists} = 0;
}
- } elsif ($iface =~ m/^eth\d+$/) {
+ } elsif (PVE::NetworkInterfaces::is_physical_interface($iface)) {
if (!$d->{ovs_type}) {
$d->{type} = 'eth';
} elsif ($d->{ovs_type} eq 'OVSPort') {
@@ -1200,7 +1202,7 @@ sub __write_etc_network_interfaces {
$d->{type} eq 'OVSBond') {
my $brname = $used_ports->{$iface};
if (!$brname || !$ifaces->{$brname}) {
- if ($iface =~ /^eth/) {
+ if (PVE::NetworkInterfaces::is_physical_interface($iface)) {
$ifaces->{$iface} = { type => 'eth',
exists => 1,
method => 'manual',
@@ -1289,7 +1291,7 @@ NETWORKDOC
my $pri;
if ($iface eq 'lo') {
$pri = $if_type_hash->{loopback};
- } elsif ($iface =~ m/^eth\d+$/) {
+ } elsif (PVE::NetworkInterfaces::is_physical_interface($iface)) {
$pri = $if_type_hash->{eth} + $child;
} elsif ($iface =~ m/^bond\d+$/) {
$pri = $if_type_hash->{bond} + $child;
diff --git a/src/PVE/Network.pm b/src/PVE/Network.pm
index be26132..1d15990 100644
--- a/src/PVE/Network.pm
+++ b/src/PVE/Network.pm
@@ -4,6 +4,7 @@ use strict;
use warnings;
use PVE::Tools qw(run_command);
use PVE::ProcFSTools;
+use PVE::NetworkInterfaces;
use PVE::INotify;
use File::Basename;
use IO::Socket::IP;
@@ -440,8 +441,10 @@ sub activate_bridge_vlan {
my @ifaces = ();
my $dir = "/sys/class/net/$bridge/brif";
- PVE::Tools::dir_glob_foreach($dir, '((eth|bond)\d+(\.\d+)?)', sub {
- push @ifaces, $_[0];
+ PVE::Tools::dir_lambda_foreach($dir, sub {
+ push @ifaces, $_[0] if $_[0] =~ /^(?:bond|eth)\d+(\.\d+)?/
+ or PVE::NetworkInterfaces::is_physical_interface($_[0]);
+ }
});
die "no physical interface on bridge '$bridge'\n" if scalar(@ifaces) == 0;
diff --git a/src/PVE/NetworkInterfaces.pm b/src/PVE/NetworkInterfaces.pm
new file mode 100644
index 0000000..80daf31
--- /dev/null
+++ b/src/PVE/NetworkInterfaces.pm
@@ -0,0 +1,50 @@
+package PVE::NetworkInterfaces;
+
+use strict;
+use warnings;
+
+# alternatively, on the linux kernel we can readlink /sys/class/net/$iface
+# and check whether it points to ../../devices/virtual/...
+
+# physical network interface pattern matching.
+# matching for predictable network interface device names is based on
+# https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-net_id.c
+# http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames
+sub is_physical_interface {
+ my ($iface) = @_;
+ return $iface =~
+ /^(?:
+ # legacy interface names
+ eth\d+
+
+ | # predictable network interface device names
+
+ # two character prefixes:
+ # en — Ethernet
+ # sl — serial line IP (slip)
+ # wl — wlan
+ # ww — wwan
+ (?:en|sl|wl|ww)
+
+ # type of names:
+ (?:
+ # b<number> — BCMA bus core number
+ b\d+
+ # c<bus_id> — CCW bus group name, without leading zeros [s390]
+ | c\d+
+ # o<index>[d<dev_port>] — on-board device index number
+ | o\d+(?:d\d+)?
+ # s<slot>[f<function>][d<dev_port>] — hotplug slot index number
+ | s\d+(?:f\d+)?(?:d\d+)?
+ # x<MAC> — MAC address
+ | x[\da-f]{12}
+ # [P<domain>]p<bus>s<slot>[f<function>][d<dev_port>] — PCI
geographical location
+ | (?:P\d+)?p\d+s\d+(?:f\d+)?(?:d\d+)?
+ # [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
— USB port number chain
+ | (?:P\d+)?p\d+s\d+(?:f\d+)?(?:u\d+)*(?:c\d+)?(?:i\d+)?
+ )
+ )$/x;
+}
+
+1;
+
diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm
index 8c7f373..24f0567 100644
--- a/src/PVE/Tools.pm
+++ b/src/PVE/Tools.pm
@@ -1125,6 +1125,17 @@ sub dir_glob_foreach {
}
}
+sub dir_lambda_foreach {
+ my ($dir, $func) = @_;
+
+ my $dh = IO::Dir->new ($dir);
+ if (defined $dh) {
+ while (defined(my $tmp = $dh->read)) {
+ &$func ($tmp);
+ }
+ }
+}
+
sub assert_if_modified {
my ($digest1, $digest2) = @_;
diff --git a/test/etc_network_interfaces/t.is_physical_interface.pl
b/test/etc_network_interfaces/t.is_physical_interface.pl
new file mode 100644
index 0000000..4518feb
--- /dev/null
+++ b/test/etc_network_interfaces/t.is_physical_interface.pl
@@ -0,0 +1,50 @@
+use lib '../../src';
+use PVE::NetworkInterfaces;
+
+map {die if PVE::NetworkInterfaces::is_physical_interface($_)} qw/
+wlan0 tap8 testiface4 br0 bond3
+/;
+
+map {die if! PVE::NetworkInterfaces::is_physical_interface($_)} qw/
+eth3 eno1 enp5s0 ens1 enx78e7d1ea46da enx000000000466 enp2s0f0
+enp2s0f1 wlx0024d7e31130 wlp3s0 wwx028037ec0200 wwp0s29u1u4i6
+enxd626b3450fb5 enp0s29u1u2
+/;
+
+
+1;
+
+__END__
+ * PCI Ethernet card with firmware index "1":
+ * ID_NET_NAME_ONBOARD=eno1
+ * ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
+ *
+ * PCI Ethernet card in hotplug slot with firmware index number:
+ * /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
+ * ID_NET_NAME_MAC=enx000000000466
+ * ID_NET_NAME_PATH=enp5s0
+ * ID_NET_NAME_SLOT=ens1
+ *
+ * PCI Ethernet multi-function card with 2 ports:
+ * /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0
+ * ID_NET_NAME_MAC=enx78e7d1ea46da
+ * ID_NET_NAME_PATH=enp2s0f0
+ * /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1
+ * ID_NET_NAME_MAC=enx78e7d1ea46dc
+ * ID_NET_NAME_PATH=enp2s0f1
+ *
+ * PCI wlan card:
+ * /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0
+ * ID_NET_NAME_MAC=wlx0024d7e31130
+ * ID_NET_NAME_PATH=wlp3s0
+ *
+ * USB built-in 3G modem:
+ * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6
+ * ID_NET_NAME_MAC=wwx028037ec0200
+ * ID_NET_NAME_PATH=wwp0s29u1u4i6
+ *
+ * USB Android phone:
+ * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2
+ * ID_NET_NAME_MAC=enxd626b3450fb5
+ * ID_NET_NAME_PATH=enp0s29u1u2
+ */
--
2.6.5
More information about the pve-devel
mailing list