From a51efbf471fb7e2772e9029d704c6a115ffb7d0b Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Mon, 9 Jun 2025 17:51:06 +0200 Subject: [PATCH] add ifEntry MIB also --- ifmib/ifmib.go | 225 +++++++++++++++++++++++++++++++++++++++++++------ main.go | 9 +- 2 files changed, 203 insertions(+), 31 deletions(-) diff --git a/ifmib/ifmib.go b/ifmib/ifmib.go index 08b715b..1a86903 100644 --- a/ifmib/ifmib.go +++ b/ifmib/ifmib.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "sync" + "time" "github.com/posteo/go-agentx" "github.com/posteo/go-agentx/pdu" @@ -11,8 +12,35 @@ import ( "go.fd.io/govpp/api" ) -// IF-MIB OID base: 1.3.6.1.2.1.31.1.1.1 -// ifXTable entries: +// IF-MIB OID bases: +// ifEntry (classic): 1.3.6.1.2.1.2.2.1 +// ifXTable (extended): 1.3.6.1.2.1.31.1.1.1 + +// ifEntry (1.3.6.1.2.1.2.2.1) - Classic Interface Table: +// ifIndex .1 - Integer32 +// ifDescr .2 - DisplayString +// ifType .3 - IANAifType +// ifMtu .4 - Integer32 +// ifSpeed .5 - Gauge32 +// ifPhysAddress .6 - PhysAddress +// ifAdminStatus .7 - INTEGER +// ifOperStatus .8 - INTEGER +// ifLastChange .9 - TimeTicks +// ifInOctets .10 - Counter32 +// ifInUcastPkts .11 - Counter32 +// ifInNUcastPkts .12 - Counter32 +// ifInDiscards .13 - Counter32 +// ifInErrors .14 - Counter32 +// ifInUnknownProtos .15 - Counter32 +// ifOutOctets .16 - Counter32 +// ifOutUcastPkts .17 - Counter32 +// ifOutNUcastPkts .18 - Counter32 +// ifOutDiscards .19 - Counter32 +// ifOutErrors .20 - Counter32 +// ifOutQLen .21 - Gauge32 +// ifSpecific .22 - OBJECT IDENTIFIER + +// ifXTable (1.3.6.1.2.1.31.1.1.1) - Extended Interface Table: // ifName .1 - DisplayString // ifInMulticastPkts .2 - Counter32 // ifInBroadcastPkts .3 - Counter32 @@ -27,14 +55,16 @@ import ( // ifHCOutMulticastPkts .12 - Counter64 // ifHCOutBroadcastPkts .13 - Counter64 +const ifEntryOID = "1.3.6.1.2.1.2.2.1" const ifXTableOID = "1.3.6.1.2.1.31.1.1.1" type InterfaceMIB struct { - mutex sync.RWMutex - handler *agentx.ListHandler - session *agentx.Session - stats map[uint32]*api.InterfaceCounters // indexed by interface index - indexOffset int + mutex sync.RWMutex + handler *agentx.ListHandler + ifEntrySession *agentx.Session + ifXTableSession *agentx.Session + stats map[uint32]*api.InterfaceCounters // indexed by interface index + indexOffset int } func NewInterfaceMIB(indexOffset int) *InterfaceMIB { @@ -65,21 +95,147 @@ func (m *InterfaceMIB) UpdateStats(interfaceStats *api.InterfaceStats) { m.stats[iface.InterfaceIndex] = &iface m.addInterfaceToMIB(&iface) } - - // Update the session with the new handler - if m.session != nil { - m.session.Handler = m.handler - log.Printf("Updated session handler with new IF-MIB data") + + // Update both sessions with the new handler + if m.ifEntrySession != nil { + m.ifEntrySession.Handler = m.handler } - + if m.ifXTableSession != nil { + m.ifXTableSession.Handler = m.handler + log.Printf("Updated session handlers with new IF-MIB data") + } + log.Printf("IF-MIB now contains %d interfaces", len(m.stats)) } func (m *InterfaceMIB) addInterfaceToMIB(iface *api.InterfaceCounters) { idx := int(iface.InterfaceIndex) + m.indexOffset + // Add ifEntry (classic interface table) entries + m.addIfEntry(iface, idx) + + // Add ifXTable (extended interface table) entries + m.addIfXTable(iface, idx) + + log.Printf("Added interface %d (%s) to IF-MIB with SNMP index %d", iface.InterfaceIndex, iface.InterfaceName, idx) +} + +func (m *InterfaceMIB) addIfEntry(iface *api.InterfaceCounters, idx int) { + var item *agentx.ListItem + + // ifIndex (.1) + item = m.handler.Add(fmt.Sprintf("%s.1.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeInteger + item.Value = int32(idx) + + // ifDescr (.2) + item = m.handler.Add(fmt.Sprintf("%s.2.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeOctetString + item.Value = iface.InterfaceName + + // ifType (.3) - Using ethernetCsmacd(6) as default + item = m.handler.Add(fmt.Sprintf("%s.3.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeInteger + item.Value = int32(6) + + // ifMtu (.4) - Default MTU 1500 + item = m.handler.Add(fmt.Sprintf("%s.4.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeInteger + item.Value = int32(1500) + + // ifSpeed (.5) - Default to 1Gbps (1000000000 bits/sec) + item = m.handler.Add(fmt.Sprintf("%s.5.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeGauge32 + item.Value = uint32(1000000000) + + // ifPhysAddress (.6) - Empty for now + item = m.handler.Add(fmt.Sprintf("%s.6.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeOctetString + item.Value = "" + + // ifAdminStatus (.7) - up(1) + item = m.handler.Add(fmt.Sprintf("%s.7.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeInteger + item.Value = int32(1) + + // ifOperStatus (.8) - up(1) + item = m.handler.Add(fmt.Sprintf("%s.8.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeInteger + item.Value = int32(1) + + // ifLastChange (.9) - 0 (unknown) + item = m.handler.Add(fmt.Sprintf("%s.9.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeTimeTicks + item.Value = 0 * time.Second + + // ifInOctets (.10) + item = m.handler.Add(fmt.Sprintf("%s.10.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(iface.Rx.Bytes) + + // ifInUcastPkts (.11) + item = m.handler.Add(fmt.Sprintf("%s.11.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(iface.RxUnicast.Packets) + + // ifInNUcastPkts (.12) - multicast + broadcast + item = m.handler.Add(fmt.Sprintf("%s.12.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(iface.RxMulticast.Packets + iface.RxBroadcast.Packets) + + // ifInDiscards (.13) - using drops + item = m.handler.Add(fmt.Sprintf("%s.13.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(iface.Drops) + + // ifInErrors (.14) + item = m.handler.Add(fmt.Sprintf("%s.14.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(iface.RxErrors) + + // ifInUnknownProtos (.15) - 0 (not available) + item = m.handler.Add(fmt.Sprintf("%s.15.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(0) + + // ifOutOctets (.16) + item = m.handler.Add(fmt.Sprintf("%s.16.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(iface.Tx.Bytes) + + // ifOutUcastPkts (.17) + item = m.handler.Add(fmt.Sprintf("%s.17.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(iface.TxUnicast.Packets) + + // ifOutNUcastPkts (.18) - multicast + broadcast + item = m.handler.Add(fmt.Sprintf("%s.18.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(iface.TxMulticast.Packets + iface.TxBroadcast.Packets) + + // ifOutDiscards (.19) - 0 (not available) + item = m.handler.Add(fmt.Sprintf("%s.19.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(0) + + // ifOutErrors (.20) + item = m.handler.Add(fmt.Sprintf("%s.20.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeCounter32 + item.Value = uint32(iface.TxErrors) + + // ifOutQLen (.21) - 0 (not available) + item = m.handler.Add(fmt.Sprintf("%s.21.%d", ifEntryOID, idx)) + item.Type = pdu.VariableTypeGauge32 + item.Value = uint32(0) + + // ifSpecific (.22) - Skip this field as it's optional and causing issues +} + +func (m *InterfaceMIB) addIfXTable(iface *api.InterfaceCounters, idx int) { + var item *agentx.ListItem + // ifName (.1) - item := m.handler.Add(fmt.Sprintf("%s.1.%d", ifXTableOID, idx)) + item = m.handler.Add(fmt.Sprintf("%s.1.%d", ifXTableOID, idx)) item.Type = pdu.VariableTypeOctetString item.Value = iface.InterfaceName @@ -142,22 +298,43 @@ func (m *InterfaceMIB) addInterfaceToMIB(iface *api.InterfaceCounters) { item = m.handler.Add(fmt.Sprintf("%s.13.%d", ifXTableOID, idx)) item.Type = pdu.VariableTypeCounter64 item.Value = iface.TxBroadcast.Packets - - log.Printf("Added interface %d (%s) to IF-MIB with SNMP index %d", iface.InterfaceIndex, iface.InterfaceName, idx) } -func (m *InterfaceMIB) RegisterWithSession(session *agentx.Session) error { +func (m *InterfaceMIB) RegisterWithClient(client *agentx.Client) error { m.mutex.Lock() defer m.mutex.Unlock() - m.session = session - session.Handler = m.handler - // Register at the ifXTable level - err := session.Register(127, value.MustParseOID(ifXTableOID)) + // Create separate sessions for each MIB + ifEntrySession, err := client.Session() if err != nil { - return fmt.Errorf("failed to register IF-MIB: %v", err) + return fmt.Errorf("failed to create ifEntry session: %v", err) } - log.Printf("Registered IF-MIB at OID %s", ifXTableOID) + ifXTableSession, err := client.Session() + if err != nil { + return fmt.Errorf("failed to create ifXTable session: %v", err) + } + + m.ifEntrySession = ifEntrySession + m.ifXTableSession = ifXTableSession + + // Set handlers for both sessions + ifEntrySession.Handler = m.handler + ifXTableSession.Handler = m.handler + + // Register the classic ifEntry + err = ifEntrySession.Register(127, value.MustParseOID(ifEntryOID)) + if err != nil { + return fmt.Errorf("failed to register ifEntry: %v", err) + } + + // Register the extended ifXTable + err = ifXTableSession.Register(127, value.MustParseOID(ifXTableOID)) + if err != nil { + return fmt.Errorf("failed to register ifXTable: %v", err) + } + + log.Printf("Registered IF-MIB ifEntry at OID %s", ifEntryOID) + log.Printf("Registered IF-MIB ifXTable at OID %s", ifXTableOID) return nil -} \ No newline at end of file +} diff --git a/main.go b/main.go index ec57928..26d531b 100644 --- a/main.go +++ b/main.go @@ -35,16 +35,11 @@ func main() { client.Timeout = 1 * time.Minute client.ReconnectInterval = 1 * time.Second - session, err := client.Session() - if err != nil { - log.Fatalf("Failed to create session: %v", err) - } - // Create the interface MIB interfaceMIB := ifmib.NewInterfaceMIB(*ifIndexOffset) - // Register the interface MIB with the AgentX session - if err := interfaceMIB.RegisterWithSession(session); err != nil { + // Register the interface MIB with the AgentX client + if err := interfaceMIB.RegisterWithClient(client); err != nil { log.Fatalf("Failed to register interface MIB: %v", err) }