=head1 NAME Net::SNMP::XS - speed up Net::SNMP by decoding in XS, with limitations =head1 SYNOPSIS use Net::SNMP::XS; # loading it is enough, there are no public symbols =head1 DESCRIPTION This module tries to speed up Net::SNMP response packet decoding. It does this by overriding a few selected internal method by (almost) equivalent XS methods. This currently reduces decode time by some 70%. There are currently the following limitations when using this module: =over 4 =item leading dots are required for iods =item error handling is currently broken (but parse errors will be detected) =item oid components are limited to unsigned 32 bit integers =item translation will be ignored (all values will be delivered "raw") =back =cut package Net::SNMP::XS; use strict qw(vars subs); no warnings; use Guard; use Net::SNMP::PDU (); use Net::SNMP::Message (); use Net::SNMP::MessageProcessing (); our $VERSION; our $old_prepare; BEGIN { $VERSION = '0.01'; $old_prepare = \&Net::SNMP::MessageProcessing::prepare_data_elements; # this overrides many methods inside require XSLoader; XSLoader::load Net::SNMP::XS, $VERSION; } sub Net::SNMP::MessageProcessing::prepare_data_elements { my ($self, $msg) = @_; set_msg $msg, $msg->{_buffer}; scope_guard \&clr_msg; &$old_prepare } # almost direct copy from Net::SNMP::Message, as we cannot access $process_methods { package Net::SNMP::Message; my @process_methods; $process_methods [INTEGER ] = \&_process_integer32; $process_methods [OCTET_STRING ] = \&_process_octet_string; $process_methods [NULL ] = \&_process_null; $process_methods [OBJECT_IDENTIFIER] = \&_process_object_identifier; $process_methods [SEQUENCE ] = \&_process_sequence; $process_methods [IPADDRESS ] = \&_process_ipaddress; $process_methods [COUNTER ] = \&_process_counter; $process_methods [GAUGE ] = \&_process_gauge; $process_methods [TIMETICKS ] = \&_process_timeticks; $process_methods [OPAQUE ] = \&_process_opaque; $process_methods [COUNTER64 ] = \&_process_counter64; $process_methods [NOSUCHOBJECT ] = \&_process_nosuchobject; $process_methods [NOSUCHINSTANCE ] = \&_process_nosuchinstance; $process_methods [ENDOFMIBVIEW ] = \&_process_endofmibview; $process_methods [GET_REQUEST ] = \&_process_get_request; $process_methods [GET_NEXT_REQUEST ] = \&_process_get_next_request; $process_methods [GET_RESPONSE ] = \&_process_get_response; $process_methods [SET_REQUEST ] = \&_process_set_request; $process_methods [TRAP ] = \&_process_trap; $process_methods [GET_BULK_REQUEST ] = \&_process_get_bulk_request; $process_methods [INFORM_REQUEST ] = \&_process_inform_request; $process_methods [SNMPV2_TRAP ] = \&_process_v2_trap; $process_methods [REPORT ] = \&_process_report; # should be done in XS sub process { # my ($this, $expected, $found) = @_; return $_[0]->_error if defined($_[0]->{_error}); return $_[0]->_error unless defined(my $type = _buffer_get($_[0], 1)); $type = unpack 'C', $type; if ($process_methods[$type]) { if (@_ >= 2 && (defined $_[1]) && $type != $_[1]) { return $_[0]->_error( 'Expected %s, but found %s', asn1_itoa($_[1]), asn1_itoa($type) ); } $_[2] = $type if (@_ == 3); $process_methods[$type]->($_[0], $type); } else { $_[0]->_error('Unknown ASN.1 type [0x%02x]', $type); } } } 1; =head1 AUTHOR Marc Lehmann http://home.schmorp.de/ =cut