Commit f6e3d3aa authored by David Johnson's avatar David Johnson
Browse files

MLE: set port speeds for non user-specified segment/path endpoint interfaces.

We now make a pass through the implemented_by tree setting port speeds
that the user left up to assign (i.e., that are 0).  We start at the
lowest level links and assign default speeds.  Then the speed values for
the start and end segments for each path get propagated to the link
being implemented by the path.  Should be pretty generic for any number
of layers.  We warn if the higher level links don't support those speed
settings (if they don't, we're gonna have a problem; but I think assign
protects this from happening).
parent b1fd6bdc
......@@ -6997,6 +6997,212 @@ sub UploadVlans($)
}
}
}
#
# MLE: make a pass through the implemented_by tree setting port speeds
# that the user left up to assign (i.e., that are 0). We start at the
# lowest level links and assign default speeds. Then we propagate those
# speeds up to higher level links, and warn the user if the higher level
# links don't support those speed settings (if they don't, we're gonna
# have a problem :)).
#
$self->printdb("Setting speeds for MLE virtlans...\n");
my @mlevlans = ();
foreach my $virtlan (values(%{ $self->vlans() })) {
next
if (!($virtlan->_implemented_by() || $virtlan->_vpath()));
if ($virtlan->_vpath()) {
$virtlan->_vpath()->_pathspeed0(0);
$virtlan->_vpath()->_pathspeed1(0);
}
push @mlevlans, $virtlan;
}
$self->printdb("mle virtlans: ".join(" ",@mlevlans)."\n");
while (@mlevlans) {
mleagain:
my $virtlan = shift @mlevlans;
# If it's a lan implemented by a path, we need to derive speeds from
# the path endpoints.
my $vpath;
if (defined($vpath = $virtlan->_implemented_by())) {
if ($vpath->_pathspeed0() == 0 || $vpath->_pathspeed1() == 0) {
$self->printdb("mlevlanspeed: delaying $virtlan until its" .
" vpath $vpath is processed\n");
push @mlevlans, $virtlan;
goto mleagain;
}
}
else {
$vpath = $virtlan->_vpath();
}
#
# Handle a virtlan (whether it's a path segment or a link implemented
# by a path -- we handle each case a little differently below):
#
my $protolink = ProtoLan->Lookup($self->experiment(),
$virtlan->vname());
my $lan = Lan->Lookup($self->experiment()->idx(),
$virtlan->vname());
my ($member0,$member1) = $virtlan->memberlist();
my ($iface0,$iface1,$pnode0,$pnode1);
if ($protolink->IfaceList() != 0) {
($iface0,$iface1,$pnode0,$pnode1) =
($protolink->{"IFACES"}->{$member0}->{"iface"},
$protolink->{"IFACES"}->{$member1}->{"iface"},
$protolink->{"IFACES"}->{$member0}->{"node"},
$protolink->{"IFACES"}->{$member1}->{"node"});
}
else {
$self->printdb("ERROR: is $protolink a protovlan?!\n");
return -1;
}
my $member0if = $protolink->{"IFACES"}->{$member0};
my $member1if = $protolink->{"IFACES"}->{$member1};
my ($cs_member0,$cs_member1) = (0,0);
if (defined($member0if->{"attrs"})
&& exists($member0if->{"attrs"}->{"current_speed"})) {
$cs_member0 = $member0if->{"attrs"}->{"current_speed"};
}
if (defined($member1if->{"attrs"})
&& exists($member1if->{"attrs"}->{"current_speed"})) {
$cs_member1 = $member1if->{"attrs"}->{"current_speed"};
}
if ($virtlan->_implemented_by()) {
$self->printdb("mlevlanspeed: $virtlan (implemented by $vpath):" .
" $member0 ($pnode0,$iface0,$cs_member0)" .
" $member1 ($pnode1,$iface1,$cs_member1)\n");
}
else {
$self->printdb("mlevlanspeed: vpath $vpath segment $virtlan:" .
" $member0 ($pnode0,$iface0,$cs_member0)" .
" $member1 ($pnode1,$iface1,$cs_member1)\n");
}
my $interface0 = Interface->LookupByIface($pnode0,$iface0);
my $interface1 = Interface->LookupByIface($pnode1,$iface1);
my ($speed0,$speed1);
if ((!exists($self->portbw()->{$member0})
|| $self->portbw()->{$member0} == 0)
&& $cs_member0 == 0) {
#
# Figure out the default speed if this is a path segment;
# otherwise inherit from the path.
#
if ($virtlan->_implemented_by()) {
$speed0 = $vpath->_pathspeed0();
}
else {
$speed0 =
$self->interfacespeedmbps($interface0->type(),"ethernet");
}
$self->printdb("Setting ifacebw: $pnode0:$iface0 $speed0\n");
#
# Save it off for later rounds of this loop for possible reference
#
$member0if->{"attrs"}->{"current_speed"} = $speed0;
#
# Upload it if we're not impotent or alloconly
#
if (!($self->impotent() || $self->alloconly())) {
$interface0->Update({'current_speed' => $speed0 });
}
}
else {
$speed0 = (exists($self->portbw()->{$member0})
&& $self->portbw()->{$member0}) ?
$self->portbw()->{$member0} / 1000 :
$cs_member0;
#
# Sanity check: did somebody set a speed already (user or previous
# current_speed attribute from an AddInterface call), and does it
# not match what the underlying path thinks it should be?
#
if ($virtlan->_implemented_by()
&& $virtlan->_vpath()->_pathspeed0() ne $speed0) {
print STDERR "mlevlanspeed: preset link speed disagreed with" .
" implementing start path segment!";
return -1;
}
}
if ((!exists($self->portbw()->{$member1})
|| $self->portbw()->{$member1} == 0)
&& $cs_member1 == 0) {
#
# Figure out the default speed if this is a path segment;
# otherwise inherit from the path.
#
if ($virtlan->_implemented_by()) {
$speed1 = $vpath->_pathspeed1();
}
else {
$speed1 =
$self->interfacespeedmbps($interface1->type(),"ethernet");
}
$self->printdb("Setting ifacebw: $pnode1:$iface1 $speed1\n");
#
# Save it off for later rounds of this loop for possible reference
#
$member1if->{"attrs"}->{"current_speed"} = $speed1;
#
# Upload it if we're not impotent or alloconly
#
if (!($self->impotent() || $self->alloconly())) {
$interface1->Update({'current_speed' => $speed1 });
}
}
else {
$speed1 = (exists($self->portbw()->{$member1})
&& $self->portbw()->{$member1}) ?
$self->portbw()->{$member1} / 1000 :
$cs_member1;
#
# Sanity check: did somebody set a speed already (user or previous
# current_speed attribute from an AddInterface call), and does it
# not match what the underlying path thinks it should be?
#
if ($virtlan->_implemented_by()
&& $virtlan->_vpath()->_pathspeed1() ne $speed1) {
print STDERR "mlevlanspeed: preset link speed disagreed with" .
" implementing start path segment!";
return -1;
}
}
#
# Now, if this segment was part of a path, and it's the end or start
# segment, set some bits on the path object so we can let links that
# are implemented by paths inherit speed settings from the implementing
# path endpoints.
#
if ($virtlan->_vpath()) {
my @links = $vpath->virtlanlist();
# save the endpoint speeds!
if ($links[0]->vname() eq $virtlan->vname()) {
$vpath->_pathspeed0($speed0);
$self->printdb("Saving ifacebw for vpath $vpath start: $speed0\n");
}
elsif ($links[@links-1]->vname() eq $virtlan->vname()
|| @links == 1) {
$vpath->_pathspeed1($speed1);
$self->printdb("Saving ifacebw for vpath $vpath end: $speed1\n");
}
}
}
$self->printdb("Done setting speeds for MLE virtlans.\n");
#
# Emulated vlans will result in node:port pairs being in more than
......
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