[pve-devel] [PATCH common] support for predictable network interface device names
Igor Vlasenko
ivlasenko at gmail.com
Wed May 11 21:56:01 CEST 2016
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.
The resulting regex is large, so it is wrapped as a common subroutine.
Signed-off-by: Igor Vlasenko <viy at altlinux.org>
---
src/Makefile | 1 +
src/PVE/INotify.pm | 10 +++++----
src/PVE/Network.pm | 7 +++++--
src/PVE/NetworkInterface.pm | 49 +++++++++++++++++++++++++++++++++++++++++++++
src/PVE/Tools.pm | 11 ++++++++++
5 files changed, 72 insertions(+), 6 deletions(-)
create mode 100644 src/PVE/NetworkInterface.pm
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/NetworkInterface.pm b/src/PVE/NetworkInterface.pm
new file mode 100644
index 0000000..1c7dcc5
--- /dev/null
+++ b/src/PVE/NetworkInterface.pm
@@ -0,0 +1,49 @@
+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;
+}
+
+__END__
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) = @_;
--
2.6.5
More information about the pve-devel
mailing list