From 545a448bca06da2a258e400235ea47730fac615f Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sun, 18 Jan 2026 08:15:27 -0800 Subject: [PATCH] remove parentid and tree logging machinery Co-Authored-By: Claude Opus 4.5 --- arp.go | 2 +- cmd/tendrils/main.go | 2 - lldp.go | 2 +- nodes.go | 178 +++---------------------------------------- snmp.go | 80 +++---------------- tendrils.go | 1 - 6 files changed, 22 insertions(+), 243 deletions(-) diff --git a/arp.go b/arp.go index 4a3b64b..3bca25b 100644 --- a/arp.go +++ b/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") } } diff --git a/cmd/tendrils/main.go b/cmd/tendrils/main.go index 802c3e6..3561bef 100644 --- a/cmd/tendrils/main.go +++ b/cmd/tendrils/main.go @@ -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 diff --git a/lldp.go b/lldp.go index b4ab22f..5f3601f 100644 --- a/lldp.go +++ b/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) diff --git a/nodes.go b/nodes.go index 8b331a3..47ab940 100644 --- a/nodes.go +++ b/nodes.go @@ -9,12 +9,9 @@ import ( ) type Node struct { - Name string - IPs map[string]net.IP - MACs map[string]net.HardwareAddr - ParentID int - LocalPort string - ParentPort string + Name string + IPs map[string]net.IP + MACs map[string]net.HardwareAddr } func (n *Node) String() string { @@ -57,19 +54,14 @@ func NewNodes(t *Tendrils) *Nodes { } n.nodes[0] = &Node{ - IPs: map[string]net.IP{}, - MACs: map[string]net.HardwareAddr{}, - ParentID: 0, + IPs: map[string]net.IP{}, + MACs: map[string]net.HardwareAddr{}, } 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 { @@ -103,11 +88,8 @@ func (n *Nodes) UpdateWithParent(parentIP net.IP, ips []net.IP, macs []net.Hardw targetID = n.nextID n.nextID++ n.nodes[targetID] = &Node{ - IPs: map[string]net.IP{}, - MACs: map[string]net.HardwareAddr{}, - ParentID: parentID, - LocalPort: childPort, - ParentPort: parentPort, + IPs: map[string]net.IP{}, + MACs: map[string]net.HardwareAddr{}, } } 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,15 +132,8 @@ 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 { - log.Printf("updated %s +%v (via %s)", node, added, source) - } - if n.t.LogTree { - n.mu.Unlock() - n.LogTree() - n.mu.Lock() - } + if len(added) > 0 && n.t.LogReasons { + log.Printf("updated %s +%v (via %s)", node, added, source) } } @@ -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 -} diff --git a/snmp.go b/snmp.go index 1d621bc..c766650 100644 --- a/snmp.go +++ b/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 !exists { - ifIndex = 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 { + ifIndex, exists := bridgePortToIfIndex[entry.bridgePort] + if !exists { + ifIndex = entry.bridgePort + } + ifName := ifNames[ifIndex] + if ifName == "" { + ifName = "??" + } 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") } } diff --git a/tendrils.go b/tendrils.go index 2a75254..6a67ec7 100644 --- a/tendrils.go +++ b/tendrils.go @@ -16,7 +16,6 @@ type Tendrils struct { DisableARP bool DisableLLDP bool DisableSNMP bool - LogTree bool LogReasons bool DebugARP bool DebugLLDP bool