master
go 152 lines 3 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package l2topology
4
5 import (
6 "math"
7 "strconv"
8 "strings"
9 "time"
10 )
11
12 func topologyCanonicalPortName(attrs map[string]any) string {
13 if name := topologyAttrString(attrs, "port_name"); name != "" {
14 return name
15 }
16 if name := topologyAttrString(attrs, "if_name"); name != "" {
17 return name
18 }
19 if name := topologyAttrString(attrs, "if_descr"); name != "" {
20 return name
21 }
22 if name := topologyAttrString(attrs, "if_alias"); name != "" {
23 return name
24 }
25
26 if ifIndex := topologyAttrInt(attrs, "if_index"); ifIndex > 0 {
27 return strconv.Itoa(ifIndex)
28 }
29
30 if portID := topologyAttrString(attrs, "port_id"); portID != "" {
31 if n, err := strconv.Atoi(strings.TrimSpace(portID)); err == nil && n > 0 {
32 return strconv.Itoa(n)
33 }
34 return portID
35 }
36 if bridgePort := topologyAttrString(attrs, "bridge_port"); bridgePort != "" {
37 if n, err := strconv.Atoi(strings.TrimSpace(bridgePort)); err == nil && n > 0 {
38 return strconv.Itoa(n)
39 }
40 return bridgePort
41 }
42 return ""
43 }
44
45 func topologyCanonicalLinkName(srcName, srcPortName, dstName, dstPortName string) string {
46 srcName = strings.TrimSpace(srcName)
47 if srcName == "" {
48 srcName = "[unset]"
49 }
50 dstName = strings.TrimSpace(dstName)
51 if dstName == "" {
52 dstName = "[unset]"
53 }
54 srcPortName = strings.TrimSpace(srcPortName)
55 if srcPortName == "" {
56 srcPortName = "[unset]"
57 }
58 dstPortName = strings.TrimSpace(dstPortName)
59 if dstPortName == "" {
60 dstPortName = "[unset]"
61 }
62 return srcName + ":" + srcPortName + " -> " + dstName + ":" + dstPortName
63 }
64
65 func topologyAttrString(attrs map[string]any, key string) string {
66 if len(attrs) == 0 {
67 return ""
68 }
69 value, ok := attrs[key]
70 if !ok || value == nil {
71 return ""
72 }
73 str, ok := value.(string)
74 if !ok {
75 return ""
76 }
77 return strings.TrimSpace(str)
78 }
79
80 func topologyAttrInt(attrs map[string]any, key string) int {
81 if len(attrs) == 0 {
82 return 0
83 }
84 value, ok := attrs[key]
85 if !ok || value == nil {
86 return 0
87 }
88 switch typed := value.(type) {
89 case int:
90 return typed
91 case int64:
92 if typed < 0 {
93 return 0
94 }
95 if typed > math.MaxInt {
96 return math.MaxInt
97 }
98 return int(typed)
99 case float64:
100 if typed <= 0 {
101 return 0
102 }
103 if typed > math.MaxInt {
104 return math.MaxInt
105 }
106 return int(typed)
107 case string:
108 parsed, err := strconv.Atoi(strings.TrimSpace(typed))
109 if err != nil || parsed <= 0 {
110 return 0
111 }
112 return parsed
113 default:
114 return 0
115 }
116 }
117
118 func topologyAttrStringSlice(attrs map[string]any, key string) []string {
119 if len(attrs) == 0 {
120 return nil
121 }
122 value, ok := attrs[key]
123 if !ok || value == nil {
124 return nil
125 }
126 switch typed := value.(type) {
127 case []string:
128 return append([]string(nil), typed...)
129 case []any:
130 out := make([]string, 0, len(typed))
131 for _, item := range typed {
132 str, ok := item.(string)
133 if !ok {
134 continue
135 }
136 if str = strings.TrimSpace(str); str != "" {
137 out = append(out, str)
138 }
139 }
140 return out
141 default:
142 return nil
143 }
144 }
145
146 func topologyTimePtr(t time.Time) *time.Time {
147 if t.IsZero() {
148 return nil
149 }
150 out := t
151 return &out
152 }