etingof / pyasn1

Generic ASN.1 library for Python
http://snmplabs.com/pyasn1
BSD 2-Clause "Simplified" License
242 stars 118 forks source link

How to decode Float class generated by pyasn1? #158

Open j-gooding opened 5 years ago

j-gooding commented 5 years ago

My MIB file defines the following:

-------------------------------------------------------------------------------
-- Define the Float Textual Convention
--   This definition was written by David Perkins.
--
Float ::= TEXTUAL-CONVENTION
    STATUS      current
    DESCRIPTION
        "A single precision floating-point number.  The semantics
         and encoding are identical for type 'single' defined in
         IEEE Standard for Binary Floating-Point,
         ANSI/IEEE Std 754-1985.
         The value is restricted to the BER serialization of
         the following ASN.1 type:
             FLOATTYPE ::= [120] IMPLICIT FloatType
         (note: the value 120 is the sum of '30'h and '48'h)
         The BER serialization of the length for values of
         this type must use the definite length, short
         encoding form.

         For example, the BER serialization of value 123
         of type FLOATTYPE is '9f780442f60000'h.  (The tag
         is '9f78'h; the length is '04'h; and the value is
         '42f60000'h.) The BER serialization of value
         '9f780442f60000'h of data type Opaque is
         '44079f780442f60000'h. (The tag is '44'h; the length
         is '07'h; and the value is '9f780442f60000'h."
    SYNTAX Opaque (SIZE (7))

-------------------------------------------------------------------------------

And pyasn1 generates the following code in the pysnmp compiled MIB file:

class Float(TextualConvention, Opaque):
    status = 'current'
    subtypeSpec = Opaque.subtypeSpec + ValueSizeConstraint(7, 7)
    fixedLength = 7

preforming an SNMP get on on values that use this data type return the following:

>>>value

<Float value object at 0x7fc7b07817f0 tagSet <TagSet object at 0x7fc7d05d0550 tags 64:0:4> subtypeSpec <ConstraintsIntersection object at 0x7fc7d0711c50 consts <ValueSizeConstraint object at 0x7fc7d0711c88 consts 7, 7>> encoding iso-8859-1 payload [0x9f78043bcb821b]>
>>>value.prettyPrint()

'0x9f78043bcb821b'

This is not what I expected, I expected a human readable number based off of the specification and the library generated Class. How do I display the decoded number? snap-get seems to handle this seamlessly.

etingof commented 5 years ago

Well, this TEXTUAL-CONVENTION does not include DISPLAY-HINT clause -- this is the statement that drives human-friendly representation of the values. I came across this RFC on the floats. Though it does not seem to explain why there is no DISPLAY-HINT in there...

Compiler-wise, it seems to behave as it should.

j-gooding commented 5 years ago

I've looked at the RFC and and those definitions while similar are not what my MIB uses, and even then that RFC still doesn't have a display hint defined for it. I am also not able to find any actual, working examples of using display hints with octet streams and not integers.

Further, I'm not entirely sure what you mean by the compiler is doing what it should? Is my MIB definition incomplete? I feel something is wrong here, or perhaps in pysnmp? Net-SNMP and two different proprietary applications not based on Net-SNMP are able to decode the Float type automatically without any issues.

etingof commented 5 years ago

The description of TEXTUAL-CONVENTION suggests that value interpretation should happen at implementation time. That makes me think that we need to add rfc6340.py module to pysnmp/smi/mibs with hand written code parsing and possibly building Float values.