Commit 1f5ff983 authored by David Johnson's avatar David Johnson

Improve docker clientside net setup: hold global lock less.

Prior to this commit, I had reused all the libvnode:: network functions,
but that requires these system-wide indexes to be built (i.e. bridges,
ifaces) before using the helpers -- and on any network state change.
Those indexing functions take a long time on heavily-loaded systems
(i.e., 5k processes, hundreds of ifaces).  The helpers become very fast;
but for the case of large numbers of vnodes on one vhost, it is better
to hold the global lock for less time, and pay a higher per-helper cost,
instead of making use of a nicely-indexed cache.

So now we cache nothing and (hopefully) use /sys intelligently to avoid
forking unnecessarily.
parent 01ec4a98
#!/usr/bin/perl -wT
#
# Copyright (c) 2008-2017 University of Utah and the Flux Group.
# Copyright (c) 2008-2018 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -28,7 +28,7 @@ use Exporter;
@ISA = "Exporter";
@EXPORT = qw( makeIfaceMaps makeBridgeMaps makeMacvlanMaps
findControlNet existsIface findIface findMac getIfaceInfo
existsBridge findBridge findBridgeIfaces
getIfaceInfoNoCache existsBridge findBridge findBridgeIfaces
existsMacvlanParent findMacvlanParent findMacvlanIfaces
downloadImage getKernelVersion createExtraFS
forwardPort removePortForward lvSize lvExists
......@@ -475,48 +475,16 @@ sub makeIfaceMaps()
# open. The only reason we'll fail to open here is if the device
# has gone away after the initial dir listing.
#
open(FD,"/sys/class/net/$iface/address")
or next;
my $mac = <FD>;
close(FD);
next if (!defined($mac) || $mac eq '');
$mac =~ s/://g;
chomp($mac);
$mac = lc($mac);
my $ifinfo = getIfaceInfoNoCache($iface);
next
if (!defined($ifinfo));
my ($mac,$ip) = ($ifinfo->{'mac'},$ifinfo->{'ip'});
$if2info{$iface} = $ifinfo;
$if2mac{$iface} = $mac;
$mac2if{$mac} = $iface;
$if2info{$iface} = { 'mac' => $mac, 'iface' => $iface };
# also find ip, ugh
my $pip = `ip addr show dev $iface | grep 'inet '`;
chomp($pip);
if ($pip =~ /^\s+inet\s+(\d+\.\d+\.\d+\.\d+)\/(\d+)/) {
my $ip = $1;
$ip2if{$ip} = $iface;
my @ip = split(/\./,$ip);
my $bits = int($2);
my @netmask = (0,0,0,0);
my ($idx,$counter) = (0,8);
for (my $i = $bits; $i > 0; --$i) {
--$counter;
$netmask[$idx] += 2 ** $counter;
if ($counter == 0) {
$counter = 8;
++$idx;
}
}
my @network = ($ip[0] & $netmask[0],$ip[1] & $netmask[1],
$ip[2] & $netmask[2],$ip[3] & $netmask[3]);
$ip2net{$ip} = join('.',@network);
$ip2mask{$ip} = join('.',@netmask);
$ip2maskbits{$ip} = $bits;
$if2info{$iface}->{'ip'} = $ip;
$if2info{$iface}->{'network'} = $ip2net{$ip};
$if2info{$iface}->{'mask'} = $ip2mask{$ip};
$if2info{$iface}->{'maskbits'} = $ip2maskbits{$ip};
}
$ip2net{$ip} = $if2info->{'network'};
$ip2mask{$ip} = $if2info->{'mask'};
$ip2maskbits{$ip} = $if2info->{'maskbits'};
}
if ($debug > 1) {
......@@ -577,6 +545,54 @@ sub findIface($) {
return undef;
}
sub getIfaceInfoNoCache($) {
my ($iface) = @_;
my $ret = {};
open(FD,"/sys/class/net/$iface/address")
or return undef;
my $mac = <FD>;
close(FD);
return undef
if (!defined($mac) || $mac eq '');
$mac =~ s/://g;
chomp($mac);
$mac = lc($mac);
$ret = { 'mac' => $mac, 'iface' => $iface };
# Find IP info
my $pip = `ip addr show dev $iface | grep 'inet '`;
chomp($pip);
if ($pip =~ /^\s+inet\s+(\d+\.\d+\.\d+\.\d+)\/(\d+)/) {
my $ip = $1;
$ip2if{$ip} = $iface;
my @ip = split(/\./,$ip);
my $bits = int($2);
my @netmask = (0,0,0,0);
my ($idx,$counter) = (0,8);
for (my $i = $bits; $i > 0; --$i) {
--$counter;
$netmask[$idx] += 2 ** $counter;
if ($counter == 0) {
$counter = 8;
++$idx;
}
}
my @network = ($ip[0] & $netmask[0],$ip[1] & $netmask[1],
$ip[2] & $netmask[2],$ip[3] & $netmask[3]);
$ret->{'network'} = join('.',@network);
$ret->{'mask'} = join('.',@netmask);
$ret->{'maskbits'} = $bits;
$ret->{'ip'} = $ip;
}
else {
return undef;
}
return $ret;
}
#
# Returns a dict of iface, mac[, ip, network, mask, maskbits], if the
# supplied iface exists. The IPv4 info is only included if it exists.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment