diff --git a/plugins/inputs/snmp/README.md b/plugins/inputs/snmp/README.md index a0c9155db5432..613868d928a1e 100644 --- a/plugins/inputs/snmp/README.md +++ b/plugins/inputs/snmp/README.md @@ -113,15 +113,21 @@ option operate similar to the `snmpget` utility. # is_tag = false ## Apply one of the following conversions to the variable value: - ## float(X) Convert the input value into a float and divides by the - ## Xth power of 10. Effectively just moves the decimal left - ## X places. For example a value of `123` with `float(2)` - ## will result in `1.23`. - ## float: Convert the value into a float with no adjustment. Same - ## as `float(0)`. - ## int: Convert the value into an integer. - ## hwaddr: Convert the value to a MAC address. - ## ipaddr: Convert the value to an IP address. + ## float(X): Convert the input value into a float and divides by the + ## Xth power of 10. Effectively just moves the decimal left + ## X places. For example a value of `123` with `float(2)` + ## will result in `1.23`. + ## float: Convert the value into a float with no adjustment. Same + ## as `float(0)`. + ## int: Convert the value into an integer. + ## hwaddr: Convert the value to a MAC address. + ## ipaddr: Convert the value to an IP address. + ## hextoint:X:Y Convert a hex string value to integer. Where X is the Endian + ## and Y the bit size. For example: hextoint:LittleEndian:uint64 + ## or hextoint:BigEndian:uint32. Valid options for the Endian are: + ## BigEndian and LittleEndian. For the bit size: uint16, uint32 + ## and uint64. + ## # conversion = "" ``` diff --git a/plugins/inputs/snmp/snmp.go b/plugins/inputs/snmp/snmp.go index 103b23d214485..5ddaffc7dc9bc 100644 --- a/plugins/inputs/snmp/snmp.go +++ b/plugins/inputs/snmp/snmp.go @@ -3,6 +3,7 @@ package snmp import ( "bufio" "bytes" + "encoding/binary" "fmt" "log" "math" @@ -561,12 +562,6 @@ func (s *Snmp) getConnection(idx int) (snmpConnection, error) { } // fieldConvert converts from any type according to the conv specification -// "float"/"float(0)" will convert the value into a float. -// "float(X)" will convert the value into a float, and then move the decimal before Xth right-most digit. -// "int" will convert the value into an integer. -// "hwaddr" will convert the value into a MAC address. -// "ipaddr" will convert the value into into an IP address. -// "" will convert a byte slice into a string. func fieldConvert(conv string, v interface{}) (interface{}, error) { if conv == "" { if bs, ok := v.([]byte); ok { @@ -658,6 +653,46 @@ func fieldConvert(conv string, v interface{}) (interface{}, error) { return v, nil } + split := strings.Split(conv, ":") + if split[0] == "hextoint" && len(split) == 3 { + + endian := split[1] + bit := split[2] + + bv, ok := v.([]byte) + if !ok { + return v, nil + } + + if endian == "LittleEndian" { + switch bit { + case "uint64": + v = binary.LittleEndian.Uint64(bv) + case "uint32": + v = binary.LittleEndian.Uint32(bv) + case "uint16": + v = binary.LittleEndian.Uint16(bv) + default: + return nil, fmt.Errorf("invalid bit value (%s) for hex to int conversion", bit) + } + } else if endian == "BigEndian" { + switch bit { + case "uint64": + v = binary.BigEndian.Uint64(bv) + case "uint32": + v = binary.BigEndian.Uint32(bv) + case "uint16": + v = binary.BigEndian.Uint16(bv) + default: + return nil, fmt.Errorf("invalid bit value (%s) for hex to int conversion", bit) + } + } else { + return nil, fmt.Errorf("invalid Endian value (%s) for hex to int conversion", endian) + } + + return v, nil + } + if conv == "ipaddr" { var ipbs []byte diff --git a/plugins/inputs/snmp/snmp_test.go b/plugins/inputs/snmp/snmp_test.go index 583b2dc847282..ddfa86d917eeb 100644 --- a/plugins/inputs/snmp/snmp_test.go +++ b/plugins/inputs/snmp/snmp_test.go @@ -726,6 +726,12 @@ func TestFieldConvert(t *testing.T) { {[]byte("abcd"), "ipaddr", "97.98.99.100"}, {"abcd", "ipaddr", "97.98.99.100"}, {[]byte("abcdefghijklmnop"), "ipaddr", "6162:6364:6566:6768:696a:6b6c:6d6e:6f70"}, + {[]byte{0x00, 0x09, 0x3E, 0xE3, 0xF6, 0xD5, 0x3B, 0x60}, "hextoint:BigEndian:uint64", uint64(2602423610063712)}, + {[]byte{0x00, 0x09, 0x3E, 0xE3}, "hextoint:BigEndian:uint32", uint32(605923)}, + {[]byte{0x00, 0x09}, "hextoint:BigEndian:uint16", uint16(9)}, + {[]byte{0x00, 0x09, 0x3E, 0xE3, 0xF6, 0xD5, 0x3B, 0x60}, "hextoint:LittleEndian:uint64", uint64(6934371307618175232)}, + {[]byte{0x00, 0x09, 0x3E, 0xE3}, "hextoint:LittleEndian:uint32", uint32(3812493568)}, + {[]byte{0x00, 0x09}, "hextoint:LittleEndian:uint16", uint16(2304)}, } for _, tc := range testTable {