Commit 58ef6899 authored by Robert Ricci's avatar Robert Ricci
Browse files

Revert "Backend snmpit module changes from Keith Sklower"

This reverts commit efdf34a0.

Attempt to solve some problems with trunk creation by reverting
this change. It's not *certain* that this change is at fault, but
I want to factor out some possible causes
parent 997fa581
......@@ -56,11 +56,6 @@ my $PORT_FORMAT_IFINDEX = 1;
my $PORT_FORMAT_MODPORT = 2;
my $PORT_FORMAT_NODEPORT = 3;
#
# used by vlanTrunkUtil()
#
my ($VOP_CLEAR, $VOP_SET, $VOP_CLEARALL, $VOP_CHECK) = (0, 1, 2, 3);
#
# Creates a new object.
#
......@@ -955,9 +950,8 @@ sub createVlan($$;$$$) {
# returns 0 on sucess.
# returns the number of failed ports on failure.
#
sub opPortVlan($$$@) {
sub setPortVlan($$@) {
my $self = shift;
my $remove = shift;
my $vlan_number = shift;
my @ports = @_;
......@@ -1038,16 +1032,11 @@ sub opPortVlan($$$@) {
$errors++;
next;
}
my $snmpvar = [$PortVlanMemb,$index, ($remove? 1 :$vlan_number),
'INTEGER'];
my $snmpvar = [$PortVlanMemb,$index,$vlan_number,'INTEGER'];
#
# Check to see if we are already in a VLAN
#
$retval = snmpitGet($self->{SESS},[$PortVlanMemb,$index]);
if ($remove && ($retval ne $vlan_number)) {
$errors++;
next;
}
if (($retval ne "NOSUCHINSTANCE") &&
("$retval" ne "$vlan_number") && ("$retval" ne "1")) {
$BumpedVlans{$retval} = 1;
......@@ -1060,8 +1049,7 @@ sub opPortVlan($$$@) {
#
# We're here if it a trunk
#
$retval = $self->setVlansOnTrunk($port,!$remove, $vlan_number);
next if ($retval); # should not enable or disable existing trunks
$retval = $self->setVlansOnTrunk($port, 1, $vlan_number);
}
if (!$retval) {
$errors++;
......@@ -1075,7 +1063,7 @@ sub opPortVlan($$$@) {
# Ports going into VLAN 1 are being taken out of circulation, so we
# disable them. Otherwise, we need to make sure they get enabled.
#
if (($vlan_number == 1) || $remove) {
if ($vlan_number == 1) {
$self->debug("Disabling " . join(',',@okports) . "...");
if ( my $rv = $self->portControl("disable",@okports) ) {
print STDERR "Port disable had $rv failures.\n";
......@@ -1101,11 +1089,6 @@ sub opPortVlan($$$@) {
return $errors;
}
sub setPortVlan($$@) {
my ($self, $vlan_number, @ports) = @_;
return opPortVlan($self, 0, $vlan_number, @ports);
}
#
# Remove all ports from the given VLANs, which are given as Cisco-specific
# VLAN numbers
......@@ -1117,7 +1100,6 @@ sub setPortVlan($$@) {
sub removePortsFromVlan($@) {
my $self = shift;
my @vlan_numbers = @_;
my $errors = 0;
#
# Make sure the VLANs actually exist
......@@ -1125,8 +1107,7 @@ sub removePortsFromVlan($@) {
foreach my $vlan_number (@vlan_numbers) {
if (!$self->vlanNumberExists($vlan_number)) {
print STDERR "ERROR: VLAN $vlan_number does not exist\n";
$errors++;
next;
return 1;
}
}
......@@ -1145,49 +1126,23 @@ sub removePortsFromVlan($@) {
} elsif ($self->{OSTYPE} eq "IOS") {
$VlanPortVlan = "vmVlan"; #index is ifIndex
}
my %ports;
my @ports;
#
# Walk the tree to find VLAN membership
#
my ($rows) = snmpitBulkwalkFatal($self->{SESS},[$VlanPortVlan]);
foreach my $rowref (@$rows) {
my ($name,$ifIndex,$port_vlan_number) = @$rowref;
$self->debug("Got $name $ifIndex $port_vlan_number\n");
my ($name,$modport,$port_vlan_number) = @$rowref;
$self->debug("Got $name $modport $port_vlan_number\n");
if ($vlan_numbers{$port_vlan_number}) {
push @{$ports{$port_vlan_number}}, $ifIndex;
}
}
my %trunks;
#
# Walk trunks for the VLAN members
#
($rows) = snmpitBulkwalkFatal($self->{SESS},["vlanTrunkPortDynamicStatus"]);
foreach my $rowref (@$rows) {
my ($name,$ifIndex,$status) = @$rowref;
$self->debug("Got $name $ifIndex $status\n",3);
if ($status ne "trunking") { next;}
# Get the allowed VLANs on this trunk
my @trunklans = $self->vlanTrunkUtil
($VOP_CHECK, $ifIndex, @vlan_numbers);
foreach my $vlan_number (@trunklans) {
$self->debug("got vlan $vlan_number on trunk $ifIndex\n",3);
push @{$trunks{$vlan_number}}, $ifIndex;
push @ports, $modport;
}
}
while (my ($number, $plist) = each %trunks) {
foreach my $ifIndex (@$plist)
{ $errors += !$self->setVlansOnTrunk($ifIndex, 0, $number); }
}
$self->debug("About to remove ports " . join(",",(%ports)) . "\n");
if (%ports) {
while (my ($port_vlan_number, $plist) = each %ports)
{ $errors += $self->opPortVlan(1,$port_vlan_number,@$plist); }
return $errors;
$self->debug("About to remove ports " . join(",",@ports) . "\n");
if (@ports) {
return $self->setPortVlan(1,@ports);
} else {
return 0;
}
......@@ -1195,7 +1150,7 @@ sub removePortsFromVlan($@) {
#
# Remove some ports from the given VLAN, which are given as Cisco-specific
# VLAN numbers.
# VLAN numbers. Do not specify trunked ports here.
#
# usage: removeSomePortsFromVlan(self,int vlan, ports)
# returns 0 on sucess.
......@@ -1206,7 +1161,55 @@ sub removeSomePortsFromVlan($$@) {
my $vlan_number = shift;
my @ports = @_;
return opPortVlan($self, 1, $vlan_number, @ports);
#
# Make sure the VLANs actually exist
#
if (!$self->vlanNumberExists($vlan_number)) {
print STDERR "ERROR: VLAN $vlan_number does not exist\n";
return 1;
}
#
# Make a hash of the ports for easy lookup later.
#
my %ports = ();
@ports{@ports} = @ports;
#
# Get a list of the ports in the VLAN
#
my $VlanPortVlan;
if ($self->{OSTYPE} eq "CatOS") {
$VlanPortVlan = "vlanPortVlan"; #index is ifIndex
} elsif ($self->{OSTYPE} eq "IOS") {
$VlanPortVlan = "vmVlan"; #index is ifIndex
}
my @remports;
#
# Walk the tree to find VLAN membership
#
my ($rows) = snmpitBulkwalkFatal($self->{SESS},[$VlanPortVlan]);
foreach my $rowref (@$rows) {
my ($name,$modport,$port_vlan_number) = @$rowref;
my ($trans) = convertPortFormat($PORT_FORMAT_NODEPORT,$modport);
if (!defined $trans) {
$trans = ""; # Guard against some uninitialized value warnings
}
$self->debug("Got $name $modport ($trans) $port_vlan_number\n");
push(@remports, $modport)
if ("$port_vlan_number" eq "$vlan_number" &&
exists($ports{$trans}));
}
$self->debug("About to remove ports " . join(",",@remports) . "\n");
if (@remports) {
return $self->setPortVlan(1,@remports);
} else {
return 0;
}
}
#
......@@ -1225,7 +1228,6 @@ sub removeVlan($@) {
my $errors = 0;
removePortsFromVlan($self, @vlan_numbers);
foreach my $vlan_number (@vlan_numbers) {
#
# Need to lock the VLAN edit buffer
......@@ -1384,6 +1386,7 @@ my %vtrunkOIDS = (
# precompute 1k 0 bits as bitfield
my $p1k = pack("x128");
my ($VOP_CLEAR, $VOP_SET, $VOP_CLEARALL, $VOP_CHECK) = (0, 1, 2, 3);
#
# vlanTrunkUtil($self, $op, $ifIndex, @vlans)
......@@ -1727,8 +1730,11 @@ sub getChannelIfIndex($@) {
# single port channel.
#
if (!$ifindex) {
if (@ifIndexes == 1) {
$ifindex = $ifIndexes[0];
}
}
return $ifindex;
}
......@@ -1756,7 +1762,6 @@ sub setVlansOnTrunk($$$$) {
}
my ($ifIndex) = $self->convertPortFormat($PORT_FORMAT_IFINDEX,$port);
$ifIndex = $self->getChannelIfIndex($ifIndex);
@vlan_numbers = $self->vlanTrunkUtil($value, $ifIndex, @vlan_numbers);
return (scalar(@vlan_numbers) != 0);
}
......@@ -1773,7 +1778,18 @@ sub clearAllVlansOnTrunk($$) {
my ($modport) = @_;
my ($ifIndex) = $self->convertPortFormat($PORT_FORMAT_IFINDEX,$modport);
$ifIndex = $self->getChannelIfIndex($ifIndex);
#
# If this is part of an EtherChannel, we have to find the ifIndex for the
# channel.
# TODO: Perhaps this should be general - ie. $self{IFINDEX} should have
# the channel ifIndex the the port is in a channel. Not sure that
# this is _always_ beneficial, though
#
my $channel = snmpitGetFatal($self->{SESS},["pagpGroupIfIndex",$ifIndex]);
if (($channel =~ /^\d+$/) && ($channel != 0)) {
$ifIndex = $channel;
}
my @vlan_numbers = $self->vlanTrunkUtil($VOP_CLEARALL, $ifIndex);
return (scalar(@vlan_numbers) != 0);
}
......@@ -1790,8 +1806,26 @@ sub clearAllVlansOnTrunk($$) {
sub resetVlanIfOnTrunk($$$) {
my ($self, $modport, $vlan_number) = @_;
my ($ifIndex) = $self->convertPortFormat($PORT_FORMAT_IFINDEX,$modport);
$ifIndex = $self->getChannelIfIndex($ifIndex);
#
# If this is part of an EtherChannel, we have to find the ifIndex for the
# channel.
# TODO: Perhaps this should be general - ie. $self{IFINDEX} should have
# the channel ifIndex the the port is in a channel. Not sure that
# this is _always_ beneficial, though
# NOTE: This 'conversion' is no longer needed, since we call
# getChannelIfIndex on the port before passing it into this function
#
#my $channel = snmpitGetFatal($self->{SESS},["pagpGroupIfIndex",$ifIndex]);
#if (!($channel =~ /^\d+$/) || ($channel == 0)) {
# print "WARNING: resetVlanIfOnTrunk got bad channel ($channel) for $self->{NAME}.$modport\n";
# return 0;
#}
#if (($channel =~ /^\d+$/) && ($channel != 0)) {
# $ifIndex = $channel;
#}
my @vlan_numbers = $self->vlanTrunkUtil($VOP_CHECK, $ifIndex, $vlan_number);
if (@vlan_numbers) {
......@@ -1899,7 +1933,7 @@ sub disablePortTrunking($$) {
my $trunkDisable = ["vlanTrunkPortDynamicState",$ifIndex,"off","INTEGER"];
$rv = snmpitSetWarn($self->{SESS},$trunkDisable);
if (!$rv) {
warn "ERROR: Unable to disable trunking\n";
warn "ERROR: Unable to enable trunking\n";
return 0;
}
......@@ -2240,7 +2274,7 @@ sub enableOpenflow($$) {
#
# Cisco switch doesn't support Openflow yet.
#
warn "ERROR: Cisco switch doesn't support Openflow now";
warn "ERROR: Cisco swith doesn't support Openflow now";
return 0;
}
......@@ -2255,7 +2289,7 @@ sub disableOpenflow($$) {
#
# Cisco switch doesn't support Openflow yet.
#
warn "ERROR: Cisco switch doesn't support Openflow now";
warn "ERROR: Cisco swith doesn't support Openflow now";
return 0;
}
......@@ -2271,7 +2305,7 @@ sub setOpenflowController($$$) {
#
# Cisco switch doesn't support Openflow yet.
#
warn "ERROR: Cisco switch doesn't support Openflow now";
warn "ERROR: Cisco swith doesn't support Openflow now";
return 0;
}
......@@ -2287,7 +2321,7 @@ sub setOpenflowListener($$$) {
#
# Cisco switch doesn't support Openflow yet.
#
warn "ERROR: Cisco switch doesn't support Openflow now";
warn "ERROR: Cisco swith doesn't support Openflow now";
return 0;
}
......@@ -2298,7 +2332,7 @@ sub getUsedOpenflowListenerPorts($) {
my $self = shift;
my %ports = ();
warn "ERROR: Cisco switch doesn't support Openflow now\n";
warn "ERROR: Cisco swith doesn't support Openflow now\n";
return %ports;
}
......
......@@ -3,7 +3,7 @@
#
# EMULAB-LGPL
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# Copyright (c) 2004-2010 Regents, University of California.
# Copyright (c) 2004-2009 Regents, University of California.
# All rights reserved.
#
......@@ -838,12 +838,12 @@ sub setPortVlan($$@) {
# b. the ports is not allocated
# c. the port is a trunk
# case a: This is a dual port, so it doesn't have to leave its PVID.
# This is a dual port, so it doesn't have to leave its PVID.
if (@{@$defaultInfo[0]}[$portIndex - 1]) {
push @newTaggedPorts, $portIndex;
next;
}
# case b: Unallocated untrunked port.
# Unallocated untrunked port.
if (@{@$defaultInfo[1]}[$portIndex - 1]) {
$pvid = 1;
} else {
......@@ -970,15 +970,48 @@ sub removePortsFromVlan($@) {
my $id = $self->{NAME} . "::removePortsFromVlan";
foreach my $vlan_number (@vlan_numbers) {
my @ports = $self->portSetToList($self->get1($egressOID, $vlan_number));
$errors += $self->removeSomePortsFromVlan($vlan_number, @ports);
#
# Do two passes: 1st untrunk any dual-mode ports on this vlan.
# 2nd, remove all ports.
#
my $dualPorts = mirvPortSet($self->get1($forbidOID, 1)); # array
my @portlist = $self->portSetToList
($self->get1($normOID, $vlan_number));
foreach my $portIndex (@portlist) {
if (@$dualPorts[$portIndex-1])
{ $self->disablePortTrunking($portIndex);}
}
$self->lock();
my $defaultLists = $self->getVlanLists(1);
my $vLists = $self->getVlanLists($vlan_number);
@portlist = bitSetToList(@$vLists[2]);
$self->debug("$id $vlan_number: @portlist\n");
foreach my $portIndex (@portlist) {
#
# If this port is not listed as a tagged member of the vlan,
# then it could have only gotten here either as a trunk
# or dual-mode port from another vlan, so don't disable it.
#
if (@{@$vLists[1]}[$portIndex - 1]) {
@{@$defaultLists[1]}[$portIndex - 1] = 1;
@{@$defaultLists[2]}[$portIndex - 1] = 1;
$self->debug("disabling port $portIndex "
. "from vlan $vlan_number \n" );
$self->set(["ifAdminStatus",$portIndex,"down","INTEGER"],$id);
}
@{@$vLists[1]}[$portIndex - 1] = 0;
@{@$vLists[2]}[$portIndex - 1] = 0;
}
$errors += $self->setVlanLists($vlan_number, $vLists, 1, $defaultLists);
$self->unlock();
}
return $errors;
}
#
# Removes and disables some ports in a given VLAN.
# The VLAN is given as a VLAN 802.1Q tag value.
# Removes and disables some ports in a given VLAN. The VLAN is given as a VLAN
# 802.1Q tag value. Ports are known to be regular ports and not trunked.
#
# usage: removeSomePortsFromVlan(self,vlan,@ports)
# returns 0 on sucess.
......@@ -991,18 +1024,7 @@ sub removeSomePortsFromVlan($$@) {
@ports = $self->convertPortFormat($PORT_FORMAT_IFINDEX,@ports);
@porthash{@ports} = @ports;
my $dualPorts = mirvPortSet($self->get1($forbidOID, 1)); # array
# First, any dual ports whose PVID is this vlan become equaltrunks
foreach my $portIndex (@ports) {
if (@$dualPorts[$portIndex-1]) {
my $pvid = $self->get1("dot1qPvid", $portIndex);
$self->enablePortTrunking2($portIndex,1,1)
if ($pvid && ($pvid eq "$vlan_number"));
}
}
# Now, remove the ports from the vlan.
$self->lock();
my $defaultLists = $self->getVlanLists(1);
my $vLists = $self->getVlanLists($vlan_number);
......@@ -1012,7 +1034,7 @@ sub removeSomePortsFromVlan($$@) {
foreach my $portIndex (@portlist) {
next unless exists($porthash{$portIndex});
if (@{@$vLists[1]}[$portIndex - 1]) {
# otherwise, port is tagged.
# otherwise, port is tagged, or dual; maybe should complain.
@{@$defaultLists[1]}[$portIndex - 1] = 1;
@{@$defaultLists[2]}[$portIndex - 1] = 1;
......@@ -1032,7 +1054,8 @@ sub removeSomePortsFromVlan($$@) {
#
# Remove the given VLANs from this switch. Removes all ports from the VLAN,
# The VLAN is given as a VLAN identifier from the database.
# It's necessary to call removePortsFromVlan() first on HP's. The VLAN is
# given as a VLAN identifier from the database.
#
# usage: removeVlan(self,int vlan)
# returns 1 on success
......@@ -1045,7 +1068,6 @@ sub removeVlan($@) {
my $errors = 0;
my $name = $self->{NAME};
$self->removePortsFromVlan(@vlan_numbers);
foreach my $vlan_number (@vlan_numbers) {
#
# Perform the actual removal
......@@ -1309,47 +1331,91 @@ sub listPorts($) {
#
# Get statistics for ports on the switch
#
# usage: getStats($self)
# usage: getPorts($self)
# see snmpit_cisco_stack.pm for a description of return value format
#
#
sub getStats() {
sub getStats ($) {
my $self = shift;
my $ifTable = ["ifInOctets",0];
my %inOctets=();
my %inUcast=();
my %inNUcast=();
my %inDiscard=();
my %inErr=();
my %inUnkProt=();
my %outOctets=();
my %outUcast=();
my %outNUcast=();
my %outDiscard=();
my %outErr=();
my %outQLen=();
my ($varname, $port, $value);
#
# Walk the tree for the VLAN members
# Walk the whole stats tree, and fill these ha
#
my $vars = new SNMP::VarList(['ifInOctets'],['ifInUcastPkts'],
['ifInNUcastPkts'],['ifInDiscards'],
['ifInErrors'],['ifInUnknownProtos'],
['ifOutOctets'],['ifOutUcastPkts'],
['ifOutNUcastPkts'],['ifOutDiscards'],
['ifOutErrors'],['ifOutQLen']);
my @stats = $self->{SESS}->bulkwalk(0,32,$vars);
$self->{SESS}->getnext($ifTable);
do {
($varname,$port,$value) = @{$ifTable};
$self->debug("getStats: Got $varname, $port, $value\n");
if ($port > $self->{MAXPORT}) {
# do nothing. There are entries for vlan interfaces, etc.
} elsif ($varname =~ /InOctets/) {
$inOctets{$port} = $value;
} elsif ($varname =~ /InUcast/) {
$inUcast{$port} = $value;
} elsif ($varname =~ /InNUcast/) {
$inNUcast{$port} = $value;
} elsif ($varname =~ /InDiscard/) {
$inDiscard{$port} = $value;
} elsif ($varname =~ /InErrors/) {
$inErr{$port} = $value;
} elsif ($varname =~ /InUnknownP/) {
$inUnkProt{$port} = $value;
} elsif ($varname =~ /OutOctets/) {
$outOctets{$port} = $value;
} elsif ($varname =~ /OutUcast/) {
$outUcast{$port} = $value;
} elsif ($varname =~ /OutNUcast/) {
$outNUcast{$port} = $value;
} elsif ($varname =~ /OutDiscard/) {
$outDiscard{$port} = $value;
} elsif ($varname =~ /OutErrors/) {
$outErr{$port} = $value;
} elsif ($varname =~ /OutQLen/) {
$outQLen{$port} = $value;
}
$self->{SESS}->getnext($ifTable);
} while ( $varname =~ /^i[f](In|Out)/) ;
#
# We need to flip the two-dimentional array we got from bulkwalk on
# its side, and convert ifindexes into node:port
# Put all of the data gathered in the loop into a list suitable for
# returning
#
my $i = 0;
my %stats;
foreach my $array (@stats) {
while (@$array) {
my ($name,$ifindex,$value) = @{shift @$array};
# See comments in walkTable above.
if (! defined $self->{IFINDEX}{$ifindex}) { next; }
my $port = portnum("$self->{NAME}:$ifindex")
|| portnum("$self->{NAME}:".$self->{IFINDEX}{$ifindex});
if (! defined $port) { next; } # Skip if we don't know about it
${$stats{$port}}[$i] = $value;
my @rv = ();
foreach my $id ( keys %inOctets ) {
my $modport = $self->{IFINDEX}{$id};
$port = portnum($self->{NAME} . ":" . $modport);
if (!$port && $self->{DOALLPORTS}) {
$modport =~ s/\./\//;
$port = $self->{NAME} . ".$modport";
}
$i++;
}
#
# Skip ports that don't seem to have anything interesting attached
#
if (!$port) {
$self->debug("$id does not seem to be connected, skipping\n");
next;
}
push @rv, [$port,$inOctets{$id},$inUcast{$id},$inNUcast{$id},
$inDiscard{$id},$inErr{$id},$inUnkProt{$id},$outOctets{$id},
$outUcast{$id},$outNUcast{$id},$outDiscard{$id},$outErr{$id},
$outQLen{$id}];
return map [$_,@{$stats{$_}}], sort {tbsort($a,$b)} keys %stats;
}
return @rv;
}
#
......@@ -1469,42 +1535,43 @@ sub setVlansOnTrunk($$$$) {
#
sub enablePortTrunking2($$$$) {
my ($self,$port,$native_vlan,$equaltrunking) = @_;
my ($curvlans, $initvlan, $errors) = ([], $native_vlan, 0);
if ($equaltrunking) {
$initvlan = 1;
push @$curvlans, $native_vlan if ($native_vlan && $native_vlan ne "1");
if (!$native_vlan) { $native_vlan = 1; }
} elsif (!defined($native_vlan) || ($native_vlan <= 1)) {
warn "Error: innappropriate or missing PVID for trunk\n";
return 0;
}
my ($ifIndex) = $self->convertPortFormat($PORT_FORMAT_IFINDEX,$port);
#
# (Temporarily) clear out all other vlans and set the PVID
# portSetVlan will clear out all other vlans and set the PVID
#
$self->disablePortTrunking($ifIndex,$curvlans);
my $rv = $self->setPortVlan($native_vlan, $port);
if ($rv) {
warn "ERROR: Unable to add Trunk $port to PVID $native_vlan\n";
return 0;
}
#
# Set port type apropriately.
#
$self->lock();
my $defLists = $self->getVlanLists(1);
if ($equaltrunking) {
@{@$defLists[1]}[$ifIndex - 1] = 0; # remove from untaggged list
my $portType = [$aftOID,$ifIndex,"admitOnlyVlanTagged","INTEGER"];
$rv = $self->{SESS}->set($portType);
if (!defined($rv)) {
warn "enablePortTrunking: Unable to set port type\n";
return 0;
}
} else {