2

I'm using snmp4j to try and perform SNMP functions against a remote agent. Due to a number of limitations out of our control I need to perform a GETBULK to obtain a large table in a short space of time.

My current implementation:

public Map<String, String> doGetBulk(@NotNull VariableBinding... vbs)  
        throws IOException {

        Map<String, String> result = new HashMap<>();
        Snmp snmp = null;

        try {

            // Create TransportMapping and Listen
            TransportMapping transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);
            transport.listen();

            PDU pdu = new PDU();
            pdu.setType(PDU.GETBULK);
            pdu.setMaxRepetitions(200);
            pdu.setNonRepeaters(0);
            pdu.addAll(vbs);

            ResponseEvent responseEvent = snmp.send(pdu, this.target);
            PDU response = responseEvent.getResponse();

            // Process Agent Response
            if (response != null) {
                for(VariableBinding vb : response.getVariableBindings()) {
                    result.put("." + vb.getOid().toString(), vb.getVariable().toString());
                }
            } else {
                LOG.error("Error: Agent Timeout... ");
            }

        } catch (NullPointerException ignore) {
            // The variable table is null
        } finally {
            if (snmp != null) snmp.close();
        }
        return result;
    }

However, this only ever returns 100 results when I know there are 5000+. I know I cant exceed the PDU size so I have so problem with the response being truncated into blocks of 100 but I cant work out how I can get a handle to cascade the request to get the next 100 entries.

tarka
  • 5,289
  • 10
  • 51
  • 75

3 Answers3

0

It is bad practice to use MaxRepetitions > 100 due to TCP/IP packet fragmentation and the nature of UDP that does not guarantee the order of packets. So most SNMP frameworks and agents have such built-in limit.

Andrew Komiagin
  • 6,446
  • 1
  • 13
  • 23
0

All details are already there in the RFC document,

https://www.rfc-editor.org/rfc/rfc1905

4.2.3 tells how the agent side should handle GET BULK requests, and

While the maximum number of variable bindings in the Response-PDU is
bounded by N + (M * R), the response may be generated with a lesser
number of variable bindings (possibly zero) for either of three
reasons.

(1) If the size of the message encapsulating the Response-PDU containing the requested number of variable bindings would be greater than either a local constraint or the maximum message size of the originator, then the response is generated with a lesser number of variable bindings. This lesser number is the ordered set of variable bindings with some of the variable bindings at the end of the set removed, such that the size of the message encapsulating the Response-PDU is approximately equal to but no greater than either a local constraint or the maximum message size of the originator. Note that the number of variable bindings removed has no relationship to the values of N, M, or R.

(2) The response may also be generated with a lesser number of variable bindings if for some value of iteration i, such that i is greater than zero and less than or equal to M, that all of the generated variable bindings have the value field set to the `endOfMibView'. In this case, the variable bindings may be truncated after the (N + (i * R))-th variable binding.

(3) In the event that the processing of a request with many repetitions requires a significantly greater amount of processing time than a normal request, then an agent may terminate the request with less than the full number of repetitions, providing at least one repetition is completed.

About how to do a series of proper GET BULK operations to query all data you want, you can refer to section 4.2.3.1 for an example.

Community
  • 1
  • 1
Lex Li
  • 60,503
  • 9
  • 116
  • 147
0

You've set maximum repetition count to 200, that is the server may send you at most 200 rows. So on the one hand, you'll never get more than 200 rows (and least of all 5000 or more). On the other hand, the server may decide to send you less rows, it's practically the server's choice; you tell him what you're able to process.

Usually you request 10-50 rows at max. (BTW: There are many servers out there with buggy SNMP implementations and the higher you set max-repetitions, the higher is the chance you get nothing at all.)

So you have to request row set by row set. Since you probably don't want to implement that yourself I'd recommend to use the TableUtils class. Just start with getTable().

steffen
  • 16,138
  • 4
  • 42
  • 81