WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions comp/core/autodiscovery/listeners/snmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ import (

const cacheKeyPrefix = "snmp"

var (
autodiscoveryStatusBySubnetVar = expvar.NewMap("snmpAutodiscovery")
)
var autodiscoveryStatusBySubnetVar = expvar.NewMap("snmpAutodiscovery")

// AutodiscoveryStatus represents the status of the autodiscovery of a subnet we want to expose in the snmp status
type AutodiscoveryStatus struct {
Expand Down Expand Up @@ -408,6 +406,11 @@ func (l *SNMPListener) checkDevices() {
discoveryTicker := time.NewTicker(time.Duration(l.config.DiscoveryInterval) * time.Second)
defer discoveryTicker.Stop()
for {
// Reset the device deduper counters at the start of each discovery interval
if l.deviceDeduper != nil {
l.deviceDeduper.ResetCounters()
}

for _, subnet := range subnets {
autodiscoveryStatusBySubnetVar.Set(GetSubnetVarKey(subnet.config.Network, subnet.index), &expvar.String{})
}
Expand Down
30 changes: 25 additions & 5 deletions pkg/snmp/devicededuper/device_deduper.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ type DeviceDeduper interface {
MarkIPAsProcessed(ip string)
AddPendingDevice(device PendingDevice)
GetDedupedDevices() []PendingDevice
ResetCounters()
}

type deviceDeduperImpl struct {
sync.RWMutex
deviceInfos []DeviceInfo
pendingDevices []PendingDevice
ipsCounter map[string]*atomic.Uint32
config snmp.ListenerConfig
}

// NewDeviceDeduper creates a new DeviceDeduper instance
Expand All @@ -66,9 +68,16 @@ func NewDeviceDeduper(config snmp.ListenerConfig) DeviceDeduper {
deviceInfos: make([]DeviceInfo, 0),
pendingDevices: make([]PendingDevice, 0),
ipsCounter: make(map[string]*atomic.Uint32),
config: config,
}

for _, config := range config.Configs {
deduper.initializeCounters()

return deduper
}

func (d *deviceDeduperImpl) initializeCounters() {
for _, config := range d.config.Configs {
ipAddr, ipNet, err := net.ParseCIDR(config.Network)
if err != nil {
log.Errorf("Couldn't parse SNMP network: %s", err)
Expand All @@ -83,16 +92,14 @@ func NewDeviceDeduper(config snmp.ListenerConfig) DeviceDeduper {
}

ipStr := currentIP.String()
counter, exists := deduper.ipsCounter[ipStr]
counter, exists := d.ipsCounter[ipStr]
if !exists {
counter = &atomic.Uint32{}
deduper.ipsCounter[ipStr] = counter
d.ipsCounter[ipStr] = counter
}
counter.Add(uint32(len(config.Authentications)))
}
}

return deduper
}

func (d *deviceDeduperImpl) checkPreviousIPs(deviceIP string) bool {
Expand Down Expand Up @@ -179,6 +186,19 @@ func (d *deviceDeduperImpl) MarkIPAsProcessed(ip string) {
}
}

// ResetCounters resets the IP counters and device infos for a new discovery interval
func (d *deviceDeduperImpl) ResetCounters() {
d.Lock()
defer d.Unlock()

for _, counter := range d.ipsCounter {
counter.Store(0)
}

d.initializeCounters()
d.deviceInfos = make([]DeviceInfo, 0)
}

func minimumIP(ipStr1, ipStr2 string) string {
ip1 := net.ParseIP(ipStr1)
ip2 := net.ParseIP(ipStr2)
Expand Down
62 changes: 60 additions & 2 deletions pkg/snmp/devicededuper/device_deduper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
package devicededuper

import (
"sync/atomic"
"testing"
"time"

"sync/atomic"

"github.com/DataDog/datadog-agent/pkg/snmp"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -549,3 +548,62 @@ func TestNewDeviceDeduper(t *testing.T) {
}
assert.Equal(t, 4, count)
}

func TestDeviceDeduper_ResetCounters(t *testing.T) {
config := snmp.ListenerConfig{
Configs: []snmp.Config{
{
Network: "192.168.1.0/30",
Authentications: []snmp.Authentication{
{Community: "public"},
{Community: "private"},
},
IgnoredIPAddresses: map[string]bool{
"192.168.1.0": true,
},
},
},
}

deduper := NewDeviceDeduper(config)
deduperImpl, ok := deduper.(*deviceDeduperImpl)
assert.True(t, ok)

// Initially, all counters should be set to 2 (number of authentications)
count := deduperImpl.ipsCounter["192.168.1.1"].Load()
assert.Equal(t, uint32(2), count)
count = deduperImpl.ipsCounter["192.168.1.2"].Load()
assert.Equal(t, uint32(2), count)

// Process some IPs
deduper.MarkIPAsProcessed("192.168.1.1")
deduper.MarkIPAsProcessed("192.168.1.2")

count = deduperImpl.ipsCounter["192.168.1.1"].Load()
assert.Equal(t, uint32(1), count)
count = deduperImpl.ipsCounter["192.168.1.2"].Load()
assert.Equal(t, uint32(1), count)

// Add a discovered device
now := time.Now().UnixMilli()
deviceInfo := DeviceInfo{
Name: "device1",
Description: "test device",
BootTimeMs: now,
SysObjectID: "1.3.6.1.4.1.9.1.1",
}
deduperImpl.deviceInfos = append(deduperImpl.deviceInfos, deviceInfo)
assert.Len(t, deduperImpl.deviceInfos, 1)

// Reset counters
deduper.ResetCounters()

// Verify counters are reset to initial value
count = deduperImpl.ipsCounter["192.168.1.1"].Load()
assert.Equal(t, uint32(2), count)
count = deduperImpl.ipsCounter["192.168.1.2"].Load()
assert.Equal(t, uint32(2), count)

// Verify device infos are cleared
assert.Len(t, deduperImpl.deviceInfos, 0)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Each section from every release note are combined when the
# CHANGELOG.rst is rendered. So the text needs to be worded so that
# it does not depend on any information only available in another
# section. This may mean repeating some details, but each section
# must be readable independently of the other.
#
# Each section note must be formatted as reStructuredText.
---
fixes:
- |
Fix SNMP Autodiscovery bug where the Agent had to be restarted to take into account new devices discovered in a subnet.