Merge remote-tracking branch 'upstream/master'
[torrus-plus.git] / src / lib / Torrus / DevDiscover / CiscoIOS_MacAccounting.pm
blobfedfc373f2a23c5c985872c2feda4f33af23e9ae
1 # Copyright (C) 2002 Stanislav Sinyagin
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
17 # $Id$
18 # Stanislav Sinyagin <ssinyagin@yahoo.com>
20 # Cisco IOS MAC accounting
22 package Torrus::DevDiscover::CiscoIOS_MacAccounting;
23 use strict;
24 use warnings;
26 use Torrus::Log;
28 our $VERSION = 1.0;
30 $Torrus::DevDiscover::registry{'CiscoIOS_MacAccounting'} = {
31 'sequence' => 510,
32 'checkdevtype' => \&checkdevtype,
33 'discover' => \&discover,
34 'buildConfig' => \&buildConfig
38 our %oiddef =
40 # CISCO-IP-STAT-MIB
41 'cipMacHCSwitchedBytes' => '1.3.6.1.4.1.9.9.84.1.2.3.1.2',
45 sub checkdevtype
47 my $dd = shift;
48 my $devdetails = shift;
50 my $session = $dd->session();
52 if( $devdetails->isDevType('CiscoIOS') and
53 $dd->checkSnmpTable('cipMacHCSwitchedBytes') )
55 return 1;
58 return 0;
62 sub discover
64 my $dd = shift;
65 my $devdetails = shift;
67 my $session = $dd->session();
68 my $data = $devdetails->data();
70 my $table = $session->get_table( -baseoid =>
71 $dd->oiddef('cipMacHCSwitchedBytes'));
73 if( not defined($table) or scalar(keys %{$table}) == 0 )
75 return 0;
77 $devdetails->storeSnmpVars( $table );
79 # External storage serviceid assignment
80 my $extSrv =
81 $devdetails->paramString('CiscoIOS_MacAccounting::external-serviceid');
82 if( $extSrv ne '' )
84 my $extStorage = {};
85 my $extStorageTrees = {};
87 for my $srvDef ( split( /\s*,\s*/, $extSrv ) )
89 my ( $serviceid, $peerName, $direction, $trees ) =
90 split( /\s*:\s*/, $srvDef );
92 if( defined( $trees ) )
94 # Trees are listed with '|' as separator,
95 # whereas compiler expects commas
97 $trees =~ s/\s*\|\s*/,/g;
100 if( $direction eq 'Both' )
102 $extStorage->{$peerName}{'In'} = $serviceid . '_IN';
103 $extStorageTrees->{$serviceid . '_IN'} = $trees;
105 $extStorage->{$peerName}{'Out'} = $serviceid . '_OUT';
106 $extStorageTrees->{$serviceid . '_OUT'} = $trees;
108 else
110 $extStorage->{$peerName}{$direction} = $serviceid;
111 $extStorageTrees->{$serviceid} = $trees;
114 $data->{'cipMacExtStorage'} = $extStorage;
115 $data->{'cipMacExtStoragetrees'} = $extStorageTrees;
119 # tokenset members
120 # Format: tokenset:ASXXXX,ASXXXX; tokenset:ASXXXX,ASXXXX;
121 # Peer MAC or IP addresses could be used too
122 $data->{'cipTokensetMember'} = {};
123 for my $memList
124 ( split( /\s*;\s*/,
125 $devdetails->paramString
126 ('CiscoIOS_MacAccounting::tokenset-members') ) )
128 my ($tset, $list) = split( /\s*:\s*/, $memList );
129 for my $peerName ( split( /\s*,\s*/, $list ) )
131 $data->{'cipTokensetMember'}->{$peerName}{$tset} = 1;
135 Torrus::DevDiscover::RFC2011_IP_MIB::discover($dd, $devdetails);
136 Torrus::DevDiscover::RFC1657_BGP4_MIB::discover($dd, $devdetails);
138 for my $INDEX
139 ( $devdetails->
140 getSnmpIndices( $dd->oiddef('cipMacHCSwitchedBytes') ) )
142 my( $ifIndex, $direction, @phyAddrOctets ) = split( '\.', $INDEX );
144 my $interface = $data->{'interfaces'}{$ifIndex};
145 next if not defined( $interface );
147 my $phyAddr = '0x';
148 my $macAddrString = '';
149 for my $byte ( @phyAddrOctets )
151 $phyAddr .= sprintf('%.2x', $byte);
152 if( length( $macAddrString ) > 0 )
154 $macAddrString .= ':';
156 $macAddrString .= sprintf('%.2x', $byte);
159 next if ( $phyAddr eq '0xffffffffffff' );
161 my $peerIP = $interface->{'mediaToIpNet'}{$phyAddr};
162 if( not defined( $peerIP ) )
164 # Try in the global table, as the ARP is stored per subinterface,
165 # and MAC accounting is on main interface
166 $peerIP = $data->{'mediaToIpNet'}{$phyAddr};
169 if( not defined( $peerIP ) )
171 # high logging level, because who cares about staled entries?
172 Debug('Cannot determine IP address for MAC accounting ' .
173 'entry: ' . $macAddrString);
174 next;
177 # There should be two entries per IP: in and out.
178 if( defined( $data->{'cipMac'}{$ifIndex . ':' . $phyAddr} ) )
180 $data->{'cipMac'}{$ifIndex . ':' . $phyAddr}{'nEntries'}++;
181 next;
184 my $peer = {
185 'peerIP' => $peerIP,
186 'phyAddr' => $phyAddr,
187 'macAddrString' => $macAddrString,
188 'ifIndex' => $ifIndex,
189 'nEntries' => 1
192 $peer->{'macAddrOID'} = join('.', @phyAddrOctets);
194 $peer->{'ifReferenceName'} =
195 $interface->{$data->{'nameref'}{'ifReferenceName'}};
196 $peer->{'ifNick'} =
197 $interface->{$data->{'nameref'}{'ifNick'}};
200 my $desc =
201 $devdetails->paramString('peer-ipaddr-description-' .
202 join('_', split('\.', $peerIP)));
203 if( $desc ne '' )
205 $peer->{'description'} = $desc;
209 if( $devdetails->hasCap('bgpPeerTable') )
211 my $peerAS = $data->{'bgpPeerAS'}{$peerIP};
212 if( defined( $peerAS ) )
214 $peer->{'peerAS'} = $data->{'bgpPeerAS'}{$peerIP};
216 my $desc =
217 $devdetails->paramString('bgp-as-description-' . $peerAS);
218 if( $desc ne '' )
220 if( defined( $peer->{'description'} ) )
222 Warn('Conflicting descriptions for peer ' .
223 $peerIP);
225 $peer->{'description'} = $desc;
228 elsif( $devdetails->paramEnabled
229 ('CiscoIOS_MacAccounting::bgponly') )
231 next;
235 if( defined( $peer->{'description'} ) )
237 $peer->{'description'} .= ' ';
239 $peer->{'description'} .= '[' . $peerIP . ']';
241 $data->{'cipMac'}{$ifIndex . ':' . $phyAddr} = $peer;
244 my %asNumbers;
245 for my $INDEX ( keys %{$data->{'cipMac'}} )
247 my $peer = $data->{'cipMac'}{$INDEX};
249 if( $peer->{'nEntries'} != 2 )
251 delete $data->{'cipMac'}{$INDEX};
253 else
255 if( defined( $peer->{'peerAS'} ) )
257 $asNumbers{$peer->{'peerAS'}}++;
262 for my $INDEX ( keys %{$data->{'cipMac'}} )
264 my $peer = $data->{'cipMac'}{$INDEX};
266 my $subtreeName = $peer->{'peerIP'};
267 my $asNum = $peer->{'peerAS'};
268 if( defined( $asNum ) )
270 $subtreeName = 'AS' . $asNum;
271 if( $asNumbers{$asNum} > 1 )
273 $subtreeName .= '_' . $peer->{'peerIP'};
276 $peer->{'subtreeName'} = $subtreeName;
279 return 1;
283 sub buildConfig
285 my $devdetails = shift;
286 my $cb = shift;
287 my $devNode = shift;
289 my $data = $devdetails->data();
291 my $countersNode =
292 $cb->addSubtree( $devNode, 'MAC_Accounting',
293 {'node-display-name' => 'MAC Accounting'},
294 ['CiscoIOS_MacAccounting::cisco-macacc-subtree']);
296 for my $INDEX ( sort { $data->{'cipMac'}{$a}{'subtreeName'} <=>
297 $data->{'cipMac'}{$b}{'subtreeName'} }
298 keys %{$data->{'cipMac'}} )
300 my $peer = $data->{'cipMac'}{$INDEX};
302 my $param = {
303 'peer-macaddr' => $peer->{'phyAddr'},
304 'peer-macoid' => $peer->{'macAddrOID'},
305 'peer-ipaddr' => $peer->{'peerIP'},
306 'interface-name' => $peer->{'ifReferenceName'},
307 'interface-nick' => $peer->{'ifNick'},
308 'comment' => $peer->{'description'},
309 'descriptive-nickname' => $peer->{'subtreeName'},
310 'precedence' => 65000 - $peer->{'peerAS'},
311 'searchable' => 'yes'
314 my $peerNode = $cb->addSubtree
315 ( $countersNode, $peer->{'subtreeName'}, $param,
316 ['CiscoIOS_MacAccounting::cisco-macacc'] );
318 if( defined( $data->{'cipMacExtStorage'} ) or
319 defined( $data->{'cipTokensetMember'} ) )
321 my $extStorageApplied = 0;
322 my $tsetMemberApplied = 0;
324 for my $peerName ( 'AS'.$peer->{'peerAS'}, $peer->{'peerIP'},
325 $peer->{'phyAddr'} )
327 if( defined( $peerName ) )
329 if( not $extStorageApplied and
330 defined( $data->{'cipMacExtStorage'}{$peerName} ) )
332 my $extStorage =
333 $data->{'cipMacExtStorage'}{$peerName};
334 for my $dir ( 'In', 'Out' )
336 if( defined( $extStorage->{$dir} ) )
338 my $serviceid = $extStorage->{$dir};
340 my $params = {
341 'storage-type' => 'rrd,ext',
342 'ext-service-units' => 'bytes',
343 'ext-service-id' => $serviceid };
345 if( defined( $data->{'cipMacExtStoragetrees'}{
346 $serviceid}) and
347 length( $data->{'cipMacExtStoragetrees'}{
348 $serviceid}) > 0 )
350 $params->{'ext-service-trees'} =
351 $data->{'cipMacExtStoragetrees'}{
352 $serviceid};
355 $cb->addLeaf
356 ( $peerNode, 'Bytes_' . $dir,
357 $params );
360 $extStorageApplied = 1;
363 if( not $tsetMemberApplied and
364 defined( $data->{'cipTokensetMember'}{$peerName} ) )
366 my $tsetList =
367 join( ',', sort keys
368 %{$data->{'cipTokensetMember'}{$peerName}} );
370 $cb->addLeaf
371 ( $peerNode, 'InOut_bps',
372 { 'tokenset-member' => $tsetList } );
379 return;
387 # Local Variables:
388 # mode: perl
389 # indent-tabs-mode: nil
390 # perl-indent-level: 4
391 # End: