add ifEntry MIB also

This commit is contained in:
Pim van Pelt
2025-06-09 17:51:06 +02:00
parent 396d2ace00
commit a51efbf471
2 changed files with 203 additions and 31 deletions

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"log" "log"
"sync" "sync"
"time"
"github.com/posteo/go-agentx" "github.com/posteo/go-agentx"
"github.com/posteo/go-agentx/pdu" "github.com/posteo/go-agentx/pdu"
@ -11,8 +12,35 @@ import (
"go.fd.io/govpp/api" "go.fd.io/govpp/api"
) )
// IF-MIB OID base: 1.3.6.1.2.1.31.1.1.1 // IF-MIB OID bases:
// ifXTable entries: // 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 // ifName .1 - DisplayString
// ifInMulticastPkts .2 - Counter32 // ifInMulticastPkts .2 - Counter32
// ifInBroadcastPkts .3 - Counter32 // ifInBroadcastPkts .3 - Counter32
@ -27,14 +55,16 @@ import (
// ifHCOutMulticastPkts .12 - Counter64 // ifHCOutMulticastPkts .12 - Counter64
// ifHCOutBroadcastPkts .13 - 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" const ifXTableOID = "1.3.6.1.2.1.31.1.1.1"
type InterfaceMIB struct { type InterfaceMIB struct {
mutex sync.RWMutex mutex sync.RWMutex
handler *agentx.ListHandler handler *agentx.ListHandler
session *agentx.Session ifEntrySession *agentx.Session
stats map[uint32]*api.InterfaceCounters // indexed by interface index ifXTableSession *agentx.Session
indexOffset int stats map[uint32]*api.InterfaceCounters // indexed by interface index
indexOffset int
} }
func NewInterfaceMIB(indexOffset int) *InterfaceMIB { func NewInterfaceMIB(indexOffset int) *InterfaceMIB {
@ -66,10 +96,13 @@ func (m *InterfaceMIB) UpdateStats(interfaceStats *api.InterfaceStats) {
m.addInterfaceToMIB(&iface) m.addInterfaceToMIB(&iface)
} }
// Update the session with the new handler // Update both sessions with the new handler
if m.session != nil { if m.ifEntrySession != nil {
m.session.Handler = m.handler m.ifEntrySession.Handler = m.handler
log.Printf("Updated session handler with new IF-MIB data") }
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)) log.Printf("IF-MIB now contains %d interfaces", len(m.stats))
@ -78,8 +111,131 @@ func (m *InterfaceMIB) UpdateStats(interfaceStats *api.InterfaceStats) {
func (m *InterfaceMIB) addInterfaceToMIB(iface *api.InterfaceCounters) { func (m *InterfaceMIB) addInterfaceToMIB(iface *api.InterfaceCounters) {
idx := int(iface.InterfaceIndex) + m.indexOffset 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) // 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.Type = pdu.VariableTypeOctetString
item.Value = iface.InterfaceName 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 = m.handler.Add(fmt.Sprintf("%s.13.%d", ifXTableOID, idx))
item.Type = pdu.VariableTypeCounter64 item.Type = pdu.VariableTypeCounter64
item.Value = iface.TxBroadcast.Packets 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() m.mutex.Lock()
defer m.mutex.Unlock() defer m.mutex.Unlock()
m.session = session // Create separate sessions for each MIB
session.Handler = m.handler ifEntrySession, err := client.Session()
// Register at the ifXTable level
err := session.Register(127, value.MustParseOID(ifXTableOID))
if err != nil { 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 return nil
} }

View File

@ -35,16 +35,11 @@ func main() {
client.Timeout = 1 * time.Minute client.Timeout = 1 * time.Minute
client.ReconnectInterval = 1 * time.Second client.ReconnectInterval = 1 * time.Second
session, err := client.Session()
if err != nil {
log.Fatalf("Failed to create session: %v", err)
}
// Create the interface MIB // Create the interface MIB
interfaceMIB := ifmib.NewInterfaceMIB(*ifIndexOffset) interfaceMIB := ifmib.NewInterfaceMIB(*ifIndexOffset)
// Register the interface MIB with the AgentX session // Register the interface MIB with the AgentX client
if err := interfaceMIB.RegisterWithSession(session); err != nil { if err := interfaceMIB.RegisterWithClient(client); err != nil {
log.Fatalf("Failed to register interface MIB: %v", err) log.Fatalf("Failed to register interface MIB: %v", err)
} }