Commit 13381879 authored by Robert Ricci's avatar Robert Ricci
Browse files

Made some functions that previously took only a single port or VLAN

take more than one. This can increase efficiency, since, for example,
we now only have to lock the VLAN edit buffer once when tearing down
an experiment, instead of once per VLAN. There are still other
functions (setVlanOnTrunks comes to mind) that could benefit from this
treatment.

These optimization have been made only for Ciscos - minimal changes
necessary to keep Intel support working were made, but they will still
have the same old slow behavior.
parent 9b51a2d6
......@@ -653,17 +653,20 @@ sub doReset($@) {
my @vlans = @_;
my $errors = 0;
foreach my $vlan (@vlans) {
#
# Just remove the VLAN from evey satck on which it exists
#
foreach my $stack (@$stacks) {
#
# Just remove the VLAN from evey satck on which it exists. We keep a
# list and do them all at once for efficiency.
#
foreach my $stack (@$stacks) {
my @existant_vlans = ();
foreach my $vlan (@vlans) {
if ($stack->vlanExists($vlan)) {
if (!$stack->removeVlan($vlan)) {
$errors++;
}
push @existant_vlans, $vlan;
}
}
if (!$stack->removeVlan(@existant_vlans)) {
$errors++;
}
}
return $errors;
}
......
......@@ -640,39 +640,42 @@ sub setPortVlan($$@) {
# Remove all ports from the given VLAN. The VLAN is given as a VLAN
# identifier from the database.
#
# usage: removePortsFromVlan(self,int vlan)
# usage: removePortsFromVlan(self,int vlans)
# returns 0 on sucess.
# returns the number of failed ports on failure.
#
sub removePortsFromVlan($$) {
sub removePortsFromVlan($@) {
my $self = shift;
my $vlan_id = shift;
my @vlan_ids = @_;
#
# Find the real VLAN number from the passed VLAN ID
# Find the real VLAN numbers from the passed VLAN IDs
#
my $vlan_number = $self->findVlan($vlan_id);
if (!defined($vlan_number)) {
print STDERR "ERROR: VLAN with identifier $vlan_id does not exist\n";
return 1;
my %vlan_numbers = ();
foreach my $vlan_id (@vlan_ids) {
my $vlan_number = $self->findVlan($vlan_id);
if (!defined($vlan_number)) {
print STDERR "ERROR: VLAN with identifier $vlan_id does not exist\n";
return 1;
}
$self->debug("Found VLAN with ID $vlan_id: $vlan_number\n");
$vlan_numbers{$vlan_number} = 1;
}
$self->debug("Found VLAN with ID $vlan_id: $vlan_number\n");
#
# Get a list of the ports in the VLAN
#
#
my $VlanPortVlan = ["vlanPortVlan"]; # index by module.port, gives vlan #
my $VlanPortVlan = ["vlanPortVlan"]; # index by module.port, gives vlan
my @ports;
#
# Walk the tree to find VLAN membership
#
my ($rows) = $self->{SESS}->bulkwalk(0,32,$VlanPortVlan);
my @ports;
foreach my $rowref (@$rows) {
my ($name,$modport,$port_vlan_number) = @$rowref;
$self->debug("Got $name $modport $port_vlan_number\n");
if ($port_vlan_number == $vlan_number) {
my ($name,$modport,$port_vlan_number) = @$rowref;
$self->debug("Got $name $modport $port_vlan_number\n");
if ($vlan_numbers{$port_vlan_number}) {
push @ports, $modport;
}
}
......@@ -695,19 +698,9 @@ sub removePortsFromVlan($$) {
# returns 0 on failure
#
#
sub removeVlan($$) {
sub removeVlan($@) {
my $self = shift;
my $vlan_id = shift;
#
# Find the real VLAN number from the passed VLAN ID
#
my $vlan_number = $self->findVlan($vlan_id);
if (!defined($vlan_number)) {
print STDERR "ERROR: VLAN with identifier $vlan_id does not exist\n";
return 0;
}
$self->debug("Found VLAN with ID $vlan_id: $vlan_number\n");
my @vlan_ids = @_;
#
# Need to lock the VLAN edit buffer
......@@ -716,24 +709,44 @@ sub removeVlan($$) {
return 0;
}
#
# Perform the actual removal
#
my $VlanRowStatus = '.1.3.6.1.4.1.9.9.46.1.4.2.1.11.1'; # vlan # is index
print " Removing VLAN #$vlan_number ... ";
my $RetVal = $self->{SESS}->set([$VlanRowStatus,$vlan_number,"destroy","INTEGER"]);
print ($RetVal ? "Succeeded.\n" : "Failed.\n");
my $errors = 0;
foreach my $vlan_id (@vlan_ids) {
#
# Find the real VLAN number from the passed VLAN ID
#
my $vlan_number = $self->findVlan($vlan_id);
if (!defined($vlan_number)) {
print STDERR "ERROR: VLAN with identifier $vlan_id does ".
"not exist\n";
return 0;
}
$self->debug("Found VLAN with ID $vlan_id: $vlan_number\n");
#
# Perform the actual removal
#
my $VlanRowStatus = '.1.3.6.1.4.1.9.9.46.1.4.2.1.11.1'; # vlan is index
print " Removing VLAN #$vlan_number ... ";
my $RetVal = $self->{SESS}->set([$VlanRowStatus,$vlan_number,
"destroy","INTEGER"]);
if ($RetVal) {
print "Succeeded.\n";
} else {
print "Failed.\n";
$errors++;
}
}
#
# Unlock whether successful or not
#
$self->vlanUnlock();
if (! defined $RetVal) {
print STDERR "VLAN #$vlan_number does not exist on this switch.\n";
if ($errors) {
return 0;
} else {
$self->vlanUnlock();
return 1;
}
......
......@@ -321,33 +321,36 @@ sub vlanExists($$) {
# Removes a VLAN from the stack. This implicitly removes all ports from the
# VLAN. It is an error to remove a VLAN that does not exist.
#
# usage: removeVlan(self, vlan identifier)
# usage: removeVlan(self, vlan identifiers)
#
# returns: 1 on success
# returns: 0 on failure
#
sub removeVlan($$) {
sub removeVlan($@) {
my $self = shift;
my $vlan_id = shift;
my (@vlan_ids) = @_;
my $errors = 0;
#
# First, make sure that the VLAN really does exist
#
my $vlan_number = $self->{LEADER}->findVlan($vlan_id);
if (!$vlan_number) {
warn "ERROR: VLAN $vlan_id not found on switch!";
return 0;
}
foreach my $vlan_id (@vlan_ids) {
#
# First, make sure that the VLAN really does exist
#
my $vlan_number = $self->{LEADER}->findVlan($vlan_id);
if (!$vlan_number) {
warn "ERROR: VLAN $vlan_id not found on switch!";
return 0;
}
#
# Prevent the VLAN from being sent across trunks.
#
if (!$self->setVlanOnTrunks($vlan_number,0)) {
warn "ERROR: Unable to set up VLANs on trunks!\n";
#
# We can keep going, 'cause we can still remove the VLAN
# Prevent the VLAN from being sent across trunks.
#
if (!$self->setVlanOnTrunks($vlan_number,0)) {
warn "ERROR: Unable to set up VLANs on trunks!\n";
#
# We can keep going, 'cause we can still remove the VLAN
#
}
}
#
......@@ -356,17 +359,26 @@ sub removeVlan($$) {
#
foreach my $devicename (sort {tbsort($a,$b)} keys %{$self->{DEVICES}}) {
my $device = $self->{DEVICES}{$devicename};
my @existant_vlans = ();
foreach my $vlan_id (@vlan_ids) {
#
# Only remove ports from the VLAN if it exists on this
# device
#
if (defined(my $number = $device->findVlan($vlan_id))) {
$errors += $device->removePortsFromVlan($vlan_id);
#
# Only remove ports from the VLAN if it exists on this
# device. Do it in one pass for efficiency
#
if (defined(my $number = $device->findVlan($vlan_id))) {
push @existant_vlans, $vlan_id;
}
}
$errors += $device->removePortsFromVlan(@existant_vlans);
}
my $ok = $self->{LEADER}->removeVlan($vlan_id);
#
# For efficiency, we remove all VLANs from the leader in one function
# call. This can save a _lot_ of locking and unlocking.
#
my $ok = $self->{LEADER}->removeVlan(@vlan_ids);
return ($ok && ($errors == 0));
}
......
......@@ -144,22 +144,27 @@ sub vlanExists($$) {
}
sub removeVlan($$) {
sub removeVlan($@) {
my $self = shift;
my $vlan_id = shift;
my @vlan_ids = @_;
#
# First, make sure that the VLAN really does exist
#
my $vlan_number = $self->{LEADER}->findVlan($vlan_id);
if (!$vlan_number) {
warn "ERROR: VLAN $vlan_id not found on switch!";
return 0;
my $errors = 0;
foreach my $vlan_id (@vlan_ids) {
#
# First, make sure that the VLAN really does exist
#
my $vlan_number = $self->{LEADER}->findVlan($vlan_id);
if (!$vlan_number) {
warn "ERROR: VLAN $vlan_id not found on switch!";
$errors++;
}
my $ok = $self->{LEADER}->removeVlan($vlan_id);
if (!$ok) {
$errors++;
}
}
my $ok = $self->{LEADER}->removeVlan($vlan_id);
return $ok;
return ($errors == 0);
}
sub portControl ($$@) {
......
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