#!/usr/bin/perl ### ### Copyright (C) 2016 Alexander Gall ### ### This program is free software: you can redistribute it and/or ### modify it under the terms of the GNU General Public License as ### published by the Free Software Foundation, either version 3 of the ### License, or (at your option) any later version. ### ### This program is distributed in the hope that it will be useful, ### but WITHOUT ANY WARRANTY; without even the implied warranty of ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ### General Public License for more details. ### ### You should have received a copy of the GNU General Public License ### along with this program. If not, see . use strict; use warnings; use Getopt::Long; use Snabb::SNMP::Agent qw(%persistent_ifIndex %compound_scalar_handlers); my %opt = ( 'check-interval' => 5, 'mibs-dirs' => '', 'shmem-dir' => '/var/lib/snabb/shmem'); sub usage() { print <<"EOF"; usage: $0 --ifindex= EOF exit(1); } ## Mappings of PW shared memory segments to the index of the ## pwTable/cpwVcTable my %pwIndex; my $pwIndex = 1; ## Indexer for pwTable/cpwVcTable. It uses the name of the segment ## that represents a row in these tables to generate the index. sub pw_indexer($$$) { my ($oid, $table_oid, $segment) = @_; my $name = $segment->{name}; my $index = $pwIndex{$name}; unless (defined $index) { $index = $pwIndex++; print("Allocating PW index $index for segment $name\n"); $pwIndex{$name} = $index; } return $oid.".".$index; } ## Indexer for the pwEnetTable. It has two indexes. The first is the ## pwIndex according to the pw_indexer. the second is the value of ## the pwEnetPwInstance object. sub pw_enet_indexer($$$) { my ($oid, $table_oid, $segment) = @_; $oid = pw_indexer($oid, $table_oid, $segment); my $pwEnetPwInstance_obj = $segment->{objs}{pwEnetPwInstance}; defined $pwEnetPwInstance_obj or die "pw_enet_indexer: no pwEnetPwInstance present for segment " ."$segment->{name}"; tie my $pwEnetPwInstance, 'Snabb::SNMP::Tie::INTEGER', $segment, 'pwEnetPwInstance'; return $oid.".".$pwEnetPwInstance; } ## Indexer for the cpwVcEnetTable. It has two indexes. The first is ## the cpwVcIndex according to the pw_indexer. the second is the value ## of the cpwVcEnetPwVlan object. sub cpw_enet_indexer($$$) { my ($oid, $table_oid, $segment) = @_; $oid = pw_indexer($oid, $table_oid, $segment); my $cpwVcEnetPwVlan_obj = $segment->{objs}{cpwVcEnetPwVlan}; defined $cpwVcEnetPwVlan_obj or die "cpw_enet_indexer: no cpwVcEnetPwVlan present for segment " ."$segment->{name}"; tie my $cpwVcEnetPwVlan, 'Snabb::SNMP::Tie::INTEGER', $segment, 'cpwVcEnetPwVlan'; return $oid.".".$cpwVcEnetPwVlan; } my %subtrees = ( cpwVcMIB => { tables => { scalars => { handlers => { cpwVcIndexNext => { compound_handler => sub { return $pwIndex; } }, cpwVcPerfTotalErrorPackets => { compound_handler => $compound_scalar_handlers{accumulator} }, }, }, cpwVcTable => { indexer => \&pw_indexer, }, }, }, pwStdMIB => { tables => { scalars => { handlers => { pwIndexNext => { compound_handler => sub { return $pwIndex; } }, pwPerfTotalErrorPackets => { compound_handler => $compound_scalar_handlers{accumulator} }, }, }, pwTable => { indexer => \&pw_indexer, }, }, }, cpwVcEnetMIB => { tables => { cpwVcEnetTable => { indexer => \&cpw_enet_indexer, handlers => { cpwVcEnetPortIfIndex => { handler => sub { my ($value, $name, $segment) = @_; my $aux_name = "_X_$name"; exists $segment->{objs}{$aux_name} or die "$name handler: auxiliary object $aux_name does not exist"; tie my $ifDescr, 'Snabb::SNMP::Tie::OCTETSTR', $segment, $aux_name; my $ifIndex = $persistent_ifIndex{$ifDescr}; defined $ifIndex or die "$name handler: unknown interface $ifDescr"; return($ifIndex); } }, }, }, }, }, pwEnetStdMIB => { tables => { pwEnetTable => { indexer => \&pw_enet_indexer, handlers => { pwEnetPortIfIndex => { handler => sub { my ($value, $name, $segment) = @_; my $aux_name = "_X_$name"; exists $segment->{objs}{$aux_name} or die "$name handler: auxiliary object $aux_name does not exist"; tie my $ifDescr, 'Snabb::SNMP::Tie::OCTETSTR', $segment, $aux_name; my $ifIndex = $persistent_ifIndex{$ifDescr}; defined $ifIndex or die "$name handler: unknown interface $ifDescr"; return($ifIndex); } }, }, }, }, }, ); GetOptions(\%opt, "check-interval=i", "mibs-dirs=s", "ifindex=s", "shmem-dir=s") or usage(); defined $opt{ifindex} or usage(); Snabb::SNMP::Agent::start({ name => "pseudowire", subtrees => \%subtrees, check_interval => $opt{'check-interval'}, if_index => $opt{ifindex}, mibs_dirs => $opt{'mibs-dirs'}, mibs => 'CISCO-SMI:CISCO-IETF-PW-TC-MIB' .':CISCO-IETF-PW-MIB:PW-STD-MIB' .':CISCO-IETF-PW-ENET-MIB:PW-ENET-STD-MIB', shmem_dir => $opt{'shmem-dir'}, }); ## Not reached ## Local Variables: ## mode: CPerl ## End: