master
go 153 lines 3.88 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package l2topology
4
5 import (
6 "strconv"
7 "strings"
8 )
9
10 func topologyMetricString(metrics map[string]any, key string) string {
11 if len(metrics) == 0 {
12 return ""
13 }
14 value, ok := metrics[key]
15 if !ok || value == nil {
16 return ""
17 }
18 typed, ok := value.(string)
19 if !ok {
20 return ""
21 }
22 return strings.TrimSpace(typed)
23 }
24
25 func bridgeDomainSegmentID(segment *bridgeDomainSegment) string {
26 if segment == nil {
27 return ""
28 }
29 portKeys := sortedBridgePortSet(segment.ports)
30 sig := strings.Join(portKeys, "<->")
31 if sig == "" {
32 sig = portSortKey(segment.designatedPort)
33 }
34 return "bridge-domain:" + sig
35 }
36
37 func bridgePortFromAdjacencySide(deviceID, port string, ifIndexByDeviceName map[string]int) bridgePortRef {
38 deviceID = strings.TrimSpace(deviceID)
39 port = strings.TrimSpace(port)
40 if deviceID == "" || port == "" {
41 return bridgePortRef{}
42 }
43 ifIndex := resolveIfIndexByPortName(deviceID, port, ifIndexByDeviceName)
44 return bridgePortRef{
45 deviceID: deviceID,
46 ifIndex: ifIndex,
47 ifName: port,
48 bridgePort: port,
49 }
50 }
51
52 func bridgePortFromAttachment(attachment Attachment, ifaceByDeviceIndex map[string]Interface) bridgePortRef {
53 deviceID := strings.TrimSpace(attachment.DeviceID)
54 if deviceID == "" {
55 return bridgePortRef{}
56 }
57 ifIndex := attachment.IfIndex
58 ifName := strings.TrimSpace(attachment.Labels["if_name"])
59 if ifName == "" && ifIndex > 0 {
60 if iface, ok := ifaceByDeviceIndex[deviceIfIndexKey(deviceID, ifIndex)]; ok {
61 ifName = strings.TrimSpace(iface.IfName)
62 }
63 }
64 bridgePort := strings.TrimSpace(attachment.Labels["bridge_port"])
65 if bridgePort == "" {
66 if ifIndex > 0 {
67 bridgePort = strconv.Itoa(ifIndex)
68 } else {
69 bridgePort = ifName
70 }
71 }
72 vlanID := strings.TrimSpace(attachment.Labels["vlan"])
73 if vlanID == "" {
74 vlanID = strings.TrimSpace(attachment.Labels["vlan_id"])
75 }
76 return bridgePortRef{
77 deviceID: deviceID,
78 ifIndex: ifIndex,
79 ifName: ifName,
80 bridgePort: bridgePort,
81 vlanID: vlanID,
82 }
83 }
84
85 func bridgeAttachmentSortKey(attachment Attachment) string {
86 vlanID := strings.TrimSpace(attachment.Labels["vlan"])
87 if vlanID == "" {
88 vlanID = strings.TrimSpace(attachment.Labels["vlan_id"])
89 }
90 parts := []string{
91 strings.TrimSpace(attachment.DeviceID),
92 strconv.Itoa(attachment.IfIndex),
93 strings.TrimSpace(attachment.Labels["if_name"]),
94 strings.TrimSpace(attachment.Labels["bridge_port"]),
95 strings.ToLower(vlanID),
96 strings.ToLower(strings.TrimSpace(attachment.Method)),
97 strings.TrimSpace(attachment.EndpointID),
98 }
99 return strings.Join(parts, keySep)
100 }
101
102 func bridgePairKey(left, right bridgePortRef) string {
103 leftKey := bridgePortRefKey(left, false, false)
104 rightKey := bridgePortRefKey(right, false, false)
105 if leftKey == "" || rightKey == "" {
106 return ""
107 }
108 if leftKey > rightKey {
109 leftKey, rightKey = rightKey, leftKey
110 }
111 return leftKey + "<->" + rightKey
112 }
113
114 func bridgePortRefKey(port bridgePortRef, includeBridgePort bool, includeVLAN bool) string {
115 deviceID := strings.TrimSpace(port.deviceID)
116 if deviceID == "" {
117 return ""
118 }
119 bridgePort := strings.TrimSpace(port.bridgePort)
120 if bridgePort == "" && port.ifIndex > 0 {
121 bridgePort = strconv.Itoa(port.ifIndex)
122 }
123 ifName := strings.TrimSpace(port.ifName)
124 vlanID := strings.TrimSpace(port.vlanID)
125 if !includeVLAN {
126 vlanID = ""
127 }
128
129 parts := []string{
130 deviceID,
131 "if:" + strconv.Itoa(port.ifIndex),
132 "name:" + strings.ToLower(ifName),
133 }
134 if includeBridgePort {
135 parts = append(parts, "bp:"+strings.ToLower(bridgePort))
136 }
137 parts = append(parts, "vlan:"+strings.ToLower(vlanID))
138 return strings.Join(parts, keySep)
139 }
140
141 func bridgePortRefSortKey(port bridgePortRef) string {
142 return bridgePortRefKey(port, true, true)
143 }
144
145 func bridgePortDisplay(port bridgePortRef) string {
146 if name := strings.TrimSpace(port.ifName); name != "" {
147 return name
148 }
149 if port.ifIndex > 0 {
150 return strconv.Itoa(port.ifIndex)
151 }
152 return strings.TrimSpace(port.bridgePort)
153 }