refactor to per-node snmp polling and immediate arp dump
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
98
nodes.go
98
nodes.go
@@ -1,11 +1,13 @@
|
||||
package tendrils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fvbommel/sortorder"
|
||||
)
|
||||
@@ -100,10 +102,11 @@ type PoEBudget struct {
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
Name string
|
||||
Interfaces map[string]*Interface
|
||||
MACTable map[string]string // peer MAC -> local interface name
|
||||
PoEBudget *PoEBudget
|
||||
Name string
|
||||
Interfaces map[string]*Interface
|
||||
MACTable map[string]string // peer MAC -> local interface name
|
||||
PoEBudget *PoEBudget
|
||||
pollTrigger chan struct{}
|
||||
}
|
||||
|
||||
func (n *Node) String() string {
|
||||
@@ -131,24 +134,35 @@ func (n *Node) String() string {
|
||||
}
|
||||
|
||||
type Nodes struct {
|
||||
mu sync.RWMutex
|
||||
nodes map[int]*Node
|
||||
ipIndex map[string]int
|
||||
macIndex map[string]int
|
||||
nextID int
|
||||
t *Tendrils
|
||||
mu sync.RWMutex
|
||||
nodes map[int]*Node
|
||||
ipIndex map[string]int
|
||||
macIndex map[string]int
|
||||
nodeCancel map[int]context.CancelFunc
|
||||
nextID int
|
||||
t *Tendrils
|
||||
ctx context.Context
|
||||
cancelAll context.CancelFunc
|
||||
}
|
||||
|
||||
func NewNodes(t *Tendrils) *Nodes {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return &Nodes{
|
||||
nodes: map[int]*Node{},
|
||||
ipIndex: map[string]int{},
|
||||
macIndex: map[string]int{},
|
||||
nextID: 1,
|
||||
t: t,
|
||||
nodes: map[int]*Node{},
|
||||
ipIndex: map[string]int{},
|
||||
macIndex: map[string]int{},
|
||||
nodeCancel: map[int]context.CancelFunc{},
|
||||
nextID: 1,
|
||||
t: t,
|
||||
ctx: ctx,
|
||||
cancelAll: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Nodes) Shutdown() {
|
||||
n.cancelAll()
|
||||
}
|
||||
|
||||
func (n *Nodes) Update(target *Node, mac net.HardwareAddr, ips []net.IP, ifaceName, nodeName, source string) {
|
||||
n.mu.Lock()
|
||||
defer n.mu.Unlock()
|
||||
@@ -184,18 +198,22 @@ func (n *Nodes) Update(target *Node, mac net.HardwareAddr, ips []net.IP, ifaceNa
|
||||
}
|
||||
}
|
||||
|
||||
var node *Node
|
||||
if targetID == -1 {
|
||||
targetID = n.nextID
|
||||
n.nextID++
|
||||
n.nodes[targetID] = &Node{
|
||||
Interfaces: map[string]*Interface{},
|
||||
MACTable: map[string]string{},
|
||||
node = &Node{
|
||||
Interfaces: map[string]*Interface{},
|
||||
MACTable: map[string]string{},
|
||||
pollTrigger: make(chan struct{}, 1),
|
||||
}
|
||||
n.nodes[targetID] = node
|
||||
isNew = true
|
||||
n.startNodePoller(targetID, node)
|
||||
} else {
|
||||
node = n.nodes[targetID]
|
||||
}
|
||||
|
||||
node := n.nodes[targetID]
|
||||
|
||||
var added []string
|
||||
if mac != nil {
|
||||
added = n.updateNodeInterface(node, targetID, mac, ips, ifaceName)
|
||||
@@ -206,6 +224,14 @@ func (n *Nodes) Update(target *Node, mac net.HardwareAddr, ips []net.IP, ifaceNa
|
||||
added = append(added, "name="+nodeName)
|
||||
}
|
||||
|
||||
hasNewIP := false
|
||||
for _, a := range added {
|
||||
if len(a) > 3 && a[:3] == "ip=" {
|
||||
hasNewIP = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(added) > 0 {
|
||||
if n.t.LogEvents {
|
||||
if isNew {
|
||||
@@ -218,6 +244,38 @@ func (n *Nodes) Update(target *Node, mac net.HardwareAddr, ips []net.IP, ifaceNa
|
||||
n.logNode(node)
|
||||
}
|
||||
}
|
||||
|
||||
if hasNewIP {
|
||||
n.triggerPoll(node)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Nodes) startNodePoller(nodeID int, node *Node) {
|
||||
ctx, cancel := context.WithCancel(n.ctx)
|
||||
n.nodeCancel[nodeID] = cancel
|
||||
|
||||
go func() {
|
||||
ticker := time.NewTicker(10 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-node.pollTrigger:
|
||||
n.t.pollNode(node)
|
||||
case <-ticker.C:
|
||||
n.t.pollNode(node)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (n *Nodes) triggerPoll(node *Node) {
|
||||
select {
|
||||
case node.pollTrigger <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Nodes) updateNodeInterface(node *Node, nodeID int, mac net.HardwareAddr, ips []net.IP, ifaceName string) []string {
|
||||
|
||||
Reference in New Issue
Block a user