master
go 122 lines 3.95 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package l2topology
4
5 import (
6 "strings"
7 "time"
8 )
9
10 type l2BuildState struct {
11 devices map[string]Device
12 managedObservationByDeviceID map[string]bool
13 interfaces map[string]Interface
14 adjacencies map[string]Adjacency
15 attachments map[string]Attachment
16 enrichments map[string]*enrichmentAccumulator
17 ifNameByDeviceIfIndex map[string]string
18
19 hostToID map[string]string
20 ipToID map[string]string
21 chassisToID map[string]string
22 macToID map[string]string
23 bridgeAddrToID map[string]string
24
25 linksLLDP int
26 linksCDP int
27 linksSTP int
28 attachmentsFDB int
29 enrichmentsARPND int
30
31 bridgeDomains map[string]struct{}
32 endpointIDs map[string]struct{}
33 }
34
35 func newL2BuildState(observationCount int) *l2BuildState {
36 return &l2BuildState{
37 devices: make(map[string]Device, observationCount),
38 managedObservationByDeviceID: make(map[string]bool, observationCount),
39 interfaces: make(map[string]Interface),
40 adjacencies: make(map[string]Adjacency),
41 attachments: make(map[string]Attachment),
42 enrichments: make(map[string]*enrichmentAccumulator),
43 ifNameByDeviceIfIndex: make(map[string]string),
44 hostToID: make(map[string]string, observationCount),
45 ipToID: make(map[string]string, observationCount),
46 chassisToID: make(map[string]string, observationCount),
47 macToID: make(map[string]string, observationCount),
48 bridgeAddrToID: make(map[string]string, observationCount),
49 bridgeDomains: make(map[string]struct{}),
50 endpointIDs: make(map[string]struct{}),
51 }
52 }
53
54 func (s *l2BuildState) refreshEndpointIndex() {
55 for endpointID := range s.endpointIDs {
56 delete(s.endpointIDs, endpointID)
57 }
58 for _, attachment := range s.attachments {
59 endpointID := strings.TrimSpace(attachment.EndpointID)
60 if endpointID == "" {
61 continue
62 }
63 s.endpointIDs[endpointID] = struct{}{}
64 }
65 for _, enrichment := range s.enrichments {
66 if enrichment == nil {
67 continue
68 }
69 endpointID := strings.TrimSpace(enrichment.EndpointID)
70 if endpointID == "" {
71 continue
72 }
73 s.endpointIDs[endpointID] = struct{}{}
74 }
75 }
76
77 func (s *l2BuildState) markManagedDevices() {
78 for id, dev := range s.devices {
79 if dev.Labels == nil {
80 dev.Labels = make(map[string]string)
81 }
82 if s.managedObservationByDeviceID[id] {
83 dev.Labels["inferred"] = "false"
84 } else {
85 dev.Labels["inferred"] = "true"
86 }
87 s.devices[id] = dev
88 }
89 }
90
91 func (s *l2BuildState) buildResult(identityAliasStats identityAliasReconcileStats, collectedAt time.Time) Result {
92 if !collectedAt.IsZero() {
93 collectedAt = collectedAt.UTC()
94 }
95
96 stats := newL2ResultStats()
97 stats["devices_total"] = len(s.devices)
98 stats["links_total"] = len(s.adjacencies)
99 stats["links_lldp"] = s.linksLLDP
100 stats["links_cdp"] = s.linksCDP
101 stats["links_stp"] = s.linksSTP
102 stats["attachments_total"] = len(s.attachments)
103 stats["attachments_fdb"] = s.attachmentsFDB
104 stats["enrichments_total"] = len(s.enrichments)
105 stats["enrichments_arp_nd"] = s.enrichmentsARPND
106 stats["bridge_domains_total"] = len(s.bridgeDomains)
107 stats["endpoints_total"] = len(s.endpointIDs)
108 stats["identity_alias_endpoints_mapped"] = identityAliasStats.endpointsMapped
109 stats["identity_alias_endpoints_ambiguous_mac"] = identityAliasStats.endpointsAmbiguousMAC
110 stats["identity_alias_ips_merged"] = identityAliasStats.ipsMerged
111 stats["identity_alias_ips_conflict_skipped"] = identityAliasStats.ipsConflictSkipped
112
113 return Result{
114 CollectedAt: collectedAt,
115 Devices: sortedDevices(s.devices),
116 Interfaces: sortedInterfaces(s.interfaces),
117 Adjacencies: sortedAdjacencies(s.adjacencies),
118 Attachments: sortedAttachments(s.attachments),
119 Enrichments: sortedEnrichments(s.enrichments),
120 Stats: stats,
121 }
122 }