Commit ad8ed130 authored by Leigh B Stoller's avatar Leigh B Stoller

Bug Fix: Fix how we determine the set of ports to tag/untag.

The basic problem is that when snmpit looks to see what ports it
should trunk (or untrunk) the equation is more complicated then it
used to be.

Case 1: In the old days, before shared nodes and shared lans, a node
and its interfaces were always one-to-one with an experiment. So the
set of trunks was easily derivable from the reserved table joined with
the interfaces table.

Case 2: But when we added shared nodes (with vlan encap of course),
the set of trunk ports is no longer associated with the experiments
using those ports, but only with the underlying experiment. That is we
do not mess with the trunking when swapping experiments on shared
nodes, we only want to add and subtract vlans to those trunked
ports. So, I added a check against the reserved table. Easy. The ports
are trunked when the underlying "shared nodes" experiment is swapped
in, and untrunked when it is swapped out.

Case 3: Then we added shared vlans. Well this is almost the exact
opposite case. The ports belong to nodes in other experiments, but now
we *do* want to consider them when turning trunking on and off. The
underlying experiment that owns the lan (emulab-ops,openflow-vlans)
does not own any of the ports, but we do want to enable/disable the
trunking as ports come and go.

Case 4: Last but certainly not least, is a potential bad interaction
between these #2 and #3! The instageni-connect port is a member of the
1750 shared vlan (and thus trunking is enabled when the openflow lan
is created or modified). But that same port is also used in the second
case above when stitching to the rack; The instageni-connect node is a
shared node, and we allocate fake VMs on it that serve simply as a
place to associate the vlans that use that port; we just want to add
and subtract vlans to the port. ÊThe gist of this is that if someone
were to remove the port from the shared 1750 vlan, its trunk would get
turned off, and all of the stitched vlans would stop working.

This bug fix deals with the addition of #3, but I do not have anything
for #4.  But I can commit this fix with the understanding that
#4 is a real problem that has to be dealt with.
parent f16a29de
......@@ -358,18 +358,60 @@ sub getExperimentTrunks($$@) {
my ($pid, $eid, @vlans) = @_;
my @ports = ();
# For debugging only.
@vlans = getExperimentVlans($pid, $eid)
if (!@vlans);
my $experiment = Experiment->Lookup($pid, $eid);
return undef
if (!defined($experiment));
#
# We want to restrict the set of ports to just those in the
# provided vlans, lest we get into a problem with a missing
# device from the stack. This became necessary after adding
# shared vlans, since those ports technically belong to the
# current experiment, but are setup in the context of a
# different experiment. Needs more thought though.
# different experiment.
#
my @vlanports = getVlanPorts(@vlans);
foreach my $port (@vlanports) {
push(@ports, $port)
if ($port->trunk());
# However, there is a problem. Without the check against the
# reserved table, we will also get the physical ports on a shared
# node, which are in use by the VMs on the node, but actually
# belong to the holding experiment, and thus should not be considered,
# lest we change the tagging and mess up all the VMs using that
# port. In other words, sometimes we want to consider ports on
# nodes that belong to another experiment (shared vlan) and sometimes
# we do not (shared nodes). Sadly, the nodes that get added to a
# shared lan are sometimes shared nodes! Confused yet?
#
foreach my $vlanid (@vlans) {
foreach my $port (getVlanPorts($vlanid)) {
next
if (!$port->trunk());
#
# Look at the node. If the node is reserved to another
# experiment, then consider it only if the lan is marked
# as a shared lan.
#
my $node = Node->Lookup($port->node_id());
if (!defined($node)) {
print STDERR "*** No such node for $port\n";
next;
}
my $reservation = $node->Reservation();
next
if (!defined($reservation));
if (! $experiment->SameExperiment($reservation)) {
my $query_result =
DBQueryFatal("select lanid from shared_vlans ".
"where lanid='$vlanid'");
next
if (!$query_result->numrows);
}
push(@ports, $port);
}
}
return @ports;
}
......@@ -383,13 +425,31 @@ sub getExperimentCurrentTrunks($$@) {
my ($pid, $eid, @vlans) = @_;
my @ports = ();
# For debugging only.
@vlans = getExperimentVlans($pid, $eid)
if (!@vlans);
my $experiment = Experiment->Lookup($pid, $eid);
return undef
if (!defined($experiment));
#
# We want to restrict the set of ports to just those in the
# provided vlans, lest we get into a problem with a missing
# device from the stack. This became necessary after adding
# shared vlans, since those ports technically belong to the
# current experiment, but are setup in the context of a
# different experiment. Needs more thought though.
# different experiment.
#
# However, there is a problem. Without the check against the
# reserved table, we will also get the physical ports on a shared
# node, which are in use by the VMs on the node, but actually
# belong to the holding experiment, and thus should not be considered,
# lest we change the tagging and mess up all the VMs using that
# port. In other words, sometimes we want to consider ports on
# nodes that belong to another experiment (shared vlan) and sometimes
# we do not (shared nodes). Sadly, the nodes that get added to a
# shared lan are sometimes shared nodes! Confused yet?
#
foreach my $vlanid (@vlans) {
my @vlanports = getExperimentVlanPorts($vlanid);
......@@ -403,8 +463,31 @@ sub getExperimentCurrentTrunks($$@) {
"where node_id='$node_id' and iface='$iface' and ".
" tagged!=0");
push(@ports, $port)
if ($query_result->numrows);
next
if (! $query_result->numrows);
#
# Look at the node. If the node is reserved to another
# experiment, then consider it only if the lan is marked
# as a shared lan.
#
my $node = Node->Lookup($node_id);
if (!defined($node)) {
print STDERR "*** No such node for $port\n";
next;
}
my $reservation = $node->Reservation();
next
if (!defined($reservation));
if (! $experiment->SameExperiment($reservation)) {
my $query_result =
DBQueryFatal("select lanid from shared_vlans ".
"where lanid='$vlanid'");
next
if (!$query_result->numrows);
}
push(@ports, $port);
}
}
return @ports;
......
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