remove parentid and tree logging machinery
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2
arp.go
2
arp.go
@@ -48,7 +48,7 @@ func (t *Tendrils) readARPTable() {
|
||||
log.Printf("[arp] %s: ip=%s mac=%s", entry.iface, entry.ip, entry.mac)
|
||||
}
|
||||
|
||||
t.nodes.Update([]net.IP{entry.ip}, []net.HardwareAddr{entry.mac}, entry.iface, "", "arp")
|
||||
t.nodes.Update([]net.IP{entry.ip}, []net.HardwareAddr{entry.mac}, "arp")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ func main() {
|
||||
noARP := flag.Bool("no-arp", false, "disable ARP discovery")
|
||||
noLLDP := flag.Bool("no-lldp", false, "disable LLDP discovery")
|
||||
noSNMP := flag.Bool("no-snmp", false, "disable SNMP discovery")
|
||||
logTree := flag.Bool("log-tree", false, "log full tree on changes")
|
||||
logReasons := flag.Bool("log-reasons", false, "log addition reasons")
|
||||
debugARP := flag.Bool("debug-arp", false, "debug ARP discovery")
|
||||
debugLLDP := flag.Bool("debug-lldp", false, "debug LLDP discovery")
|
||||
@@ -23,7 +22,6 @@ func main() {
|
||||
t.DisableARP = *noARP
|
||||
t.DisableLLDP = *noLLDP
|
||||
t.DisableSNMP = *noSNMP
|
||||
t.LogTree = *logTree
|
||||
t.LogReasons = *logReasons
|
||||
t.DebugARP = *debugARP
|
||||
t.DebugLLDP = *debugLLDP
|
||||
|
||||
2
lldp.go
2
lldp.go
@@ -68,7 +68,7 @@ func (t *Tendrils) handleLLDPPacket(ifaceName string, packet gopacket.Packet) {
|
||||
log.Printf("[lldp] %s: mac=%s port=%s name=%s", ifaceName, mac, childPort, systemName)
|
||||
}
|
||||
|
||||
t.nodes.Update(nil, []net.HardwareAddr{mac}, ifaceName, childPort, "lldp")
|
||||
t.nodes.Update(nil, []net.HardwareAddr{mac}, "lldp")
|
||||
|
||||
if systemName != "" {
|
||||
t.nodes.SetName(mac, systemName)
|
||||
|
||||
162
nodes.go
162
nodes.go
@@ -12,9 +12,6 @@ type Node struct {
|
||||
Name string
|
||||
IPs map[string]net.IP
|
||||
MACs map[string]net.HardwareAddr
|
||||
ParentID int
|
||||
LocalPort string
|
||||
ParentPort string
|
||||
}
|
||||
|
||||
func (n *Node) String() string {
|
||||
@@ -59,17 +56,12 @@ func NewNodes(t *Tendrils) *Nodes {
|
||||
n.nodes[0] = &Node{
|
||||
IPs: map[string]net.IP{},
|
||||
MACs: map[string]net.HardwareAddr{},
|
||||
ParentID: 0,
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Nodes) Update(ips []net.IP, macs []net.HardwareAddr, parentPort, childPort, source string) {
|
||||
n.UpdateWithParent(nil, ips, macs, parentPort, childPort, source)
|
||||
}
|
||||
|
||||
func (n *Nodes) UpdateWithParent(parentIP net.IP, ips []net.IP, macs []net.HardwareAddr, parentPort, childPort, source string) {
|
||||
func (n *Nodes) Update(ips []net.IP, macs []net.HardwareAddr, source string) {
|
||||
n.mu.Lock()
|
||||
defer n.mu.Unlock()
|
||||
|
||||
@@ -77,13 +69,6 @@ func (n *Nodes) UpdateWithParent(parentIP net.IP, ips []net.IP, macs []net.Hardw
|
||||
return
|
||||
}
|
||||
|
||||
parentID := 0
|
||||
if parentIP != nil {
|
||||
if id, exists := n.ipIndex[parentIP.String()]; exists {
|
||||
parentID = id
|
||||
}
|
||||
}
|
||||
|
||||
existingIDs := map[int]bool{}
|
||||
|
||||
for _, ip := range ips {
|
||||
@@ -105,9 +90,6 @@ func (n *Nodes) UpdateWithParent(parentIP net.IP, ips []net.IP, macs []net.Hardw
|
||||
n.nodes[targetID] = &Node{
|
||||
IPs: map[string]net.IP{},
|
||||
MACs: map[string]net.HardwareAddr{},
|
||||
ParentID: parentID,
|
||||
LocalPort: childPort,
|
||||
ParentPort: parentPort,
|
||||
}
|
||||
} else if len(existingIDs) == 1 {
|
||||
for id := range existingIDs {
|
||||
@@ -127,28 +109,11 @@ func (n *Nodes) UpdateWithParent(parentIP net.IP, ips []net.IP, macs []net.Hardw
|
||||
if n.t.LogReasons {
|
||||
log.Printf("merged nodes %v into %s (via %s)", merging, n.nodes[targetID], source)
|
||||
}
|
||||
if n.t.LogTree {
|
||||
n.mu.Unlock()
|
||||
n.LogTree()
|
||||
n.mu.Lock()
|
||||
}
|
||||
}
|
||||
|
||||
node := n.nodes[targetID]
|
||||
var added []string
|
||||
|
||||
if targetID != 0 {
|
||||
if node.LocalPort == "" && childPort != "" {
|
||||
node.LocalPort = childPort
|
||||
added = append(added, "localPort="+childPort)
|
||||
}
|
||||
|
||||
if node.ParentPort == "" && parentPort != "" {
|
||||
node.ParentPort = parentPort
|
||||
added = append(added, "parentPort="+parentPort)
|
||||
}
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
ipKey := ip.String()
|
||||
if _, exists := node.IPs[ipKey]; !exists {
|
||||
@@ -167,16 +132,9 @@ func (n *Nodes) UpdateWithParent(parentIP net.IP, ips []net.IP, macs []net.Hardw
|
||||
n.macIndex[macKey] = targetID
|
||||
}
|
||||
|
||||
if len(added) > 0 {
|
||||
if n.t.LogReasons {
|
||||
if len(added) > 0 && n.t.LogReasons {
|
||||
log.Printf("updated %s +%v (via %s)", node, added, source)
|
||||
}
|
||||
if n.t.LogTree {
|
||||
n.mu.Unlock()
|
||||
n.LogTree()
|
||||
n.mu.Lock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Nodes) mergeNodes(keepID, mergeID int) {
|
||||
@@ -238,119 +196,3 @@ func (n *Nodes) All() []*Node {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (n *Nodes) LogTree() {
|
||||
n.mu.RLock()
|
||||
defer n.mu.RUnlock()
|
||||
|
||||
n.logNode(0, "", true)
|
||||
}
|
||||
|
||||
func (n *Nodes) logNode(id int, prefix string, isLast bool) {
|
||||
node := n.nodes[id]
|
||||
|
||||
if id == 0 {
|
||||
log.Printf("%s", node)
|
||||
n.logChildrenByInterface(id, "")
|
||||
} else {
|
||||
connector := "├──"
|
||||
if isLast {
|
||||
connector = "└──"
|
||||
}
|
||||
|
||||
childPort := node.LocalPort
|
||||
if childPort == "" {
|
||||
childPort = "??"
|
||||
}
|
||||
|
||||
log.Printf("%s%s %s on %s", prefix, connector, childPort, node)
|
||||
|
||||
children := n.getChildren(id)
|
||||
for i, childID := range children {
|
||||
childIsLast := i == len(children)-1
|
||||
childPrefix := prefix
|
||||
if isLast {
|
||||
childPrefix += " "
|
||||
} else {
|
||||
childPrefix += "│ "
|
||||
}
|
||||
n.logNode(childID, childPrefix, childIsLast)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Nodes) logChildrenByInterface(parentID int, prefix string) {
|
||||
children := n.getChildren(parentID)
|
||||
|
||||
byInterface := map[string][]int{}
|
||||
for _, childID := range children {
|
||||
child := n.nodes[childID]
|
||||
iface := child.ParentPort
|
||||
if iface == "" {
|
||||
iface = "??"
|
||||
}
|
||||
byInterface[iface] = append(byInterface[iface], childID)
|
||||
}
|
||||
|
||||
var interfaces []string
|
||||
for iface := range byInterface {
|
||||
interfaces = append(interfaces, iface)
|
||||
}
|
||||
sort.Strings(interfaces)
|
||||
|
||||
for i, iface := range interfaces {
|
||||
isLastInterface := i == len(interfaces)-1
|
||||
connector := "├──"
|
||||
if isLastInterface {
|
||||
connector = "└──"
|
||||
}
|
||||
|
||||
log.Printf("%s%s %s", prefix, connector, iface)
|
||||
|
||||
nodes := byInterface[iface]
|
||||
for j, nodeID := range nodes {
|
||||
isLastNode := j == len(nodes)-1
|
||||
nodeConnector := "├──"
|
||||
if isLastNode {
|
||||
nodeConnector = "└──"
|
||||
}
|
||||
|
||||
nodePrefix := prefix
|
||||
if isLastInterface {
|
||||
nodePrefix += " "
|
||||
} else {
|
||||
nodePrefix += "│ "
|
||||
}
|
||||
|
||||
node := n.nodes[nodeID]
|
||||
childPort := node.LocalPort
|
||||
if childPort == "" {
|
||||
childPort = "??"
|
||||
}
|
||||
|
||||
log.Printf("%s%s %s on %s", nodePrefix, nodeConnector, childPort, node)
|
||||
|
||||
grandchildren := n.getChildren(nodeID)
|
||||
if len(grandchildren) > 0 {
|
||||
grandchildPrefix := nodePrefix
|
||||
if isLastNode {
|
||||
grandchildPrefix += " "
|
||||
} else {
|
||||
grandchildPrefix += "│ "
|
||||
}
|
||||
n.logChildrenByInterface(nodeID, grandchildPrefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Nodes) getChildren(parentID int) []int {
|
||||
var children []int
|
||||
for id, node := range n.nodes {
|
||||
if node.ParentID == parentID && id != 0 {
|
||||
children = append(children, id)
|
||||
}
|
||||
}
|
||||
sort.Ints(children)
|
||||
return children
|
||||
}
|
||||
|
||||
70
snmp.go
70
snmp.go
@@ -5,26 +5,12 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gosnmp/gosnmp"
|
||||
)
|
||||
|
||||
var (
|
||||
addToParentRules = []*regexp.Regexp{
|
||||
regexp.MustCompile(`CPU Interface`),
|
||||
}
|
||||
|
||||
portNameRewrites = []struct {
|
||||
regex *regexp.Regexp
|
||||
replacement string
|
||||
}{
|
||||
{regexp.MustCompile(`Slot: (\d+) Port: (\d+) .+`), "$1/$2"},
|
||||
}
|
||||
)
|
||||
|
||||
type snmpConfig struct {
|
||||
username string
|
||||
authKey string
|
||||
@@ -181,7 +167,7 @@ func (t *Tendrils) queryInterfaceMACs(snmp *gosnmp.GoSNMP, deviceIP net.IP) {
|
||||
}
|
||||
|
||||
if len(macs) > 0 {
|
||||
t.nodes.Update([]net.IP{deviceIP}, macs, "", "", "snmp-ifmac")
|
||||
t.nodes.Update([]net.IP{deviceIP}, macs, "snmp-ifmac")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,70 +212,24 @@ func (t *Tendrils) queryBridgeMIB(snmp *gosnmp.GoSNMP, deviceIP net.IP) {
|
||||
|
||||
for _, entry := range macPorts {
|
||||
mac := entry.mac
|
||||
bridgePort := entry.bridgePort
|
||||
|
||||
if isBroadcastOrZero(mac) {
|
||||
continue
|
||||
}
|
||||
|
||||
ifIndex, exists := bridgePortToIfIndex[bridgePort]
|
||||
if t.DebugSNMP {
|
||||
ifIndex, exists := bridgePortToIfIndex[entry.bridgePort]
|
||||
if !exists {
|
||||
ifIndex = bridgePort
|
||||
ifIndex = entry.bridgePort
|
||||
}
|
||||
|
||||
ifName := ifNames[ifIndex]
|
||||
if ifName == "" {
|
||||
ifName = "??"
|
||||
}
|
||||
|
||||
addToParent := false
|
||||
for _, rule := range addToParentRules {
|
||||
if rule.MatchString(ifName) {
|
||||
addToParent = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, rewrite := range portNameRewrites {
|
||||
if rewrite.regex.MatchString(ifName) {
|
||||
ifName = rewrite.regex.ReplaceAllString(ifName, rewrite.replacement)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if t.DebugSNMP {
|
||||
log.Printf("[snmp] %s: mac=%s port=%s", deviceIP, mac, ifName)
|
||||
}
|
||||
|
||||
if addToParent {
|
||||
t.nodes.Update([]net.IP{deviceIP}, []net.HardwareAddr{mac}, "", "", "snmp")
|
||||
} else {
|
||||
t.nodes.mu.RLock()
|
||||
deviceNodeID := -1
|
||||
if id, exists := t.nodes.ipIndex[deviceIP.String()]; exists {
|
||||
deviceNodeID = id
|
||||
}
|
||||
macNodeID := -1
|
||||
if id, exists := t.nodes.macIndex[mac.String()]; exists {
|
||||
macNodeID = id
|
||||
}
|
||||
|
||||
if deviceNodeID != -1 && macNodeID != -1 {
|
||||
deviceNode := t.nodes.nodes[deviceNodeID]
|
||||
if deviceNode.ParentID == macNodeID {
|
||||
t.nodes.mu.RUnlock()
|
||||
t.nodes.mu.Lock()
|
||||
if deviceNode.LocalPort == "" {
|
||||
deviceNode.LocalPort = ifName
|
||||
}
|
||||
t.nodes.mu.Unlock()
|
||||
continue
|
||||
}
|
||||
}
|
||||
t.nodes.mu.RUnlock()
|
||||
|
||||
t.nodes.UpdateWithParent(deviceIP, nil, []net.HardwareAddr{mac}, ifName, "", "snmp")
|
||||
}
|
||||
t.nodes.Update(nil, []net.HardwareAddr{mac}, "snmp")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ type Tendrils struct {
|
||||
DisableARP bool
|
||||
DisableLLDP bool
|
||||
DisableSNMP bool
|
||||
LogTree bool
|
||||
LogReasons bool
|
||||
DebugARP bool
|
||||
DebugLLDP bool
|
||||
|
||||
Reference in New Issue
Block a user