diff --git a/arp.go b/arp.go index e2636bb..b6a42b3 100644 --- a/arp.go +++ b/arp.go @@ -36,6 +36,8 @@ type arpEntry struct { func (t *Tendrils) readARPTable() { entries := t.parseARPTable() + localNode := t.getLocalNode() + for _, entry := range entries { if t.Interface != "" && entry.iface != t.Interface { continue @@ -49,6 +51,9 @@ func (t *Tendrils) readARPTable() { } t.nodes.Update(nil, entry.mac, []net.IP{entry.ip}, "", "", "arp") + if localNode != nil { + t.nodes.UpdateMACTable(localNode, entry.mac, entry.iface) + } } } diff --git a/nodes.go b/nodes.go index 1f00beb..eb9ae06 100644 --- a/nodes.go +++ b/nodes.go @@ -42,6 +42,7 @@ func (i *Interface) String() string { type Node struct { Name string Interfaces map[string]*Interface + MACTable map[string]string // peer MAC -> local interface name } func (n *Node) String() string { @@ -118,6 +119,7 @@ func (n *Nodes) Update(target *Node, mac net.HardwareAddr, ips []net.IP, ifaceNa n.nextID++ n.nodes[targetID] = &Node{ Interfaces: map[string]*Interface{}, + MACTable: map[string]string{}, } isNew = true } @@ -263,6 +265,13 @@ func (n *Nodes) mergeNodes(keepID, mergeID int) { n.macIndex[iface.MAC.String()] = keepID } + for peerMAC, ifaceName := range merge.MACTable { + if keep.MACTable == nil { + keep.MACTable = map[string]string{} + } + keep.MACTable[peerMAC] = ifaceName + } + delete(n.nodes, mergeID) } @@ -286,6 +295,16 @@ func (n *Nodes) GetByMAC(mac net.HardwareAddr) *Node { return nil } +func (n *Nodes) UpdateMACTable(node *Node, peerMAC net.HardwareAddr, ifaceName string) { + n.mu.Lock() + defer n.mu.Unlock() + + if node.MACTable == nil { + node.MACTable = map[string]string{} + } + node.MACTable[peerMAC.String()] = ifaceName +} + func (n *Nodes) logNode(node *Node) { name := node.Name if name == "" { @@ -303,6 +322,10 @@ func (n *Nodes) logNode(node *Node) { iface := node.Interfaces[ifaceKey] log.Printf("[node] %s", iface) } + + if len(node.MACTable) > 0 { + log.Printf("[node] mac table: %d entries", len(node.MACTable)) + } } func (n *Nodes) All() []*Node { diff --git a/snmp.go b/snmp.go index 7caa912..a89e4b2 100644 --- a/snmp.go +++ b/snmp.go @@ -124,7 +124,7 @@ func (t *Tendrils) querySNMPDevice(node *Node, ip net.IP) { t.querySysName(snmp, node) t.queryInterfaceMACs(snmp, node) - t.queryBridgeMIB(snmp, ip) + t.queryBridgeMIB(snmp, node) } func (t *Tendrils) querySysName(snmp *gosnmp.GoSNMP, node *Node) { @@ -192,7 +192,7 @@ func (t *Tendrils) queryInterfaceMACs(snmp *gosnmp.GoSNMP, node *Node) { } } -func (t *Tendrils) queryBridgeMIB(snmp *gosnmp.GoSNMP, deviceIP net.IP) { +func (t *Tendrils) queryBridgeMIB(snmp *gosnmp.GoSNMP, node *Node) { portOID := "1.3.6.1.2.1.17.7.1.2.2.1.2" portResults, err := snmp.BulkWalkAll(portOID) @@ -238,19 +238,18 @@ func (t *Tendrils) queryBridgeMIB(snmp *gosnmp.GoSNMP, deviceIP net.IP) { continue } + ifIndex, exists := bridgePortToIfIndex[entry.bridgePort] + if !exists { + ifIndex = entry.bridgePort + } + ifName := rewritePortName(ifNames[ifIndex]) + 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) + log.Printf("[snmp] %s: mac=%s port=%s", snmp.Target, mac, ifName) } t.nodes.Update(nil, mac, nil, "", "", "snmp") + t.nodes.UpdateMACTable(node, mac, ifName) } } diff --git a/tendrils.go b/tendrils.go index 80ad4d0..ac520a3 100644 --- a/tendrils.go +++ b/tendrils.go @@ -97,6 +97,22 @@ func (t *Tendrils) populateLocalAddresses() { } } +func (t *Tendrils) getLocalNode() *Node { + interfaces, err := net.Interfaces() + if err != nil { + return nil + } + + for _, iface := range interfaces { + if len(iface.HardwareAddr) > 0 { + if node := t.nodes.GetByMAC(iface.HardwareAddr); node != nil { + return node + } + } + } + return nil +} + func (t *Tendrils) listInterfaces() []net.Interface { interfaces, err := net.Interfaces() if err != nil {