[pve-devel] [PATCH common] Fix #882: active state of interfaces depends on ipv6
Wolfgang Bumiller
w.bumiller at proxmox.com
Fri Feb 5 08:50:57 CET 2016
read_etc_network_interfaces uses the content of
/proc/net/if_inet6 to decide whether an interface's state is
"active", which means an interface is only active when it
has an ipv6 address, thus using net.ipv6.conf.*.disable_ipv6
on an interface will cause it to show as inactive in the web
interface.
Fix this by instead listing the interfaces in /sys/class/net
which have an 'operstate' of "up" or "unknown".
"unknown" because an active tap or tun device usually shows
up as 'unknown' even when it's working and has addresses
assigned.
---
src/PVE/INotify.pm | 21 ++++++++-------------
src/PVE/Network.pm | 13 +++++++++++++
test/etc_network_interfaces/active_interfaces | 3 +++
test/etc_network_interfaces/proc_net_if_inet6 | 3 ---
test/etc_network_interfaces/runtest.pl | 11 +++++------
5 files changed, 29 insertions(+), 22 deletions(-)
create mode 100644 test/etc_network_interfaces/active_interfaces
delete mode 100644 test/etc_network_interfaces/proc_net_if_inet6
diff --git a/src/PVE/INotify.pm b/src/PVE/INotify.pm
index 6cec84b..74a0fe1 100644
--- a/src/PVE/INotify.pm
+++ b/src/PVE/INotify.pm
@@ -785,12 +785,12 @@ my $extract_ovs_option = sub {
sub read_etc_network_interfaces {
my ($filename, $fh) = @_;
my $proc_net_dev = IO::File->new('/proc/net/dev', 'r');
- my $proc_net_if_inet6 = IO::File->new('/proc/net/if_inet6', 'r');
- return __read_etc_network_interfaces($fh, $proc_net_dev, $proc_net_if_inet6);
+ my $active = PVE::Network::get_active_interfaces();
+ return __read_etc_network_interfaces($fh, $proc_net_dev, $active);
}
sub __read_etc_network_interfaces {
- my ($fh, $proc_net_dev, $proc_net_if_inet6) = @_;
+ my ($fh, $proc_net_dev, $active_ifaces) = @_;
my $config = {};
my $ifaces = $config->{ifaces} = {};
@@ -905,7 +905,11 @@ sub __read_etc_network_interfaces {
}
}
-
+ foreach my $ifname (@$active_ifaces) {
+ if (my $iface = $ifaces->{$ifname}) {
+ $iface->{active} = 1;
+ }
+ }
if (!$ifaces->{lo}) {
$ifaces->{lo}->{priority} = 1;
@@ -997,15 +1001,6 @@ sub __read_etc_network_interfaces {
$d->{families} ||= ['inet'];
}
- if ($proc_net_if_inet6) {
- while (defined ($line = <$proc_net_if_inet6>)) {
- if ($line =~ m/^[a-f0-9]{32}\s+[a-f0-9]{2}\s+[a-f0-9]{2}\s+[a-f0-9]{2}\s+[a-f0-9]{2}\s+(\S+)$/) {
- $ifaces->{$1}->{active} = 1 if defined($ifaces->{$1});
- }
- }
- close ($proc_net_if_inet6);
- }
-
# OVS bridges create "allow-$BRIDGE $IFACE" lines which we need to remove
# from the {options} hash for them to be removed correctly.
@$options = grep {defined($_)} map {
diff --git a/src/PVE/Network.pm b/src/PVE/Network.pm
index 8cfac0d..b7935b1 100644
--- a/src/PVE/Network.pm
+++ b/src/PVE/Network.pm
@@ -514,4 +514,17 @@ sub is_ip_in_cidr {
return $cidr_obj->overlaps($ip_obj) == $Net::IP::IP_B_IN_A_OVERLAP;
}
+sub get_active_interfaces {
+ my $ifaces = [];
+ foreach my $if (</sys/class/net/*>) {
+ my $state = PVE::Tools::file_read_firstline("$if/operstate");
+ # possible values: (see linux/Documentation/ABI/testing/sysfs-class-net):
+ # [unknown, notpresent, down, lowerlayerdown, testing, dormant, up]
+ # We include unknown as some devices (eg. tun/tap) can be up and
+ # assinged addresses while showing an unknown state.
+ push @$ifaces, substr($if, 15) if $state =~ /^(?:up | unknown)$/x;
+ }
+ return $ifaces;
+}
+
1;
diff --git a/test/etc_network_interfaces/active_interfaces b/test/etc_network_interfaces/active_interfaces
new file mode 100644
index 0000000..dd3634d
--- /dev/null
+++ b/test/etc_network_interfaces/active_interfaces
@@ -0,0 +1,3 @@
+lo
+eth0
+vmbr0
diff --git a/test/etc_network_interfaces/proc_net_if_inet6 b/test/etc_network_interfaces/proc_net_if_inet6
deleted file mode 100644
index 441e1d2..0000000
--- a/test/etc_network_interfaces/proc_net_if_inet6
+++ /dev/null
@@ -1,3 +0,0 @@
-00000000000000000000000000000001 01 80 10 80 lo
-fe80000000000000ae9e17fffe846a7a 03 40 20 80 vmbr0
-fc050000000000000000000010000001 03 70 00 80 vmbr0
diff --git a/test/etc_network_interfaces/runtest.pl b/test/etc_network_interfaces/runtest.pl
index ba26dcd..92cd7f8 100755
--- a/test/etc_network_interfaces/runtest.pl
+++ b/test/etc_network_interfaces/runtest.pl
@@ -59,16 +59,15 @@ sub flush_files() {
## Interface parsing:
##
-# Read an interfaces file with optional /proc/net/dev and /proc/net/if_inet6
-# file content strings, which default to the provided ones.
+# Read an interfaces file with optional /proc/net/dev file content string and
+# the list of active interfaces, which otherwise default
sub r($;$$) {
- my ($ifaces, $proc_net_dev, $proc_net_if_inet6) = @_;
+ my ($ifaces, $proc_net_dev, $active) = @_;
$proc_net_dev //= load('proc_net_dev');
- $proc_net_if_inet6 //= load('proc_net_if_inet6');
+ $active //= [split(/\s+/, load('active_interfaces'))];
open my $fh1, '<', \$ifaces;
open my $fh2, '<', \$proc_net_dev;
- open my $fh3, '<', \$proc_net_if_inet6;
- $config = PVE::INotify::__read_etc_network_interfaces($fh1, $fh2, $fh3);
+ $config = PVE::INotify::__read_etc_network_interfaces($fh1, $fh2, $active);
close $fh1;
}
--
2.1.4
More information about the pve-devel
mailing list