-
Notifications
You must be signed in to change notification settings - Fork 38
Description
Summary
When running device-snmp-go with multiple devices, all SNMP requests are sent to the first device that triggered an autoEvent — regardless of which device is actually being polled. This causes persistent Request timeout errors for all subsequent devices.
This is an architectural bug caused by the use of a global singleton for both the SNMP client and the underlying gosnmp connection.
Root Cause
1. Global client singleton in snmpdriver.go (lines 78–82)
mu.Lock()
defer mu.Unlock()
if client == nil {
client = NewSNMPClient(Address, uint16(port)) // created once for the FIRST device
}Once client is created for the first device, it is never replaced for subsequent devices. All devices share this single client instance.
2. Global g.Default connection in snmpclient.go (lines 61–69)
if g.Default.Conn == nil {
g.Default.Target = c.ipAddr
g.Default.Port = c.ipPort
g.Default.Community = COMMUNITY_ACCESS
err := g.Default.Connect()
...
}g.Default is the package-level global GoSNMP instance from the gosnmp library. Once g.Default.Conn is set (for the first device), subsequent calls skip the Connect() block entirely — the target IP/port is never updated for other devices.
Reproduction Scenario
Setup with two devices:
- Device A (e.g.
192.168.10.200) — unreachable, autoEvents every5s/10s/15s - Device B (e.g.
192.168.84.1) — reachable, autoEvents every1m
Event sequence:
- Device A autoEvent fires first →
client = NewSNMPClient("192.168.10.200", 161)— global client created g.Default.Target = "192.168.10.200"→g.Default.Connect()— UDP socket bound to Device Ag.Default.Get(...)→ timeout (Device A unreachable)- Device B autoEvent fires →
client != nil→ reused (still points to Device A's config) g.Default.Conn != nil→ Connect() is skipped, target is NOT updated to192.168.84.1g.Default.Get(...)→ packet is sent to192.168.10.200→ timeout for Device B too
Debug logs correctly show Device B's address (192.168.84.1) because it is read from the device protocol and printed — but the actual SNMP packet goes to the address hardcoded in g.Default at first connection time.
Expected Behavior
Each device should use its own isolated SNMP connection. When HandleReadCommands is called for a specific device, the SNMP request must be sent to that device's IP and port, not a globally cached connection from a different device.
Suggested Fix
- Remove the package-level
clientsingleton insnmpdriver.go. Create a per-device client instance keyed by device name or address. - In
snmpclient.go, stop usingg.Default. Instead, create a dedicatedgosnmp.GoSNMPstruct per client instance and call.Connect()on it directly. - Ensure connections are properly closed and recreated when the target address changes.
Related Issues
- SNMP device not reachable : "Request timeout" #119 — reports
Request timeoutwith a single device; one commenter identifiedCOMMUNITY_ACCESShardcoding as a separate but related issue insnmpclient.go
Environment
device-snmp-golatest (mainbranch / v4.0.1)- Multiple devices defined in
device.snmp.*.yamlwith different autoEvent intervals - One or more devices unreachable (causes the first
Connto remain open to wrong target)