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 #!/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 # {{{EMULAB-LICENSE
# #
...@@ -28,7 +28,7 @@ use Exporter; ...@@ -28,7 +28,7 @@ use Exporter;
@ISA = "Exporter"; @ISA = "Exporter";
@EXPORT = qw( makeIfaceMaps makeBridgeMaps makeMacvlanMaps @EXPORT = qw( makeIfaceMaps makeBridgeMaps makeMacvlanMaps
findControlNet existsIface findIface findMac getIfaceInfo findControlNet existsIface findIface findMac getIfaceInfo
existsBridge findBridge findBridgeIfaces getIfaceInfoNoCache existsBridge findBridge findBridgeIfaces
existsMacvlanParent findMacvlanParent findMacvlanIfaces existsMacvlanParent findMacvlanParent findMacvlanIfaces
downloadImage getKernelVersion createExtraFS downloadImage getKernelVersion createExtraFS
forwardPort removePortForward lvSize lvExists forwardPort removePortForward lvSize lvExists
...@@ -475,48 +475,16 @@ sub makeIfaceMaps() ...@@ -475,48 +475,16 @@ sub makeIfaceMaps()
# open. The only reason we'll fail to open here is if the device # open. The only reason we'll fail to open here is if the device
# has gone away after the initial dir listing. # has gone away after the initial dir listing.
# #
open(FD,"/sys/class/net/$iface/address") my $ifinfo = getIfaceInfoNoCache($iface);
or next; next
my $mac = <FD>; if (!defined($ifinfo));
close(FD); my ($mac,$ip) = ($ifinfo->{'mac'},$ifinfo->{'ip'});
next if (!defined($mac) || $mac eq ''); $if2info{$iface} = $ifinfo;
$mac =~ s/://g;
chomp($mac);
$mac = lc($mac);
$if2mac{$iface} = $mac; $if2mac{$iface} = $mac;
$mac2if{$mac} = $iface; $mac2if{$mac} = $iface;
$if2info{$iface} = { 'mac' => $mac, 'iface' => $iface }; $ip2net{$ip} = $if2info->{'network'};
$ip2mask{$ip} = $if2info->{'mask'};
# also find ip, ugh $ip2maskbits{$ip} = $if2info->{'maskbits'};
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};
}
} }
if ($debug > 1) { if ($debug > 1) {
...@@ -577,6 +545,54 @@ sub findIface($) { ...@@ -577,6 +545,54 @@ sub findIface($) {
return undef; 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 # Returns a dict of iface, mac[, ip, network, mask, maskbits], if the
# supplied iface exists. The IPv4 info is only included if it exists. # 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