master
go 234 lines 6.96 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package l2topology
4
5 import (
6 "net/netip"
7 "strings"
8 "time"
9 )
10
11 // GraphOptions controls conversion from Result to the internal graph projection.
12 type GraphOptions struct {
13 SchemaVersion string
14 Source string
15 Layer string
16 View string
17 AgentID string
18 LocalDeviceID string
19 CollectedAt time.Time
20 ResolveDNSName func(ip string) string
21 CollapseActorsByIP bool
22 EliminateNonIPInferred bool
23 ProbabilisticConnectivity bool
24 InferenceStrategy string
25 }
26
27 const (
28 topologyInferenceStrategyFDBMinimumKnowledge = "fdb_minimum_knowledge"
29 topologyInferenceStrategySTPParentTree = "stp_parent_tree"
30 topologyInferenceStrategyFDBPairwise = "fdb_pairwise_minimum_knowledge"
31 topologyInferenceStrategySTPFDBCorrelated = "stp_fdb_correlated"
32 topologyInferenceStrategyCDPFDBHybrid = "cdp_fdb_hybrid"
33 )
34
35 type topologyInferenceStrategyConfig struct {
36 id string
37 includeLLDPBridgeLinks bool
38 includeCDPBridgeLinks bool
39 includeSTPBridgeLinks bool
40 useSTPDesignatedParent bool
41 enableFDBPairwiseLinks bool
42 enableSTPManagedAliasCorrelation bool
43 filterSwitchFacingAttachments bool
44 }
45
46 type endpointActorAccumulator struct {
47 endpointID string
48 mac string
49 ips map[string]netip.Addr
50 sources map[string]struct{}
51 deviceIDs map[string]struct{}
52 ifIndexes map[string]struct{}
53 ifNames map[string]struct{}
54 }
55
56 type projectedSegments struct {
57 actors []Actor
58 links []Link
59 linksFdb int
60 bidirectionalCount int
61 endpointLinksCandidates int
62 endpointLinksEmitted int
63 endpointLinksSuppressed int
64 endpointsWithAmbiguousSegment int
65 endpointDirectOwners map[string]fdbEndpointOwner
66 suppressedManagedOverlapIDs map[string]struct{}
67 }
68
69 type fdbReporterObservation struct {
70 byEndpoint map[string]map[string]map[string]struct{}
71 byReporter map[string]map[string]map[string]struct{}
72 }
73
74 type fdbEndpointOwner struct {
75 portKey string
76 portVLANKey string
77 port bridgePortRef
78 source string
79 }
80
81 type probableEndpointReporterHint struct {
82 deviceID string
83 ifIndex int
84 ifName string
85 }
86
87 type segmentReporterIndex struct {
88 byDevice map[string]map[string]struct{}
89 byDeviceIfIndex map[string]map[string]struct{}
90 byDeviceIfName map[string]map[string]struct{}
91 }
92
93 type topologyIdentityKeySet map[string]struct{}
94
95 type topologyDevicePortStatus struct {
96 IfIndex int
97 IfName string
98 IfDescr string
99 IfAlias string
100 MAC string
101 SpeedBps int64
102 LastChange int64
103 Duplex string
104 InterfaceType string
105 AdminStatus string
106 OperStatus string
107 LinkMode string
108 ModeConfidence string
109 ModeSources []string
110 VLANIDs []string
111 TopologyRole string
112 RoleConfidence string
113 RoleSources []string
114 FDBMACCount int
115 STPState string
116 VLANs []map[string]any
117 Neighbors []topologyPortNeighborStatus
118 }
119
120 type topologyPortNeighborStatus struct {
121 Protocol string
122 RemoteDevice string
123 RemotePort string
124 RemoteIP string
125 RemoteChassisID string
126 RemoteCapabilities []string
127 }
128
129 type topologyDeviceInterfaceSummary struct {
130 portsTotal int
131 ifIndexes []string
132 ifNames []string
133 adminStatusCount map[string]any
134 operStatusCount map[string]any
135 linkModeCount map[string]any
136 roleCount map[string]any
137 portsUp int
138 portsDown int
139 portsAdminDown int
140 totalBandwidthBps int64
141 fdbTotalMACs int
142 vlanCount int
143 lldpNeighborCount int
144 cdpNeighborCount int
145 portStatuses []map[string]any
146 }
147
148 type topologyDevicePortEvidence struct {
149 vlanIDs map[string]struct{}
150 vlanNames map[string]string
151 fdbEndpointIDs map[string]struct{}
152 hasFDB bool
153 hasFDBManagedAlias bool
154 hasSTP bool
155 hasPeer bool
156 hasBridgeLink bool
157 isLAG bool
158 stpStates map[string]struct{}
159 neighbors map[string]topologyPortNeighborStatus
160 }
161
162 func normalizeTopologyInferenceStrategy(value string) string {
163 switch strings.ToLower(strings.TrimSpace(value)) {
164 case "", topologyInferenceStrategyFDBMinimumKnowledge:
165 return topologyInferenceStrategyFDBMinimumKnowledge
166 case topologyInferenceStrategySTPParentTree:
167 return topologyInferenceStrategySTPParentTree
168 case topologyInferenceStrategyFDBPairwise:
169 return topologyInferenceStrategyFDBPairwise
170 case topologyInferenceStrategySTPFDBCorrelated:
171 return topologyInferenceStrategySTPFDBCorrelated
172 case topologyInferenceStrategyCDPFDBHybrid:
173 return topologyInferenceStrategyCDPFDBHybrid
174 default:
175 return topologyInferenceStrategyFDBMinimumKnowledge
176 }
177 }
178
179 func topologyInferenceStrategyConfigFor(strategy string) topologyInferenceStrategyConfig {
180 switch normalizeTopologyInferenceStrategy(strategy) {
181 case topologyInferenceStrategySTPParentTree:
182 return topologyInferenceStrategyConfig{
183 id: topologyInferenceStrategySTPParentTree,
184 includeSTPBridgeLinks: true,
185 useSTPDesignatedParent: true,
186 filterSwitchFacingAttachments: true,
187 }
188 case topologyInferenceStrategyFDBPairwise:
189 return topologyInferenceStrategyConfig{
190 id: topologyInferenceStrategyFDBPairwise,
191 enableFDBPairwiseLinks: true,
192 filterSwitchFacingAttachments: true,
193 }
194 case topologyInferenceStrategySTPFDBCorrelated:
195 return topologyInferenceStrategyConfig{
196 id: topologyInferenceStrategySTPFDBCorrelated,
197 includeLLDPBridgeLinks: true,
198 includeCDPBridgeLinks: true,
199 includeSTPBridgeLinks: true,
200 useSTPDesignatedParent: true,
201 enableFDBPairwiseLinks: true,
202 enableSTPManagedAliasCorrelation: true,
203 filterSwitchFacingAttachments: true,
204 }
205 case topologyInferenceStrategyCDPFDBHybrid:
206 return topologyInferenceStrategyConfig{
207 id: topologyInferenceStrategyCDPFDBHybrid,
208 includeCDPBridgeLinks: true,
209 enableFDBPairwiseLinks: true,
210 filterSwitchFacingAttachments: true,
211 }
212 default:
213 return topologyInferenceStrategyConfig{
214 id: topologyInferenceStrategyFDBMinimumKnowledge,
215 includeLLDPBridgeLinks: true,
216 includeCDPBridgeLinks: true,
217 filterSwitchFacingAttachments: true,
218 }
219 }
220 }
221
222 // ToGraph converts an engine result to the internal graph projection.
223 func ToGraph(result Result, opts GraphOptions) Graph {
224 builder := newGraphBuilder(result, opts)
225 builder.prepareIndexes()
226 builder.collectBridgeTopologyInputs()
227 builder.buildDeviceActors()
228 builder.projectAdjacencyTopology()
229 builder.buildEndpointTopology()
230 builder.buildSegmentTopology()
231 builder.finalizeGraph()
232 builder.buildStats()
233 return builder.graph()
234 }