Commit ecb66ab5 authored by Leigh B. Stoller's avatar Leigh B. Stoller
Browse files

Add a "regression" mode to both the old assign_wrapper and the new

mapper wrapper. In regression mode, the wrapper/mapper proceeds
normally, creating a .vtop file, and then running assign with a fixed
seed. If the wrapper and the mapper agree on the .vtop file, then the
solution from assign should be identical.

The wrapper/mapper then proceeds normally, reserving resources and
making all the DB changes. Needless to say, this has to be on a
private copy of the database, with all nodes free. Creating that DB
was a tale in its own right.

At completion, call the existing BackupPhysicalState() function that
we use in swapmod, and write all the physical tables we have changed
(just the rows corresponding to the experiment of course). The delete
all that state, and free the nodes.

If everything is working correctly, those physical tables should be
identical when created by the mapper or the wrapper.

Of course, its not quite there yet. I have a few things to fix up
before diff -r produces no results.
parent 5f5452e1
...@@ -44,6 +44,7 @@ sub array_diff($$); ...@@ -44,6 +44,7 @@ sub array_diff($$);
sub LoadCurrent(); sub LoadCurrent();
sub SetUpTracing($$$$$); sub SetUpTracing($$$$$);
sub fatal(@); sub fatal(@);
sub FinalizeRegression($);
# #
# This function as the main assign loop. It converts the virtual # This function as the main assign loop. It converts the virtual
...@@ -84,19 +85,22 @@ sub usage () ...@@ -84,19 +85,22 @@ sub usage ()
"implies -n\n"; "implies -n\n";
exit($WRAPPER_FAILED); exit($WRAPPER_FAILED);
} }
my $optlist = "vutnfp"; my $optlist = "vutnfpr";
my $verbose = 0; my $verbose = 0;
my $fixmode = 0; my $fixmode = 0;
my $updating = 0; my $updating = 0;
my $toponly = 0; my $toponly = 0;
my $impotent = 0; my $impotent = 0;
my $precheck = 0; my $precheck = 0;
my $regression=0;
my $warnings = 0; my $warnings = 0;
# #
# Configure variables # Configure variables
# #
my $TBROOT = "@prefix@"; my $TBROOT = "@prefix@";
my $NFREE = "$TBROOT/bin/nfree";
my $DBNAME = "@TBDBNAME@";
my $DELAYCAPACITY = @DELAYCAPACITY@; # Can be overridden by user! my $DELAYCAPACITY = @DELAYCAPACITY@; # Can be overridden by user!
$ENV{'PATH'} = "/usr/bin:$TBROOT/libexec:$TBROOT/sbin:$TBROOT/bin"; $ENV{'PATH'} = "/usr/bin:$TBROOT/libexec:$TBROOT/sbin:$TBROOT/bin";
...@@ -178,14 +182,20 @@ if (defined($options{"p"})) { ...@@ -178,14 +182,20 @@ if (defined($options{"p"})) {
if (defined($options{"f"})) { if (defined($options{"f"})) {
$fixmode = 1; $fixmode = 1;
} }
if (defined($options{"r"})) {
if ($DBNAME eq "tbdb") {
fatal("Cannot use regression mode on main DB");
}
$regression = 1;
}
my $pid = $ARGV[0]; my $pid = $ARGV[0];
my $eid = $ARGV[1]; my $eid = $ARGV[1];
my $ptopfile = "$pid-$eid-$$.ptop"; my $ptopfile = ($regression ? "$pid-$eid.ptop" : "$pid-$eid-$$.ptop");
# Since the topfile could change across # Since the topfile could change across
# swapins and modifies, it makes sense # swapins and modifies, it makes sense
# to store all of them. Helps in # to store all of them. Helps in
# degugging. # degugging.
my $topfile = "$pid-$eid-$$.top"; my $topfile = ($regression ? "$pid-$eid.top" : "$pid-$eid-$$.top");
TBDebugTimeStampsOn(); TBDebugTimeStampsOn();
...@@ -816,7 +826,7 @@ TBDebugTimeStamp("TOP started"); ...@@ -816,7 +826,7 @@ TBDebugTimeStamp("TOP started");
# #
# Do admission control test right away. # Do admission control test right away.
# #
if (!$toponly) { if (!($toponly || $regression)) {
fatal("Failed admission control checks!") fatal("Failed admission control checks!")
if (!TBAdmissionControlCheck(undef, $experiment, \%admission_control)); if (!TBAdmissionControlCheck(undef, $experiment, \%admission_control));
} }
...@@ -838,12 +848,19 @@ LoadPhysInfo(); ...@@ -838,12 +848,19 @@ LoadPhysInfo();
# #
LoadExperiment(); LoadExperiment();
if ($regression) {
print STDERR "Freeing reserved nodes in regression mode\n";
system("export NORELOAD=1; $NFREE -x -a $pid $eid") == 0
or fatal("Could not release nodes in regression mode");
}
# #
# If updating, load current experiment resources. We have to be careful # If updating, load current experiment resources. We have to be careful
# of how this is merged in with the (new) desired topology. See below. # of how this is merged in with the (new) desired topology. See below.
# #
if ($updating) { if ($updating || $regression) {
LoadCurrent(); LoadCurrent()
if ($updating);
print STDERR "Resetting DB before updating.\n"; print STDERR "Resetting DB before updating.\n";
$experiment->RemovePhysicalState(); $experiment->RemovePhysicalState();
} }
...@@ -907,6 +924,11 @@ while (1) { ...@@ -907,6 +924,11 @@ while (1) {
last last
if ($retval == 0); if ($retval == 0);
if ($regression) {
FinalizeRegression(1);
fatal("Failed to find solution in regression mode");
}
if (!$precheck && !$tried_precheck) { if (!$precheck && !$tried_precheck) {
my $ptopfile0 = $ptopfile; my $ptopfile0 = $ptopfile;
my $impotent0 = $impotent; my $impotent0 = $impotent;
...@@ -1017,6 +1039,8 @@ sub RunAssign () ...@@ -1017,6 +1039,8 @@ sub RunAssign ()
if ($virtcount || $simcount); if ($virtcount || $simcount);
$cmdargs = "-n $cmdargs" $cmdargs = "-n $cmdargs"
if ($precheck); if ($precheck);
$cmdargs = "-s 123456 $cmdargs"
if ($regression);
my $cmd; my $cmd;
...@@ -1091,7 +1115,8 @@ sub RunAssign () ...@@ -1091,7 +1115,8 @@ sub RunAssign ()
# for debugging and archiving purposes # for debugging and archiving purposes
# We do not call it .log though, since we do not want it copied # We do not call it .log though, since we do not want it copied
# out to the user directory every swapin. See Experiment.pm # out to the user directory every swapin. See Experiment.pm
system("/bin/cp assign.log $pid-$eid-$$.assign"); my $assignlog = ($regression ? "$pid-$eid.assign" : "$pid-$eid-$$.assign");
system("/bin/cp assign.log $assignlog");
if (!open(ASSIGNFP, "assign.log")) { if (!open(ASSIGNFP, "assign.log")) {
print("Could not open assign logfile!\n"); print("Could not open assign logfile!\n");
return -1; return -1;
...@@ -2279,85 +2304,6 @@ PatchVirts(); ...@@ -2279,85 +2304,6 @@ PatchVirts();
exit(0) exit(0)
if ($impotent); if ($impotent);
#
# Seed the virt_agents table. This should probably be done elsewhere.
# Anyway, each lan/link needs an agent to handle changes to delays or
# other link parameters, and that agent (might be several) will be
# running on more than one node. Delay node agent, wireless agent,
# etc. They might be running on a node different then where the link
# is really (delay node). So, just send all link event to all nodes,
# and let them figure out what they should do (what to ignore, what to
# act on). So, specify a wildcard; a "*" for the vnode will be treated
# specially by the event scheduler, and no ipaddr will be inserted
# into the event. Second, add pseudo agents, one for each member of
# the link (or just one if a lan). The objname is lan-vnode, and
# allows us to send an event to just the agent controlling that link
# (or lan node delay). The agents will subscribe to these additional
# names when they start up.
#
# Must clean these to avoid duplicates.
DBQueryFatal("delete from event_groups ".
"where pid='$pid' and eid='$eid' and ".
" (group_name='__all_lans' or group_name='__all_tracemon')");
foreach my $lan (keys(%virt_lans)) {
DBQueryFatal("replace into virt_agents ".
" (exptidx, pid, eid, vname, vnode, objecttype) ".
" select '$experiment_idx', '$pid', '$eid', '$lan', '*', ".
" idx from event_objecttypes where ".
" event_objecttypes.type='LINK'");
#
# XXX there is no link (delay) agent running on plab nodes
# (i.e., protocol==ipv4) currently, so we cannot be sending them
# events that they will not acknowledge.
#
if (virtlanprotocol($lan) ne "ipv4") {
DBQueryFatal("insert into event_groups ".
" (exptidx, pid, eid, idx, group_name, agent_name) ".
" values ('$experiment_idx', ".
" '$pid', '$eid', NULL, '__all_lans', '$lan')");
}
# Must clean these to avoid duplicates created by the loop below.
DBQueryFatal("delete from event_groups ".
"where pid='$pid' and eid='$eid' and ".
" group_name='${lan}-tracemon'");
# Must clean these cause of how this code used to work; temporary.
DBQueryFatal("delete from virt_agents ".
"where pid='$pid' and eid='$eid' and ".
" vname='${lan}-tracemon'");
foreach my $member (virtlanmembers($lan)) {
my ($vnode) = split(":", $member);
DBQueryFatal("replace into virt_agents ".
" (exptidx, pid, eid, vname, vnode, objecttype) ".
" select '$experiment_idx', '$pid', '$eid', ".
" '${lan}-${vnode}', '*', ".
" idx from event_objecttypes where ".
" event_objecttypes.type='LINK'");
DBQueryFatal("replace into virt_agents ".
" (exptidx, pid, eid, vname, vnode, objecttype) ".
" select '$experiment_idx', '$pid', '$eid', ".
" '${lan}-${vnode}-tracemon', '*', ".
" idx from event_objecttypes where ".
" event_objecttypes.type='LINKTRACE'");
DBQueryFatal("insert into event_groups ".
" (exptidx, pid, eid, idx, group_name, agent_name) ".
" values ('$experiment_idx', '$pid', '$eid', NULL, ".
" '__all_tracemon', '${lan}-${vnode}-tracemon')");
DBQueryFatal("insert into event_groups ".
" (exptidx, pid, eid, idx, group_name, agent_name) ".
" values ('$experiment_idx', '$pid', '$eid', NULL, ".
" '${lan}-tracemon','${lan}-${vnode}-tracemon')");
}
}
# #
# Enter delays. # Enter delays.
# #
...@@ -2968,6 +2914,8 @@ if( $simcount > 0 ) { ...@@ -2968,6 +2914,8 @@ if( $simcount > 0 ) {
} }
TBDebugTimeStamp("assign_wrapper finished"); TBDebugTimeStamp("assign_wrapper finished");
FinalizeRegression(0)
if ($regression);
exit(0); exit(0);
###################################################################### ######################################################################
...@@ -5418,7 +5366,7 @@ sub CreateTopFile() ...@@ -5418,7 +5366,7 @@ sub CreateTopFile()
$maximum_nodes = $physnode_count + keys(%delaynodes); $maximum_nodes = $physnode_count + keys(%delaynodes);
$minimum_nodes = POSIX::ceil($minimum_nodes); $minimum_nodes = POSIX::ceil($minimum_nodes);
if (! $impotent) { if (! ($impotent || $regression)) {
DBQueryFatal("UPDATE experiments set maximum_nodes=$maximum_nodes, " . DBQueryFatal("UPDATE experiments set maximum_nodes=$maximum_nodes, " .
" minimum_nodes=$minimum_nodes ". " minimum_nodes=$minimum_nodes ".
"where pid='$pid' and eid='$eid'"); "where pid='$pid' and eid='$eid'");
...@@ -5715,6 +5663,39 @@ sub nodejailosid($) ...@@ -5715,6 +5663,39 @@ sub nodejailosid($)
return $nextosid; return $nextosid;
} }
#
# In regression mode we want to save the physical state and then clear
# the physical resources.
#
sub FinalizeRegression($)
{
my ($error) = @_;
my $cwd;
chomp($cwd = `/bin/pwd`);
if (!$error) {
print STDERR "Saving physical state in regression mode\n";
if ($experiment->BackupPhysicalState("$cwd/$pid-$eid.pstate") != 0) {
print STDERR "Could not save physical state!\n";
exit(1);
}
}
print STDERR "Removing physical state in regression mode\n";
if ($experiment->RemovePhysicalState() != 0) {
print STDERR "Could not remove physical state!\n";
exit(1);
}
if (scalar(keys(%newreservednodes))) {
my @nodeids = keys(%newreservednodes);
system("export NORELOAD=1; $NFREE -x $pid $eid @nodeids");
if ($?) {
exit(1);
}
}
return 0;
}
# #
# All exits happen via this function! # All exits happen via this function!
# #
......
...@@ -10,7 +10,8 @@ use strict; ...@@ -10,7 +10,8 @@ use strict;
use Exporter; use Exporter;
use vars qw(@ISA @EXPORT @EXPORT_OK use vars qw(@ISA @EXPORT @EXPORT_OK
$VTOP_FLAGS_UPDATE $VTOP_FLAGS_VERBOSE $VTOP_FLAGS_UPDATE $VTOP_FLAGS_VERBOSE
$VTOP_FLAGS_FIXNODES $VTOP_FLAGS_IMPOTENT); $VTOP_FLAGS_FIXNODES $VTOP_FLAGS_IMPOTENT
$VTOP_FLAGS_REGRESSION);
@ISA = "Exporter"; @ISA = "Exporter";
@EXPORT = qw( ); @EXPORT = qw( );
...@@ -34,6 +35,9 @@ use XML::LibXML; ...@@ -34,6 +35,9 @@ use XML::LibXML;
my $TB = "@prefix@"; my $TB = "@prefix@";
my $BOSSNODE = "@BOSSNODE@"; my $BOSSNODE = "@BOSSNODE@";
my $AVAIL = "$TB/bin/avail"; my $AVAIL = "$TB/bin/avail";
my $NALLOC = "$TB/bin/nalloc";
my $NFREE = "$TB/bin/nfree";
my $OS_SELECT = "$TB/bin/os_select";
my $DELAYCAPACITY = @DELAYCAPACITY@; # Can be overridden by user! my $DELAYCAPACITY = @DELAYCAPACITY@; # Can be overridden by user!
my $DELAYTHRESH = @DELAYTHRESH@; my $DELAYTHRESH = @DELAYTHRESH@;
...@@ -42,9 +46,10 @@ $VTOP_FLAGS_VERBOSE = 0x01; ...@@ -42,9 +46,10 @@ $VTOP_FLAGS_VERBOSE = 0x01;
$VTOP_FLAGS_UPDATE = 0x02; $VTOP_FLAGS_UPDATE = 0x02;
$VTOP_FLAGS_FIXNODES = 0x04; $VTOP_FLAGS_FIXNODES = 0x04;
$VTOP_FLAGS_IMPOTENT = 0x08; $VTOP_FLAGS_IMPOTENT = 0x08;
$VTOP_FLAGS_REGRESSION = 0x10;
@EXPORT_OK = qw($VTOP_FLAGS_UPDATE $VTOP_FLAGS_VERBOSE $VTOP_FLAGS_FIXNODES @EXPORT_OK = qw($VTOP_FLAGS_UPDATE $VTOP_FLAGS_VERBOSE $VTOP_FLAGS_FIXNODES
$VTOP_FLAGS_IMPOTENT); $VTOP_FLAGS_IMPOTENT $VTOP_FLAGS_REGRESSION);
# #
# Create an object representing the stuff we need to create the vtop file. # Create an object representing the stuff we need to create the vtop file.
...@@ -122,7 +127,7 @@ sub current_v2v($) { return $_[0]->{'CURRENT_V2V'}; } ...@@ -122,7 +127,7 @@ sub current_v2v($) { return $_[0]->{'CURRENT_V2V'}; }
sub pnodes($) { return $_[0]->{'PNODES'}; } sub pnodes($) { return $_[0]->{'PNODES'}; }
sub fixednodes($) { return $_[0]->{'FIXEDNODES'}; } sub fixednodes($) { return $_[0]->{'FIXEDNODES'}; }
sub newreserved($) { return $_[0]->{'NEWRESERVED'}; } sub newreserved($) { return $_[0]->{'NEWRESERVED'}; }
sub newreservednodes($) { return @{ $_[0]->{'NEWRESERVED'} }; } sub newreservednodes($) { return keys(%{ $_[0]->{'NEWRESERVED'} }); }
sub norecover($) { return $_[0]->{'norecover'}; } sub norecover($) { return $_[0]->{'norecover'}; }
sub pid($) { return $_[0]->experiment()->pid(); } sub pid($) { return $_[0]->experiment()->pid(); }
sub pid_idx($) { return $_[0]->experiment()->pid_idx(); } sub pid_idx($) { return $_[0]->experiment()->pid_idx(); }
...@@ -151,6 +156,7 @@ sub verbose($) { return $_[0]->flags() & $VTOP_FLAGS_VERBOSE; } ...@@ -151,6 +156,7 @@ sub verbose($) { return $_[0]->flags() & $VTOP_FLAGS_VERBOSE; }
sub updating($) { return $_[0]->flags() & $VTOP_FLAGS_UPDATE; } sub updating($) { return $_[0]->flags() & $VTOP_FLAGS_UPDATE; }
sub fixcurrent($) { return $_[0]->flags() & $VTOP_FLAGS_FIXNODES; } sub fixcurrent($) { return $_[0]->flags() & $VTOP_FLAGS_FIXNODES; }
sub impotent($) { return $_[0]->flags() & $VTOP_FLAGS_IMPOTENT; } sub impotent($) { return $_[0]->flags() & $VTOP_FLAGS_IMPOTENT; }
sub regression($) { return $_[0]->flags() & $VTOP_FLAGS_REGRESSION; }
sub printdb($$) { print $_[1] if ($_[0]->verbose()); } sub printdb($$) { print $_[1] if ($_[0]->verbose()); }
# We name delay nodes internally as they are needed. # We name delay nodes internally as they are needed.
...@@ -285,7 +291,8 @@ sub Create($$$$) ...@@ -285,7 +291,8 @@ sub Create($$$$)
$self->{'VIRTLANLAN'} = $virt_lanlan; $self->{'VIRTLANLAN'} = $virt_lanlan;
$self->{'VTOP'} = $vtop; $self->{'VTOP'} = $vtop;
$self->{'MEMBERS'} = {}; $self->{'MEMBERHASH'} = {};
$self->{'MEMBERLIST'} = [];
$self->{'SHAPEDMEMBERS'} = {}; $self->{'SHAPEDMEMBERS'} = {};
$self->{'HASH'} = {}; $self->{'HASH'} = {};
...@@ -293,8 +300,8 @@ sub Create($$$$) ...@@ -293,8 +300,8 @@ sub Create($$$$)
} }
# accessors # accessors
sub virt_lanlan($) { return $_[0]->{'VIRTLANLAN'}; } sub virt_lanlan($) { return $_[0]->{'VIRTLANLAN'}; }
sub members($) { return $_[0]->{'MEMBERS'}; } sub members($) { return $_[0]->{'MEMBERHASH'}; }
sub memberlist($) { return values(%{ $_[0]->members() }); } sub memberlist($) { return @{ $_[0]->{'MEMBERLIST'} }; }
sub shapedmembers($) { return $_[0]->{'SHAPEDMEMBERS'}; } sub shapedmembers($) { return $_[0]->{'SHAPEDMEMBERS'}; }
sub vtop($) { return $_[0]->{'VTOP'}; } sub vtop($) { return $_[0]->{'VTOP'}; }
sub hash($) { return $_[0]->{'HASH'}; } sub hash($) { return $_[0]->{'HASH'}; }
...@@ -304,7 +311,8 @@ sub DESTROY { ...@@ -304,7 +311,8 @@ sub DESTROY {
my $self = shift; my $self = shift;
$self->{'VIRTLANLAN'} = undef; $self->{'VIRTLANLAN'} = undef;
$self->{'MEMBERS'} = undef; $self->{'MEMBERHASH'} = undef;
$self->{'MEMBERLIST'} = undef;
$self->{'VTOP'} = undef; $self->{'VTOP'} = undef;
$self->{'HASH'} = undef; $self->{'HASH'} = undef;
} }
...@@ -317,6 +325,16 @@ sub Stringify($) ...@@ -317,6 +325,16 @@ sub Stringify($)
return "[vlan:$vname]"; return "[vlan:$vname]";
} }
sub addmember($$)
{
my ($self, $vlanmember) = @_;
$self->members()->{$vlanmember->member()} = $vlanmember;
push(@{ $self->{'MEMBERLIST'} }, $vlanmember);
return 0;
}
# #
# Other support functions. # Other support functions.
# #
...@@ -467,7 +485,7 @@ sub LoadPhysInfo($) ...@@ -467,7 +485,7 @@ sub LoadPhysInfo($)
while (my ($iface_type, $node_type) = $query_result->fetchrow()) { while (my ($iface_type, $node_type) = $query_result->fetchrow()) {
my $typeinfo = NodeType->Lookup($node_type); my $typeinfo = NodeType->Lookup($node_type);
if (!defined($typeinfo)) { if (!defined($typeinfo)) {
carp("No type info for node type $node_type"); warn("No type info for node type $node_type\n");
return -1; return -1;
} }
my $node_class = $typeinfo->class(); my $node_class = $typeinfo->class();
...@@ -478,7 +496,7 @@ sub LoadPhysInfo($) ...@@ -478,7 +496,7 @@ sub LoadPhysInfo($)
if (!defined($node_type_linkbw{$node_class})); if (!defined($node_type_linkbw{$node_class}));
if (!defined($interface_capabilities{$iface_type}->{"protocols"})) { if (!defined($interface_capabilities{$iface_type}->{"protocols"})) {
carp("No protocols listed in capabilities for $iface_type!"); warn("No protocols listed in capabilities for $iface_type!\n");
return -1; return -1;
} }
my @protolist = my @protolist =
...@@ -489,7 +507,7 @@ sub LoadPhysInfo($) ...@@ -489,7 +507,7 @@ sub LoadPhysInfo($)
$interface_capabilities{$iface_type}->{"${proto}_defspeed"}; $interface_capabilities{$iface_type}->{"${proto}_defspeed"};
if (!defined($def_speed)) { if (!defined($def_speed)) {
carp("No default speed in capabilites for $iface_type!"); warn("No default speed in capabilites for $iface_type!\n");
return -1; return -1;
} }
...@@ -658,7 +676,7 @@ sub LoadVirtNodes($) ...@@ -658,7 +676,7 @@ sub LoadVirtNodes($)
if (!defined($nodetype)) { if (!defined($nodetype)) {
my $vtype = $self->virttypeisvtype($type); my $vtype = $self->virttypeisvtype($type);
if (!defined($vtype)) { if (!defined($vtype)) {
carp("Improper type $type for node $vnode!"); warn("Improper type $type for node $vnode!\n");
return -1; return -1;
} }
# #
...@@ -669,7 +687,7 @@ sub LoadVirtNodes($) ...@@ -669,7 +687,7 @@ sub LoadVirtNodes($)
$nodetype = NodeType->LookupAny($vtypename); $nodetype = NodeType->LookupAny($vtypename);
if (!defined($nodetype)) { if (!defined($nodetype)) {
carp("Improper type $vtypename in vtypes for node $vnode!"); warn("Improper type $vtypename in vtypes for node $vnode!\n");
return -1; return -1;
} }
$isvtyped = 1; $isvtyped = 1;
...@@ -718,7 +736,7 @@ sub LoadVirtNodes($) ...@@ -718,7 +736,7 @@ sub LoadVirtNodes($)
# Must be a parent. Set in the parser, either explicitly, or else # Must be a parent. Set in the parser, either explicitly, or else
# one is created if the user leaves it out. # one is created if the user leaves it out.
if (!defined($fixed) || $fixed eq "") { if (!defined($fixed) || $fixed eq "") {
carp("Subnode $vname must be fixed to its parent!"); warn("Subnode $vname must be fixed to its parent!\n");
return -1; return -1;
} }
$vnode->_parent($fixed); $vnode->_parent($fixed);
...@@ -853,7 +871,7 @@ sub LoadVirtLans($) ...@@ -853,7 +871,7 @@ sub LoadVirtLans($)
# Which we add to the member hash for the lan by vnode:vport # Which we add to the member hash for the lan by vnode:vport
# Note that $vlanmember->member() returns vnode:port. # Note that $vlanmember->member() returns vnode:port.
$virtlan->members()->{$vlanmember->member()} = $vlanmember; $virtlan->addmember($vlanmember);
# Global map from vnode:port back to the lan object # Global map from vnode:port back to the lan object
$self->memberof()->{$vlanmember->member()} = $virtlan; $self->memberof()->{$vlanmember->member()} = $virtlan;
...@@ -862,10 +880,12 @@ sub LoadVirtLans($) ...@@ -862,10 +880,12 @@ sub LoadVirtLans($)
my $delay = $vlanmember->delay(); my $delay = $vlanmember->delay();
my $bandwidth = $vlanmember->bandwidth(); my $bandwidth = $vlanmember->bandwidth();
my $est_bandwidth = $vlanmember->est_bandwidth(); my $est_bandwidth = $vlanmember->est_bandwidth();
my $backfill = $vlanmember->backfill();
my $lossrate = $vlanmember->lossrate(); my $lossrate = $vlanmember->lossrate();
my $rdelay = $vlanmember->rdelay(); my $rdelay = $vlanmember->rdelay();
my $rbandwidth = $vlanmember->rbandwidth(); my $rbandwidth = $vlanmember->rbandwidth();
my $rest_bandwidth = $vlanmember->rest_bandwidth(); my $rest_bandwidth = $vlanmember->rest_bandwidth();
my $rbackfill = $vlanmember->rbackfill();
my $rlossrate = $vlanmember->rlossrate(); my $rlossrate = $vlanmember->rlossrate();
my $widearea = $vlanmember->widearea(); my $widearea = $vlanmember->widearea();
my $isemulated = $vlanmember->emulated(); my $isemulated = $vlanmember->emulated();
...@@ -919,10 +939,12 @@ sub LoadVirtLans($) ...@@ -919,10 +939,12 @@ sub LoadVirtLans($)
$vlanmember->_delayinfo([ $delay, $vlanmember->_delayinfo([ $delay,
$bandwidth, $bandwidth,
$est_bandwidth, $est_bandwidth,
$backfill,
$lossrate, $lossrate,
$rdelay, $rdelay,
$rbandwidth, $rbandwidth,
$rest_bandwidth, $rest_bandwidth,
$rbackfill,
$rlossrate ]); $rlossrate ]);
# #
...@@ -1522,18 +1544,22 @@ sub GenVirtLans($) ...@@ -1522,18 +1544,22 @@ sub GenVirtLans($)
my $vname0 = $virtnode0->vname(); my $vname0 = $virtnode0->vname();
my $vname1 = $virtnode1->vname(); my $vname1 = $virtnode1->vname();
my ($delay0,$bw0,$ebw0,$loss0, my ($delay0,$bw0,$ebw0,$backfill0,$loss0,
$rdelay0,$rbw0,$rebw0,$rloss0) = @{$member0->_delayinfo()}; $rdelay0,$rbw0,$rebw0,$rbackfill0,$rloss0) =
my ($delay1,$bw1,$ebw1,$loss1, @{$member0->_delayinfo()};
$rdelay1,$rbw1,$rebw1,$rloss1) = @{$member1->_delayinfo()};