pysnmp icon indicating copy to clipboard operation
pysnmp copied to clipboard

Asyncio bulkCmd and nextCmd returning one additional entry

Open ICKGeek opened this issue 4 years ago • 2 comments

Hi,

I am trying to use async bulkCmd and nextCmd for obtaining the SNMP details. With this usage, I am observing that one additional entry is returned. Below is the snippet of the code

        oid = '.1.3.6.1.4.1.9.9.23.1.2.1'
        varBinds = [ObjectType(ObjectIdentity(oid))]
        initialVarBinds = varBinds

        while True:
            (errorIndication, errorStatus, errorIndex, varBindTable) = await bulkCmd(
                snmpEngine, CommunityData(switch_pwd, mpModel=0), UdpTransportTarget((switch_ip, 161)),
                ContextData(), 0, 50, *varBinds, lexicographicMode=False)

            if errorIndication:
                print(errorIndication)
                break
            elif errorStatus:
                print('%s at %s' % (
                    errorStatus.prettyPrint(),
                    errorIndex and varBinds1[int(errorIndex) - 1][0] or '?'))
                break
            else:
                for varBindRow in varBindTable:
                    for idx, varBind in enumerate(varBindRow):
                        print(' = '.join([x.prettyPrint() for x in varBind]))

                varBinds = varBindTable[-1]
                if isEndOfMib(varBinds):
                    break

                for varBind in varBinds:
                    if initialVarBinds[0][idx] and initialVarBinds[0][idx].isPrefixOf(varBind[0]):
                        break

                else:
                    break

This prints below entries (Removed the RHSS values in below print statements)

SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.3.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.4.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.5.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.6.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.7.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.8.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.9.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.10.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.11.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.12.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.2.1.1.24.10048.14 = <..>
SNMPv2-SMI::enterprises.9.9.23.1.3.1.0 = 1

if I don't use "async", I don't see the last entry(which is SNMPv2-SMI::enterprises.9.9.23.1.3.1.0 = 1). Why I am seeing this one additional entry when async is used with await? Do I have to exit in some other conditions also to avoid this?

I am using pysnmp 4.4.9

Thanks

ICKGeek avatar Aug 06 '19 20:08 ICKGeek

Can someone please help me with above query?

Thanks

ICKGeek avatar Aug 20 '19 05:08 ICKGeek

The additional entry that is out of scope does not appear with synchronous PySNMP, because of the lexicographicMode option set to False (like you also did in your snippet). But when using asyncio-PySNMP there is no lexicographicMode option for nextCmd and bulkCmd, so they should behave like the lexicographicMode option set to True.

That's why this issue appears only for asyncio bulk/next queries...

Your snippet doesn't catch this case, as

  • It first prints the obtained varBinds, and than checks whether the obtained object OID is out of scope
  • Your last for-loop, that checks for out-of-scope, will only break the while-loop if all varBinds have an out-of-scope OID

I suggest you could check every varBind whether it is out-of-scope before printing. Using the following code as the else-clause should make your snippet work:

end = False
for varBindRow in varBindTable:
    if not initialVarBinds[0][0].isPrefixOf(varBindRow[0][0]):
        # GETNEXT/GETBULK returned something out of scope of the requested OIDs
        end = True
        break

    for varBind in varBindRow:
        print(' = '.join([x.prettyPrint() for x in varBind]))

# For next request
varBinds = varBindTable[-1]

if end or isEndOfMib(varBinds):
    break

(It would be possible with an else clause for the for-loop instead of the end variable too, but I find this easier to read...)

I hope that I could help you with that, as your snippet gave me the idea I needed to get my own code working ;)

TimL20 avatar Nov 25 '19 11:11 TimL20