Multi(3pm)
π SNMP::Multi β like, the whole vibe π
SNMP::Multi(3pm) β User Contributed Perl Documentation β SNMP::Multi(3pm)
okay bestie, pull up a chair π«Ά you're about to learn how to do SNMP on a whole bunch of hosts at once and honestly? it's giving main character energy.
β¨ NAME β¨
SNMP::Multi β Perform SNMP operations on multiple hosts simultaneously. no cap. that's literally the whole job. π
π¦ SYNOPSIS π¦
here's the whole thing, verbatim, because I would never do you dirty like that:
use SNMP::Multi;
my $req = SNMP::Multi::VarReq->new (
nonrepeaters => 1,
hosts => [ qw/ router1.my.com router2.my.com / ],
vars => [ [ 'sysUpTime' ], [ 'ifInOctets' ], [ 'ifOutOctets' ] ],
);
die "VarReq: $SNMP::Multi::VarReq::error\n" unless $req;
my $sm = SNMP::Multi->new (
Method => 'bulkwalk',
MaxSessions => 32,
PduPacking => 16,
Community => 'public',
Version => '2c',
Timeout => 5,
Retries => 3,
UseNumeric => 1,
# Any additional options for SNMP::Session::new() ...
)
or die "$SNMP::Multi::error\n";
$sm->request($req) or die $sm->error;
my $resp = $sm->execute() or die "Execute: $SNMP::Multi::error\n";
print "Got response for ", (join ' ', $resp->hostnames()), "\n";
for my $host ($resp->hosts()) {
print "Results for $host: \n";
for my $result ($host->results()) {
if ($result->error()) {
print "Error with $host: ", $result->error(), "\n";
next;
}
print "Values for $host: ", (join ' ', $result->values());
for my $varlist ($result->varlists()) {
print map { "\t" . $_->fmt() . "\n" } @$varlist;
}
print "\n";
}
}
likeβ¦ look at it. one request object, a whole list of hosts, and it just goes. π
πΈ DESCRIPTION πΈ
so the SNMP::Multi package? it's a mechanism for doing SNMP operations on several hosts at the same time. iconic behavior honestly.
SNMP::Multi builds on G. Marzot's SNMP Perl interface to the UC-Davis SNMP libraries, and it uses asynchronous SNMP operations to send queries/sets to multiple hosts simultaneously. yes, all of them. at once. she doesn't wait around. π
Results from all hosts get compiled into a single object, and that object is serving methods to access the data either in aggregate, or broken down by host, or broken down by the individual request. choose your own adventure bestie π
SNMP::Multi supports SNMP GET, SET, GETNEXT, GETBULK and BULKWALK requests. It also performs PDU packing in order to improve network efficiency, when packing is possible. efficiency queen π
π OPTIONS π
The SNMP::Multi constructor takes the following options to control its behavior. Any other options are stored and handed to the SNMP::Session constructor when a new SNMP session is created. And because SNMP::Multi's behavior depends on certain SNMP::Session parameters (i.e. Timeout), those get listed below as SNMP::Multi options too. These "overlapped" options get passed un-changed to SNMP::Session's constructor. no edits, no remix, straight through π«Ά
`Method`β Specify one ofget,set,getnext,getbulkorbulkwalk. The appropriate SNMP request will be made to each host for each set of variables requested by the user.
β This parameter is required. There is no default value. like, you gotta say something, bestie, she's not a mind reader π
`Requests`β TheSNMP::Multiobject may be given a new set of requests via therequest()method, or by passing a reference to anSNMP::Multi::VarReqobject into the constructor. AnyVarReqrequests given to theSNMP::Multiobject through the constructor will be overwritten by subsequent calls toSNMP::Multi::request(). so like, the constructor ones are placeholders at best, fr fr.
This parameter is optional.
`PduPacking`β The maximum number of variable requests that will be packed into a single SNMP request is controlled by thePduPackingparameter. PDU packing improves the efficiency and accuracy of SNMP requests by reducing the number of packets exchanged. Setting this variable to'0'will disable PDU packing altogether. PDU packing is not performed for SNMPGETBULKorBULKWALKrequests. (getbulk/bulkwalk said "we're good actually" π)
This optional parameter defaults to the value of $SNMP::Multi::pdupacking.
`MaxSessions`β This variable controls the maximum number of SNMP sessions that will be kept open simultaneously. SettingMaxSessionshigher increases the number of agents being queried at any time, up to the maximum limit of file descriptors available to the process.SNMP::Multidetects "out of resources" conditions (i.e.EMFILE) and adjusts the number of open connections accordingly. she adapts. she's flexible. she's that girl π
This optional parameter defaults to the value of $SNMP::Multi::maxsessions.
`Concurrent`β The value ofConcurrentlimits the number of requests that may be "in flight" at any time. It defaults to the value ofMaxSessions(see above). Setting this value higher may reduce the overall runtime of theSNMP::Multirequest, but will also likely increase network traffic and congestion (current maintainer has hadSNMP::Multirunning smoothly with concurrent set to512). so 512 is lowkey the vibe. π
This optional parameter defaults to the value of$SNMP::Multi::maxsessionsor the object's'MaxSessions'parameter.
`GetbulkMax`β Sets the default "maxrepetitions" value for SNMPGETBULKandBULKWALKrequests. This value may be overridden on a per-request basis (by specifying the'maxrepetitions'parameter in theSNMP::Multi::VarReqconstructor). per-request overrides are such a slay π
This optional parameter defaults to the value of $SNMP::Multi::getbulkmax.
`ExternalSelect`β IfExternalSelectis specified, theSNMP::Multi'sexecute()method will return immediately after dispatching the first volley of SNMP requests. The caller can then useSNMP::select_info()to get a list of the current file descriptors for the SNMP sessions, andselect()on them. When one of the fd's becomes readable, it should be handed toSNMP::reply_cb()to handle it. you're driving now, bestie π
β οΈ Note that SNMP bulkwalks use the callbacks to dispatch continuingGETBULKrequests. This causes the file descriptor to be readable, butSNMP::reply_cb()calls an internal callback inSNMP.xs's bulkwalk implementation, not theSNMP::Multihandler callback. When the walk completes, theSNMP::Multicallback will be called with the specified arguments. iykyk π§
`Retries`(shared withSNMP::Session) β TheRetriesoptions specifies the maximum number of retries for each SNMP request. Note that this is the number of retries, not the total number of attempted requests. subtle but so important, don't let it trip you π
This optional parameter defaults to the value of $SNMP::Multi::maxretries.
`Timeout`(shared withSNMP::Session) β TheTimeoutparameter specifies the timeout in seconds between successive retries for SNMP requests. The overall runtime for the completeSNMP::Multirequest will be approximately :
(retries + 1) * timeout
Please note that this is the lower-bound on the time-out. Without sufficient resources (especially file descriptors) to optimize the network communications, completing all requested SNMP operations can take considerably longer. π
An over-all timeout may be specified as the optional "timeout" parameter to the SNMP::Multi's execute() method.
This optional parameter defaults to the value of $SNMP::Multi::timeout.
`Community`(shared withSNMP::Session) β TheCommunityparameter specifies the SNMP community string to use when making requests from SNMP agents. No mechanism exists at this time to specify a different community for individual agents. one community for everybody, that's the rule π«Ά
This optional parameter defaults to the value of $SNMP::Multi::community.
`Version`(shared withSNMP::Session) β TheVersionoption specifies the SNMP protocol to use with the agents. Due to the poor error reporting in SNMP v1, it is recommended that SNMPv2corv3be used to communicate with the agents when possible. v1 could never, and I said what I said π
This optional parameter defaults to the value of $SNMP::Multi::snmpversion.
β¨ METHODS β¨
Okay bestie, the SNMP::Multi object hands you a whole lil toolbox of methods. In most cases you literally only need new(), request(), and execute() β the rest is just there for when you're feeling extra. They're documented in roughly the order you'd call them, so it reads like a lil story. π
SNMP::Multi::new(...)β makes you a shiny new instance of anSNMP::Multiobject. The constructor options? Scroll up, they're described above. πSNMP::Multi::request( <ref to SNMP::Multi::VarReq> )βrequest()takes the whole set of host/variable requests living inside thatSNMP::Multi::VarReqobject and hands them over to theSNMP::Multiobject. You could also just do this in the constructor with therequestsoption, but where's the fun in that. π
Not me forgetting this: therequest()method is NOT cumulative β every new call torequest()straight up overwrites the previous requests. Previous requests are gone. Poof. π
SNMP::Multi::execute( [timeout] )β theexecute()function does the actual work inSNMP::Multi, and it returns once every request has been answered or has timed out. There's an optionaltimeoutargument you can pass toexecute(), which sets an overall timeout β doesn't matter how many retries there are or when they happen, this is the big-picture deadline. β°
execute() hands back a reference to an SNMP::Multi::Response object, and that object has methods to grab the returned data values all conveniently-like. π«Ά
SNMP::Multi::error()β if something goes sideways whileSNMP::Multiis executing, you can callerror()to pull out a descriptive string telling you what went wrong. πSNMP::Multi::remaining( $req )β this one's iconic.remaining()produces anSNMP::Multi::VarReqstuffed with the requests for any un-answered or un-sent request hunks. You can then pass thatVarReqto anotherSNMP::Multiobject (or the same one, we don't judge). This is how an app loops on timeouts, like so:
my $req = SNMP::Multi::VarReq->new( ... );
my $sm = SNMP::Multi->new( ... );
while ($req) {
$sm->request($req);
my $resp = $sm->execute();
handle_response($resp);
print "Timeout - retrying" if ($req = $sm->remaining());
}
And here's the glow-up: you can accumulate remaining requests by passing an already existing SNMP::Multi::VarReq object as an argument. The remaining requests get added onto that object. That means you can collect all the remaining ones with ease while looping over a huge number of hosts. Main character efficiency, honestly. π
πΈ Building SNMP::Multi::VarReq Requests πΈ
SNMP variable requests get composed and passed to the SNMP::Multi object through a lil auxiliary class called an SNMP::Multi::VarReq. This class is basically a little collector β it gathers SNMP requests for variables and hosts (and it can optionally validate them too, if you want). π§Ί
The interface to SNMP::Multi::VarReq is super simple, like, only new() and add() methods. They take these arguments:
'vars' => [ list of Varbinds to be requested (REQUIRED) ]
'hosts' => [ list of hosts for this variable list ]
'nonrepeaters' => [ GETBULK/BULKWALK "nonrepeaters" parameter ]
'maxrepetitions' => [ GETBULK/BULKWALK "maxrepetitions" parameter ]
Every single call to new() or add() must contain a list of SNMP variables β that part is not optional, bestie. If you don't specify the hosts parameter, the variable list gets requested from all hosts currently known by the SNMP::Multi::VarReq object. And if you do give a host list? Then the variables get requested only from those named hosts. π¦
Some simple sanity checks can be run on the VarReq by calling its validate() method, or by setting $SNMP::Multi::VarReq::autovalidate to 1 before you call new(). π
Here's an example of building up a complicated request with new() and add():
Start with:
$r = SNMP::Multi::VarReq->new(
hosts => [ qw/ A B C / ],
vars => [ qw/ 1 2 3 / ]
);
to get:
A: 1 2 3
B: 1 2 3
C: 1 2 3
Now add a var to each host:
$r->add( vars => [ qw/ 4 / ] );
to get:
A: 1 2 3 4
B: 1 2 3 4
C: 1 2 3 4
Add a var to a specific set of hosts:
$r->add( hosts => [ qw/ A C / ],
vars => [ qw/ 5 / ] );
to get:
A: 1 2 3 4 5
B: 1 2 3 4
C: 1 2 3 4 5
Finally, create two new hosts and add a pair of vars to them:
$r->add( hosts => [ qw/ D E / ],
vars => [ qw/ 6 7 / ] );
to get:
A: 1 2 3 4 5
B: 1 2 3 4
C: 1 2 3 4 5
D: 6 7
E: 6 7
The SNMP::Multi::VarReq object also gives you a dump() method, which generates a simple dump of the current host/var requests. Perfect for when you're like "what is even in here rn". π
π₯ SNMP PDU Packing Features π₯
SNMP::Multi packs SNMP::Varbind requests into bigger request "hunks" so it needs fewer request/response pairs to finish the whole SNMP::Multi request. This packing is controlled by the SNMP::Multi 'PduPacking' parameter. π¦
For instance β say your app creates an SNMP::Multi object with a 'PduPacking' value of 3. SNMP::Multi will pack 5 single SNMP variable requests into two distinct requests. The first request holds the first 3 variables, and the second one gets the remaining two. Math! Slay. β¨
Heads up though: PDU packing is not done for SNMPGETBULKandBULKWALKrequests. And you can disable the whole feature by setting the'PduPacking'parameter to'0'. π
π Accessing SNMP Data From Agent Responses π
The SNMP::Multi::execute() method returns the responses from the SNMP agents inside an SNMP::Multi::Response object. This object is indexed by hostname, and it's made up of per-host response objects (SNMP::Multi::Response::Host's), each one containing a list of SNMP::Multi::Result objects. Those Result objects are what connect an SNMP::VarList with the error status (if there is one) from the SNMP request. And listen β an entry only gets made in the Response object if the SNMP agent actually returned some response to SNMP::Multi. No response, no entry. π
This is fairly complicated, ngl, but the various objects provide accessor methods so getting at the SNMP responses stays simple. Assume your application is structured something like this example source code:
my $req = SNMP::Multi::VarReq->new( hosts => [...],
vars => [...] );
my $sm = SNMP::Multi->new( ... requests => $req, ... );
my $response = $sm->execute( $overall_timeout );
die $sm->error() if $sm->error();
Now you can get at the data through methods on the objects that make up the SNMP::Multi::Response returned by execute(). An SNMP::VarList object gets returned for each variable requested, which normalizes the return format across all SNMP operations (yes, including bulkwalks). π
Peep the SYNOPSIS section above for an example of how to access the SNMP data values after calling the execute() method. β
π SNMP::Multi::Response methods π
hostnames()β returns a list of the hosts that responded to the SNMP queries made byexecute(). πvalues()β returns all values returned by the SNMP agents, collated into one single list. Use this when your app doesn't care which value came from which specific host (iykyk β like summing up octet counts on router interfaces). πhosts()β returns a list ofSNMP::Multi::Response::Hostobjects, one per host queried by theSNMP::Multi::execute()method. π
π¦ SNMP::Multi::Response::Host methods π¦
hostname()β returns the hostname associated with this set of responses. You can also just stringify the reference to get the hostname:
print "This is the list of results for $host: \n";
values()β returns all values received in response to requests made to the associated host. πresults()β returns a list ofSNMP::Multi::Resultobjects for this host. There's oneResultobject for each request sent to the SNMP agent on this host. β¨
π SNMP::Multi::Result methods π
The SNMP::Multi::Result object correlates SNMP error information with the response to an SNMP request.
error()β returns a printable string describing the error encountered for this variable, orundefif no error occurred. π«Άvalues()β returns a list of the values received for this request.varlists()β returns an array ofSNMP::VarListobjects, one per variable requested in the SNMP packet. This format stays consistent across all SNMP operations, and it's required to support bulkwalks (where the number of returned values per variable isn't known a priori by the calling application). No cap. π₯
π EXAMPLES π
A complete example is given in the "SYNOPSIS" section above. Go look, bestie, it's right there. π
π CAVEATS π
The VarList returned for GETBULK requests is "decoded" by SNMP::Multi into an array of single VarLists, one for each requested variable. This behavior differs from the return from the getbulk() method in the SNMP.pm module β but it is consistent with the return value of SNMP.pm's bulkwalk() method. Consistency where it counts. β¨
Also, note that the V1 SNMP protocol has very limited error reporting (the agent returns no values, and the 'errind' is set to the index of the offending SNMP variable request). The SNMP::Multi module adjusts the 'errind' index so it indicates which of the variable requests made for a host have failed, regardless of how many actual packets got exchanged. This is necessary to support SNMP::Multi's transparent pdu-packing feature. π§
SNMP::Multi relies on features added to the SNMP module by Electric Lightwave, Inc. These features have been incorporated into UCD-SNMP releases 4.2 and later. So you must have SNMP 4.2 or later installed to use this package. Periodt. π
UsingSNMP::Multiwith large numbers of hosts or large requests may cause network congestion. π All targets may send PDU's to the originating host simultaneously, which could cause heavy traffic and/or dropped packets at the host. Adjusting theConcurrentandPduPackingvariables can mitigate this problem. Tune those knobs, bestie.
Network congestion may be a serious problem for bulkwalks, because multiple packets get exchanged per session. However, network latency and variable target response times cause packets in multiple bulkwalk exchanges to become spread out as the walk progresses. The initial exchange, though? That one will always cause congestion. Every time. π
π BUGS π
okay so bestie, there's one lil thing missing and we gotta be honest about it:
- There is no interface to specify a different SNMP community string for a specific host. even though the community is stored on a per-host basis. so like... the data's there, the vibes are there, the API just isn't giving π
β¨ SEE ALSO β¨
go touch some grass in these other docs, fr fr:
SNMP- the NetSNMP homepage at http://www.net-snmp.org/
π AUTHOR π
this absolute icon wrote it:
- Karl ("Terminator rAT") Schilke <rat@eli.net>
yes the nickname is real and yes it eats every single time π«Ά
π«Ά CONTRIBUTORS π«Ά
the besties who helped carry:
- Joshua Keroes
- Todd Caine
- Toni Prug <tony@irational.org>
π COPYRIGHT π
okay so legal moment, but make it cute:
- Developed by Karl "Terminator rAT" Schilke for Electric Lightwave, Inc.
- Copyright (c) 2000-2002 Electric Lightwave, Inc. All rights reserved.
- Co-maintained by Toni Prug.
This software is provided ``as is'' and without any express or implied warranties, including, without limitation, the implied warranties of merchantibility and/or fitness for a particular purpose.
translation: no promises, bestie, use at your own risk π
This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. slay, open source royalty β¨
π POD ERRORS π
not me exposing the doc's messy era but okay, the pod parser said the above document had some coding errors, and here's exactly what it clocked:
- Around line 93:
'=item' outside of any '=over'
- Around line 250:
You forgot a '=back' before '=head1'
- Around line 257:
'=item' outside of any '=over'
- Around line 268:
You can't have =items (as at line 277) unless the first thing after the =over is an =item
- Around line 326:
You forgot a '=back' before '=head1'You forgot a '=back' before '=head1'
- Around line 444:
'=item' outside of any '=over'
- Around line 480:
'=item' outside of any '=over'
- Around line 551:
You forgot a '=back' before '=head1'
it's giving "the pod was fighting for its life" but the content still ate, so we move π§
and that's the whole page, bestie β this lil manual page is from perl v5.32.0 and it was dated 2021-01-05. go forth and SNMP responsibly πβ¨
π¦ where this page comes from
- ubuntu jammy: libsnmp-multi-perl 2.1-4.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms