fix(snmp,db): save FDB to PG (empty inet null), bridge_port + MAC normalize
Made-with: Cursor
This commit is contained in:
+73
-15
@@ -245,8 +245,8 @@ func probePortDevices(client *gosnmp.GoSNMP, ip string, checkedAt time.Time) []P
|
||||
|
||||
macToIPs := make(map[string]map[string]struct{})
|
||||
for key, mac := range arpIfIPToMac {
|
||||
mac = strings.ToLower(strings.TrimSpace(mac))
|
||||
if mac == "" || !strings.Contains(mac, ":") {
|
||||
mac = normalizeMACKey(mac)
|
||||
if mac == "" {
|
||||
continue
|
||||
}
|
||||
parts := strings.Split(key, ".")
|
||||
@@ -266,11 +266,11 @@ func probePortDevices(client *gosnmp.GoSNMP, ip string, checkedAt time.Time) []P
|
||||
seen := make(map[string]struct{})
|
||||
out := make([]PortDeviceResult, 0, len(combinedFdb))
|
||||
for macTail, bridgePortRaw := range combinedFdb {
|
||||
mac := dottedDecimalToMACTail(macTail)
|
||||
mac := normalizeMACKey(dottedDecimalToMACTail(macTail))
|
||||
if mac == "" {
|
||||
continue
|
||||
}
|
||||
bridgePort, err := strconv.Atoi(strings.TrimSpace(bridgePortRaw))
|
||||
bridgePort, err := strconv.Atoi(strings.TrimSpace(snmpNumericString(bridgePortRaw)))
|
||||
if err != nil || bridgePort <= 0 {
|
||||
continue
|
||||
}
|
||||
@@ -283,7 +283,7 @@ func probePortDevices(client *gosnmp.GoSNMP, ip string, checkedAt time.Time) []P
|
||||
continue
|
||||
}
|
||||
|
||||
ipsSet := macToIPs[strings.ToLower(mac)]
|
||||
ipsSet := macToIPs[mac]
|
||||
if len(ipsSet) == 0 {
|
||||
key := fmt.Sprintf("%d|%s|", ifIndex, mac)
|
||||
if _, ok := seen[key]; ok {
|
||||
@@ -291,11 +291,12 @@ func probePortDevices(client *gosnmp.GoSNMP, ip string, checkedAt time.Time) []P
|
||||
}
|
||||
seen[key] = struct{}{}
|
||||
out = append(out, PortDeviceResult{
|
||||
IP: ip,
|
||||
IfIndex: ifIndex,
|
||||
MAC: mac,
|
||||
LearnedIP: "",
|
||||
CheckedAt: checkedAt,
|
||||
IP: ip,
|
||||
IfIndex: ifIndex,
|
||||
BridgePort: bridgePort,
|
||||
MAC: mac,
|
||||
LearnedIP: "",
|
||||
CheckedAt: checkedAt,
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -306,11 +307,12 @@ func probePortDevices(client *gosnmp.GoSNMP, ip string, checkedAt time.Time) []P
|
||||
}
|
||||
seen[key] = struct{}{}
|
||||
out = append(out, PortDeviceResult{
|
||||
IP: ip,
|
||||
IfIndex: ifIndex,
|
||||
MAC: mac,
|
||||
LearnedIP: learnedIP,
|
||||
CheckedAt: checkedAt,
|
||||
IP: ip,
|
||||
IfIndex: ifIndex,
|
||||
BridgePort: bridgePort,
|
||||
MAC: mac,
|
||||
LearnedIP: learnedIP,
|
||||
CheckedAt: checkedAt,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -331,6 +333,62 @@ func probePortDevices(client *gosnmp.GoSNMP, ip string, checkedAt time.Time) []P
|
||||
return out
|
||||
}
|
||||
|
||||
// snmpNumericString — значение SNMP как строка (int/float/[]byte) для Atoi.
|
||||
func snmpNumericString(v any) string {
|
||||
switch x := v.(type) {
|
||||
case string:
|
||||
return x
|
||||
case []byte:
|
||||
return strings.TrimSpace(string(x))
|
||||
default:
|
||||
return strings.TrimSpace(fmt.Sprint(x))
|
||||
}
|
||||
}
|
||||
|
||||
// normalizeMACKey приводит MAC к виду aa:bb:cc:dd:ee:ff для сопоставления FDB и ARP.
|
||||
func normalizeMACKey(s string) string {
|
||||
s = strings.ToLower(strings.TrimSpace(s))
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
s = strings.ReplaceAll(s, "-", ":")
|
||||
if strings.Count(s, ":") == 5 {
|
||||
parts := strings.Split(s, ":")
|
||||
if len(parts) != 6 {
|
||||
return ""
|
||||
}
|
||||
var b [6]byte
|
||||
for i, p := range parts {
|
||||
n, err := strconv.ParseUint(strings.TrimSpace(p), 16, 8)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
b[i] = byte(n)
|
||||
}
|
||||
return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", b[0], b[1], b[2], b[3], b[4], b[5])
|
||||
}
|
||||
if strings.HasPrefix(s, "0x") {
|
||||
h := strings.TrimPrefix(s, "0x")
|
||||
h = strings.ReplaceAll(h, ":", "")
|
||||
if len(h) != 12 {
|
||||
return ""
|
||||
}
|
||||
raw, err := hex.DecodeString(h)
|
||||
if err != nil || len(raw) != 6 {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", raw[0], raw[1], raw[2], raw[3], raw[4], raw[5])
|
||||
}
|
||||
if len(s) == 12 {
|
||||
raw, err := hex.DecodeString(s)
|
||||
if err != nil || len(raw) != 6 {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", raw[0], raw[1], raw[2], raw[3], raw[4], raw[5])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func dottedDecimalToMACTail(s string) string {
|
||||
p := strings.Split(strings.TrimSpace(s), ".")
|
||||
if len(p) < 6 {
|
||||
|
||||
Reference in New Issue
Block a user