-
Notifications
You must be signed in to change notification settings - Fork 5.5k
/
gosmi.go
123 lines (101 loc) · 3.53 KB
/
gosmi.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package snmp
import (
"fmt"
"sync"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/internal/snmp"
"github.com/sleepinggenius2/gosmi"
)
type gosmiTranslator struct {
}
func NewGosmiTranslator(paths []string, log telegraf.Logger) (*gosmiTranslator, error) {
err := snmp.LoadMibsFromPath(paths, log, &snmp.GosmiMibLoader{})
if err == nil {
return &gosmiTranslator{}, nil
}
return nil, err
}
type gosmiSnmpTranslateCache struct {
mibName string
oidNum string
oidText string
conversion string
node gosmi.SmiNode
err error
}
var gosmiSnmpTranslateCachesLock sync.Mutex
var gosmiSnmpTranslateCaches map[string]gosmiSnmpTranslateCache
//nolint:revive
func (g *gosmiTranslator) SnmpTranslate(oid string) (string, string, string, string, error) {
a, b, c, d, _, e := g.SnmpTranslateFull(oid)
return a, b, c, d, e
}
//nolint:revive
func (g *gosmiTranslator) SnmpTranslateFull(oid string) (
mibName string, oidNum string, oidText string,
conversion string,
node gosmi.SmiNode,
err error) {
gosmiSnmpTranslateCachesLock.Lock()
if gosmiSnmpTranslateCaches == nil {
gosmiSnmpTranslateCaches = map[string]gosmiSnmpTranslateCache{}
}
var stc gosmiSnmpTranslateCache
var ok bool
if stc, ok = gosmiSnmpTranslateCaches[oid]; !ok {
// This will result in only one call to snmptranslate running at a time.
// We could speed it up by putting a lock in snmpTranslateCache and then
// returning it immediately, and multiple callers would then release the
// snmpTranslateCachesLock and instead wait on the individual
// snmpTranslation.Lock to release. But I don't know that the extra complexity
// is worth it. Especially when it would slam the system pretty hard if lots
// of lookups are being performed.
stc.mibName, stc.oidNum, stc.oidText, stc.conversion, stc.node, stc.err = snmp.SnmpTranslateCall(oid)
gosmiSnmpTranslateCaches[oid] = stc
}
gosmiSnmpTranslateCachesLock.Unlock()
return stc.mibName, stc.oidNum, stc.oidText, stc.conversion, stc.node, stc.err
}
type gosmiSnmpTableCache struct {
mibName string
oidNum string
oidText string
fields []Field
err error
}
var gosmiSnmpTableCaches map[string]gosmiSnmpTableCache
var gosmiSnmpTableCachesLock sync.Mutex
// snmpTable resolves the given OID as a table, providing information about the
// table and fields within.
//nolint:revive //Too many return variable but necessary
func (g *gosmiTranslator) SnmpTable(oid string) (
mibName string, oidNum string, oidText string,
fields []Field,
err error) {
gosmiSnmpTableCachesLock.Lock()
if gosmiSnmpTableCaches == nil {
gosmiSnmpTableCaches = map[string]gosmiSnmpTableCache{}
}
var stc gosmiSnmpTableCache
var ok bool
if stc, ok = gosmiSnmpTableCaches[oid]; !ok {
stc.mibName, stc.oidNum, stc.oidText, stc.fields, stc.err = g.SnmpTableCall(oid)
gosmiSnmpTableCaches[oid] = stc
}
gosmiSnmpTableCachesLock.Unlock()
return stc.mibName, stc.oidNum, stc.oidText, stc.fields, stc.err
}
//nolint:revive //Too many return variable but necessary
func (g *gosmiTranslator) SnmpTableCall(oid string) (mibName string, oidNum string, oidText string, fields []Field, err error) {
mibName, oidNum, oidText, _, node, err := g.SnmpTranslateFull(oid)
if err != nil {
return "", "", "", nil, fmt.Errorf("translating: %w", err)
}
mibPrefix := mibName + "::"
col, tagOids, err := snmp.GetIndex(oidNum, mibPrefix, node)
for _, c := range col {
_, isTag := tagOids[mibPrefix+c]
fields = append(fields, Field{Name: c, Oid: mibPrefix + c, IsTag: isTag})
}
return mibName, oidNum, oidText, fields, err
}