master
go 106 lines 2.82 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package snmptopology
4
5 import (
6 "sync"
7 )
8
9 type topologyQueryOptions struct {
10 CollapseActorsByIP bool
11 EliminateNonIPInferred bool
12 MapType string
13 InferenceStrategy string
14 ManagedDeviceFocus string
15 Depth int
16 ResolveDNSName func(ip string) string
17 }
18
19 type topologyRegistry struct {
20 mu sync.RWMutex
21 caches map[*topologyCache]struct{}
22 }
23
24 type topologyManagedFocusTarget struct {
25 Value string
26 Name string
27 }
28
29 func newTopologyRegistry() *topologyRegistry {
30 return &topologyRegistry{
31 caches: make(map[*topologyCache]struct{}),
32 }
33 }
34
35 var snmpTopologyRegistry = newTopologyRegistry()
36
37 func (r *topologyRegistry) register(cache *topologyCache) {
38 if r == nil || cache == nil {
39 return
40 }
41 r.mu.Lock()
42 r.caches[cache] = struct{}{}
43 r.mu.Unlock()
44 }
45
46 func (r *topologyRegistry) unregister(cache *topologyCache) {
47 if r == nil || cache == nil {
48 return
49 }
50 r.mu.Lock()
51 delete(r.caches, cache)
52 r.mu.Unlock()
53 }
54
55 func (r *topologyRegistry) snapshot() (topologyData, bool) {
56 return r.snapshotWithOptions(topologyQueryOptions{
57 CollapseActorsByIP: true,
58 EliminateNonIPInferred: true,
59 MapType: topologyMapTypeLLDPCDPManaged,
60 InferenceStrategy: topologyInferenceStrategyFDBMinimumKnowledge,
61 ManagedDeviceFocus: topologyManagedFocusAllDevices,
62 Depth: topologyDepthAllInternal,
63 ResolveDNSName: resolveTopologyReverseDNSName, // live resolver — warms the cache
64 })
65 }
66
67 func (r *topologyRegistry) snapshotWithOptions(options topologyQueryOptions) (topologyData, bool) {
68 if r == nil {
69 return topologyData{}, false
70 }
71 options = normalizeTopologyQueryOptions(options)
72
73 aggregate, ok := aggregateTopologyObservationSnapshots(r.observationSnapshots())
74 if !ok {
75 return topologyData{}, false
76 }
77
78 return buildSNMPTopologySnapshot(aggregate, options)
79 }
80
81 func normalizeTopologyQueryOptions(options topologyQueryOptions) topologyQueryOptions {
82 options.MapType = normalizeTopologyMapType(options.MapType)
83 if options.MapType == "" {
84 options.MapType = topologyMapTypeLLDPCDPManaged
85 }
86 options.InferenceStrategy = normalizeTopologyInferenceStrategy(options.InferenceStrategy)
87 if options.InferenceStrategy == "" {
88 options.InferenceStrategy = topologyInferenceStrategyFDBMinimumKnowledge
89 }
90 options.ManagedDeviceFocus = formatTopologyManagedFocuses(parseTopologyManagedFocuses(options.ManagedDeviceFocus))
91 if options.Depth != topologyDepthAllInternal {
92 if options.Depth < topologyDepthMin {
93 options.Depth = topologyDepthMin
94 } else if options.Depth > topologyDepthMax {
95 options.Depth = topologyDepthMax
96 }
97 }
98 return options
99 }
100
101 func (r *topologyRegistry) managedDeviceFocusTargets() []topologyManagedFocusTarget {
102 if r == nil {
103 return nil
104 }
105 return buildTopologyManagedFocusTargets(r.observationSnapshots())
106 }