Commit c9762876 authored by Robert Ricci's avatar Robert Ricci

Merge branch 'snmpit-revert'

parents ba204933 58ef6899
......@@ -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.
#
......@@ -948,16 +943,15 @@ sub createVlan($$;$$$) {
}
#
# Either add or remove the given ports from the given VLAN. The VLAN is given
# as a cisco-specific VLAN number
# Put the given ports in the given VLAN. The VLAN is given as a cisco-specific
# VLAN number
#
# usage: opPortVlan($self, $remove, $vlan_number, @ports)
# usage: setPortVlan($self, $vlan_number, @ports)
# 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,19 +1089,6 @@ sub opPortVlan($$$@) {
return $errors;
}
#
# Put the given ports in the given VLAN. The VLAN is given as a cisco-specific
# VLAN number
#
# usage: setPortVlan($self, $vlan_number, @ports)
# returns 0 on sucess.
# returns the number of failed ports on failure.
#
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
......@@ -1125,7 +1100,6 @@ sub setPortVlan($$@) {
sub removePortsFromVlan($@) {
my $self = shift;
my @vlan_numbers = @_;
my $errors = 0;
#
# Make sure the VLANs actually exist
......@@ -1133,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;
}
}
......@@ -1153,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;
}
......@@ -1203,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.
......@@ -1214,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;
}
}
#
......@@ -1233,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
......@@ -1392,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)
......@@ -1735,8 +1730,11 @@ sub getChannelIfIndex($@) {
# single port channel.
#
if (!$ifindex) {
if (@ifIndexes == 1) {
$ifindex = $ifIndexes[0];
}
}
return $ifindex;
}
......@@ -1764,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);
}
......@@ -1781,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);
}
......@@ -1798,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) {
......@@ -1907,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;
}
......@@ -2248,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;
}
......@@ -2263,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;
}
......@@ -2279,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;
}
......@@ -2295,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;
}
......@@ -2306,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 {
$self->lock();
my $defLists = $self->getVlanLists(1);
@{@$defLists[0]}[$ifIndex - 1] = 1; # add to forbid list of default
$rv = $self->setVlanLists(1, $defLists);
$self->unlock();
if (!defined($rv)) {
warn "enablePortTrunking: Unable to set port type\n";
return 0;
}