master
go 150 lines 3.71 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package l2topology
4
5 import (
6 "sort"
7 "strings"
8 )
9
10 func buildFDBReporterAliases(
11 deviceByID map[string]Device,
12 ifaceByDeviceIndex map[string]Interface,
13 ) map[string][]string {
14 aliases := make(map[string]map[string]struct{}, len(deviceByID))
15
16 for _, device := range deviceByID {
17 deviceID := strings.TrimSpace(device.ID)
18 if deviceID == "" {
19 continue
20 }
21 chassisMAC := normalizeMAC(device.ChassisID)
22 if chassisMAC == "" {
23 continue
24 }
25 if aliases[deviceID] == nil {
26 aliases[deviceID] = make(map[string]struct{})
27 }
28 aliases[deviceID]["mac:"+chassisMAC] = struct{}{}
29 }
30
31 for _, iface := range ifaceByDeviceIndex {
32 deviceID := strings.TrimSpace(iface.DeviceID)
33 if deviceID == "" {
34 continue
35 }
36 ifaceMAC := normalizeMAC(iface.MAC)
37 if ifaceMAC == "" {
38 continue
39 }
40 if aliases[deviceID] == nil {
41 aliases[deviceID] = make(map[string]struct{})
42 }
43 aliases[deviceID]["mac:"+ifaceMAC] = struct{}{}
44 }
45
46 out := make(map[string][]string, len(aliases))
47 for deviceID, set := range aliases {
48 values := sortedTopologySet(set)
49 if len(values) == 0 {
50 continue
51 }
52 out[deviceID] = values
53 }
54
55 return out
56 }
57
58 func buildFDBReporterObservations(macLinks []bridgeMacLinkRecord) fdbReporterObservation {
59 obs := fdbReporterObservation{
60 byEndpoint: make(map[string]map[string]map[string]struct{}),
61 byReporter: make(map[string]map[string]map[string]struct{}),
62 }
63 for _, link := range macLinks {
64 if strings.ToLower(strings.TrimSpace(link.method)) != "fdb" {
65 continue
66 }
67 reporterID := strings.TrimSpace(link.port.deviceID)
68 if reporterID == "" {
69 continue
70 }
71 endpointID := normalizeFDBEndpointID(link.endpointID)
72 if endpointID == "" {
73 continue
74 }
75 portKey := bridgePortObservationKey(link.port)
76 if portKey == "" {
77 continue
78 }
79
80 byEndpointReporter := obs.byEndpoint[endpointID]
81 if byEndpointReporter == nil {
82 byEndpointReporter = make(map[string]map[string]struct{})
83 obs.byEndpoint[endpointID] = byEndpointReporter
84 }
85 if byEndpointReporter[reporterID] == nil {
86 byEndpointReporter[reporterID] = make(map[string]struct{})
87 }
88 byEndpointReporter[reporterID][portKey] = struct{}{}
89
90 byReporterEndpoint := obs.byReporter[reporterID]
91 if byReporterEndpoint == nil {
92 byReporterEndpoint = make(map[string]map[string]struct{})
93 obs.byReporter[reporterID] = byReporterEndpoint
94 }
95 if byReporterEndpoint[endpointID] == nil {
96 byReporterEndpoint[endpointID] = make(map[string]struct{})
97 }
98 byReporterEndpoint[endpointID][portKey] = struct{}{}
99 }
100 return obs
101 }
102
103 func normalizeFDBEndpointID(endpointID string) string {
104 kind, value, ok := strings.Cut(strings.TrimSpace(endpointID), ":")
105 if !ok {
106 return ""
107 }
108 switch strings.ToLower(strings.TrimSpace(kind)) {
109 case "mac":
110 if mac := normalizeMAC(value); mac != "" {
111 return "mac:" + mac
112 }
113 }
114 return ""
115 }
116
117 func buildFDBAliasOwnerMap(reporterAliases map[string][]string) map[string]map[string]struct{} {
118 if len(reporterAliases) == 0 {
119 return nil
120 }
121 aliasOwners := make(map[string]map[string]struct{})
122 reporterIDs := make([]string, 0, len(reporterAliases))
123 for reporterID := range reporterAliases {
124 reporterID = strings.TrimSpace(reporterID)
125 if reporterID == "" {
126 continue
127 }
128 reporterIDs = append(reporterIDs, reporterID)
129 }
130 sort.Strings(reporterIDs)
131 for _, reporterID := range reporterIDs {
132 aliases := uniqueTopologyStrings(reporterAliases[reporterID])
133 for _, alias := range aliases {
134 alias = normalizeFDBEndpointID(alias)
135 if alias == "" {
136 continue
137 }
138 owners := aliasOwners[alias]
139 if owners == nil {
140 owners = make(map[string]struct{})
141 aliasOwners[alias] = owners
142 }
143 owners[reporterID] = struct{}{}
144 }
145 }
146 if len(aliasOwners) == 0 {
147 return nil
148 }
149 return aliasOwners
150 }