diff --git a/ChangeLog b/ChangeLog index 645d9ffd..177795be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,12 +10,18 @@ version 3.21 () [ENHANCEMENTS] * No longer ignore interfaces based on name, in base L2/L3/L7 device - classes. For several device classes SNMP::Info will now return tunnel - interfaces and/or loopbacks, if present. + classes. For several device classes SNMP::Info will now return tunnel + interfaces and/or loopbacks, if present. + * Use dot1qVlanCurrentTable if available to capture dynamic and static + VLANs, fall back to dot1qVlanStaticTable if not available. + * New method i_vlan_membership_untagged() for VLANs transmitted as + untagged frames. [BUG FIXES] * [#64] Misdetection: Wireless APs, add products MIB to L2::3Com + * Use FDB ID to VID mapping if available to determine end station VLAN + rather than assuming they are the same. version 3.20 (2014-09-08) diff --git a/Info/Bridge.pm b/Info/Bridge.pm index 55ac7db1..746651ef 100644 --- a/Info/Bridge.pm +++ b/Info/Bridge.pm @@ -99,6 +99,7 @@ $VERSION = '3.20'; 'qb_i_vlan_in_flt' => 'dot1qPortIngressFiltering', # Q-BRIDGE-MIB : dot1qVlanCurrentTable + 'qb_cv_fdb_id' => 'dot1qVlanFdbId', 'qb_cv_egress' => 'dot1qVlanCurrentEgressPorts', 'qb_cv_untagged' => 'dot1qVlanCurrentUntaggedPorts', 'qb_cv_stat' => 'dot1qVlanStatus', @@ -134,6 +135,7 @@ $VERSION = '3.20'; 'qb_v_egress' => \&SNMP::Info::munge_port_list, 'qb_v_fbdn_egress' => \&SNMP::Info::munge_port_list, 'qb_v_untagged' => \&SNMP::Info::munge_port_list, + 'qb_cv_untagged' => \&SNMP::Info::munge_port_list, ); @@ -163,10 +165,21 @@ sub qb_fw_vlan { my $partial = shift; my $qb_fw_port = $bridge->qb_fw_port($partial); + # Some devices may not implement TimeFilter in a standard manner + # appearing to loop on this request. Override in the device class, + # see Enterasys for example. + my $qb_fdb_ids = $bridge->qb_cv_fdb_id() || {}; + my $qb_fw_vlan = {}; foreach my $idx ( keys %$qb_fw_port ) { my ( $fdb_id, $mac ) = _qb_fdbtable_index($idx); - $qb_fw_vlan->{$idx} = $fdb_id; + # Many devices do not populate the dot1qVlanCurrentTable, so default + # to FDB ID = VID, but if we have a mapping use it. + my $vlan = $fdb_id; + if ($qb_fdb_ids->{$fdb_id}) { + $vlan = $qb_fdb_ids->{$fdb_id}; + } + $qb_fw_vlan->{$idx} = $vlan; } return $qb_fw_vlan; } @@ -343,20 +356,31 @@ sub i_vlan_membership { my $bridge = shift; my $partial = shift; - my $index = $bridge->bp_index(); + # Use VlanCurrentTable if available since it will include dynamic + # VLANs. However, some devices do not populate the table. + my $v_ports = $bridge->qb_cv_egress() || $bridge->qb_v_egress(); + + return $bridge->_vlan_hoa($v_ports, $partial); +} + +sub i_vlan_membership_untagged { + my $bridge = shift; + my $partial = shift; # Use VlanCurrentTable if available since it will include dynamic # VLANs. However, some devices do not populate the table. + my $v_ports = $bridge->qb_cv_untagged() || $bridge->qb_v_untagged(); - # 11/07 - Todo: Issue with some devices trying to query VlanCurrentTable - # as table may grow very large with frequent VLAN changes. - # 06/08 - VlanCurrentTable may be due to timefilter, should query with - # zero partial for no time filter. - # my $v_ports = $bridge->qb_cv_egress() || $bridge->qb_v_egress(); + return $bridge->_vlan_hoa($v_ports, $partial); +} - my $v_ports = $bridge->qb_v_egress() || {}; +sub _vlan_hoa { + my $bridge = shift; + my ( $v_ports, $partial ) = @_; - my $i_vlan_membership = {}; + my $index = $bridge->bp_index(); + + my $vlan_hoa = {}; foreach my $idx ( keys %$v_ports ) { next unless ( defined $v_ports->{$idx} ); my $portlist = $v_ports->{$idx}; @@ -376,10 +400,10 @@ sub i_vlan_membership { my $ifindex = $index->{$port}; next unless ( defined($ifindex) ); # shouldn't happen next if ( defined $partial and $ifindex !~ /^$partial$/ ); - push( @{ $i_vlan_membership->{$ifindex} }, $vlan ); + push( @{ $vlan_hoa->{$ifindex} }, $vlan ); } } - return $i_vlan_membership; + return $vlan_hoa; } sub set_i_pvid { @@ -649,6 +673,12 @@ IDs. These are the VLANs which are members of the egress list for the port. print "Port: $port VLAN: $vlan\n"; } +=item $bridge->i_vlan_membership_untagged() + +Returns reference to hash of arrays: key = C, value = array of VLAN +IDs. These are the VLANs which are members of the untagged egress list for +the port. + =item $bridge->qb_i_vlan_t() Returns reference to hash: key = C, value = either 'trunk' for diff --git a/Info/Layer3/Enterasys.pm b/Info/Layer3/Enterasys.pm index e4b89838..e8650cec 100644 --- a/Info/Layer3/Enterasys.pm +++ b/Info/Layer3/Enterasys.pm @@ -149,11 +149,54 @@ sub i_duplex_admin { return $enterasys->mau_i_duplex_admin($partial); } -# LLDP table timefilter implementation continuously increments when walked +# TimeFilter implementation continuously increments when walked # and we may never reach the end of the table. This behavior can be # modified with the "set snmp timefilter break disable" command, # unfortunately it is not the default. Query with a partial value of zero -# which means no time filter. +# which means no time filter for tables with and index containing a +# TimeFilter + +sub qb_fw_vlan { + my $bridge = shift; + my $partial = shift; + + my $qb_fw_port = $bridge->qb_fw_port($partial); + # dot1qVlanCurrentTable TimeFilter index + my $qb_fdb_ids = $bridge->qb_cv_fdb_id(0) || {}; + + my $qb_fw_vlan = {}; + foreach my $idx ( keys %$qb_fw_port ) { + my ( $fdb_id, $mac ) = _qb_fdbtable_index($idx); + # Many devices do not populate the dot1qVlanCurrentTable, so default + # to FDB ID = VID, but if we have a mapping use it. + my $vlan = $fdb_id; + if ($qb_fdb_ids->{$fdb_id}) { + $vlan = $qb_fdb_ids->{$fdb_id}; + } + $qb_fw_vlan->{$idx} = $vlan; + } + return $qb_fw_vlan; +} + +sub i_vlan_membership { + my $bridge = shift; + my $partial = shift; + + # dot1qVlanCurrentTable TimeFilter index + my $v_ports = $bridge->qb_cv_egress(0) || $bridge->qb_v_egress(); + + return $bridge->_vlan_hoa($v_ports, $partial); +} + +sub i_vlan_membership_untagged { + my $bridge = shift; + my $partial = shift; + + # dot1qVlanCurrentTable TimeFilter index + my $v_ports = $bridge->qb_cv_untagged(0) || $bridge->qb_v_untagged(); + + return $bridge->_vlan_hoa($v_ports, $partial); +} sub lldp_ip { my $enterasys = shift;