@@ -3,11 +3,102 @@ package netlink
3
3
import (
4
4
"errors"
5
5
"fmt"
6
+ "syscall"
6
7
7
8
"github.com/vishvananda/netlink/nl"
8
9
"golang.org/x/sys/unix"
9
10
)
10
11
12
+ // BridgeVlanTunnelShow gets vlanid-tunnelid mapping.
13
+ // Equivalent to: `bridge vlan tunnelshow`
14
+ //
15
+ // If the returned error is [ErrDumpInterrupted], results may be inconsistent
16
+ // or incomplete.
17
+ func BridgeVlanTunnelShow () ([]nl.TunnelInfo , error ) {
18
+ return pkgHandle .BridgeVlanTunnelShow ()
19
+ }
20
+
21
+ func (h * Handle ) BridgeVlanTunnelShow () ([]nl.TunnelInfo , error ) {
22
+ req := h .newNetlinkRequest (unix .RTM_GETLINK , unix .NLM_F_DUMP )
23
+ msg := nl .NewIfInfomsg (unix .AF_BRIDGE )
24
+ req .AddData (msg )
25
+ req .AddData (nl .NewRtAttr (unix .IFLA_EXT_MASK , nl .Uint32Attr (uint32 (nl .RTEXT_FILTER_BRVLAN ))))
26
+
27
+ msgs , executeErr := req .Execute (unix .NETLINK_ROUTE , unix .RTM_NEWLINK )
28
+ if executeErr != nil && ! errors .Is (executeErr , ErrDumpInterrupted ) {
29
+ return nil , executeErr
30
+ }
31
+ ret := make ([]nl.TunnelInfo , 0 )
32
+ for _ , m := range msgs {
33
+ msg := nl .DeserializeIfInfomsg (m )
34
+
35
+ attrs , err := nl .ParseRouteAttr (m [msg .Len ():])
36
+ if err != nil {
37
+ return nil , err
38
+ }
39
+ for _ , attr := range attrs {
40
+ switch attr .Attr .Type {
41
+ case unix .IFLA_AF_SPEC :
42
+ nestedAttrs , err := nl .ParseRouteAttr (attr .Value )
43
+ if err != nil {
44
+ return nil , fmt .Errorf ("failed to parse nested attr %v" , err )
45
+ }
46
+ for _ , nestAttr := range nestedAttrs {
47
+ switch nestAttr .Attr .Type {
48
+ case nl .IFLA_BRIDGE_VLAN_TUNNEL_INFO :
49
+ ret , err = parseTunnelInfo (& nestAttr , ret )
50
+ if err != nil {
51
+ return nil , fmt .Errorf ("failed to parse tunnelinfo %v" , err )
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ return ret , executeErr
59
+ }
60
+
61
+ func parseTunnelInfo (nestAttr * syscall.NetlinkRouteAttr , results []nl.TunnelInfo ) ([]nl.TunnelInfo , error ) {
62
+ tunnelInfos , err := nl .ParseRouteAttr (nestAttr .Value )
63
+ if err != nil {
64
+ return nil , fmt .Errorf ("failed to parse nested attr %v" , err )
65
+ }
66
+ var tunnelId uint32
67
+ var vid uint16
68
+ var flag uint16
69
+ for _ , tunnelInfo := range tunnelInfos {
70
+ switch tunnelInfo .Attr .Type {
71
+ case nl .IFLA_BRIDGE_VLAN_TUNNEL_ID :
72
+ tunnelId = native .Uint32 (tunnelInfo .Value )
73
+ case nl .IFLA_BRIDGE_VLAN_TUNNEL_VID :
74
+ vid = native .Uint16 (tunnelInfo .Value )
75
+ case nl .IFLA_BRIDGE_VLAN_TUNNEL_FLAGS :
76
+ flag = native .Uint16 (tunnelInfo .Value )
77
+ }
78
+ }
79
+
80
+ if flag == nl .BRIDGE_VLAN_INFO_RANGE_END {
81
+ lastTi := results [len (results )- 1 ]
82
+ vni := lastTi .TunId + 1
83
+ for i := lastTi .Vid + 1 ; i < vid ; i ++ {
84
+ t := nl.TunnelInfo {
85
+ TunId : vni ,
86
+ Vid : i ,
87
+ }
88
+ results = append (results , t )
89
+ vni ++
90
+ }
91
+ }
92
+
93
+ t := nl.TunnelInfo {
94
+ TunId : tunnelId ,
95
+ Vid : vid ,
96
+ }
97
+
98
+ results = append (results , t )
99
+ return results , nil
100
+ }
101
+
11
102
// BridgeVlanList gets a map of device id to bridge vlan infos.
12
103
// Equivalent to: `bridge vlan show`
13
104
//
@@ -61,6 +152,38 @@ func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
61
152
return ret , executeErr
62
153
}
63
154
155
+ // BridgeVlanAddTunnelInfo adds a new vlan filter entry
156
+ // Equivalent to: `bridge vlan add dev DEV vid VID tunnel_info id TUNID [ self ] [ master ]`
157
+ func BridgeVlanAddTunnelInfo (link Link , vid uint16 , tunid uint32 , self , master bool ) error {
158
+ return pkgHandle .BridgeVlanAddTunnelInfo (link , vid , 0 , tunid , 0 , self , master )
159
+ }
160
+
161
+ // BridgeVlanAddRangeTunnelInfoRange adds a new vlan filter entry
162
+ // Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND tunnel_info id VIN-VINEND [ self ] [ master ]`
163
+ func BridgeVlanAddRangeTunnelInfoRange (link Link , vid , vidEnd uint16 , tunid , tunidEnd uint32 , self , master bool ) error {
164
+ return pkgHandle .BridgeVlanAddTunnelInfo (link , vid , vidEnd , tunid , tunidEnd , self , master )
165
+ }
166
+
167
+ func (h * Handle ) BridgeVlanAddTunnelInfo (link Link , vid , vidEnd uint16 , tunid , tunidEnd uint32 , self , master bool ) error {
168
+ return h .bridgeVlanModify (unix .RTM_SETLINK , link , vid , vidEnd , tunid , tunidEnd , false , false , self , master )
169
+ }
170
+
171
+ // BridgeVlanDelTunnelInfo adds a new vlan filter entry
172
+ // Equivalent to: `bridge vlan del dev DEV vid VID tunnel_info id TUNID [ self ] [ master ]`
173
+ func BridgeVlanDelTunnelInfo (link Link , vid uint16 , tunid uint32 , self , master bool ) error {
174
+ return pkgHandle .BridgeVlanDelTunnelInfo (link , vid , 0 , tunid , 0 , self , master )
175
+ }
176
+
177
+ // BridgeVlanDelRangeTunnelInfoRange adds a new vlan filter entry
178
+ // Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND tunnel_info id VIN-VINEND [ self ] [ master ]`
179
+ func BridgeVlanDelRangeTunnelInfoRange (link Link , vid , vidEnd uint16 , tunid , tunidEnd uint32 , self , master bool ) error {
180
+ return pkgHandle .BridgeVlanDelTunnelInfo (link , vid , vidEnd , tunid , tunidEnd , self , master )
181
+ }
182
+
183
+ func (h * Handle ) BridgeVlanDelTunnelInfo (link Link , vid , vidEnd uint16 , tunid , tunidEnd uint32 , self , master bool ) error {
184
+ return h .bridgeVlanModify (unix .RTM_DELLINK , link , vid , vidEnd , tunid , tunidEnd , false , false , self , master )
185
+ }
186
+
64
187
// BridgeVlanAdd adds a new vlan filter entry
65
188
// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
66
189
func BridgeVlanAdd (link Link , vid uint16 , pvid , untagged , self , master bool ) error {
@@ -70,7 +193,7 @@ func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) err
70
193
// BridgeVlanAdd adds a new vlan filter entry
71
194
// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
72
195
func (h * Handle ) BridgeVlanAdd (link Link , vid uint16 , pvid , untagged , self , master bool ) error {
73
- return h .bridgeVlanModify (unix .RTM_SETLINK , link , vid , 0 , pvid , untagged , self , master )
196
+ return h .bridgeVlanModify (unix .RTM_SETLINK , link , vid , 0 , 0 , 0 , pvid , untagged , self , master )
74
197
}
75
198
76
199
// BridgeVlanAddRange adds a new vlan filter entry
@@ -82,7 +205,7 @@ func BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, mas
82
205
// BridgeVlanAddRange adds a new vlan filter entry
83
206
// Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
84
207
func (h * Handle ) BridgeVlanAddRange (link Link , vid , vidEnd uint16 , pvid , untagged , self , master bool ) error {
85
- return h .bridgeVlanModify (unix .RTM_SETLINK , link , vid , vidEnd , pvid , untagged , self , master )
208
+ return h .bridgeVlanModify (unix .RTM_SETLINK , link , vid , vidEnd , 0 , 0 , pvid , untagged , self , master )
86
209
}
87
210
88
211
// BridgeVlanDel adds a new vlan filter entry
@@ -94,7 +217,7 @@ func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) err
94
217
// BridgeVlanDel adds a new vlan filter entry
95
218
// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
96
219
func (h * Handle ) BridgeVlanDel (link Link , vid uint16 , pvid , untagged , self , master bool ) error {
97
- return h .bridgeVlanModify (unix .RTM_DELLINK , link , vid , 0 , pvid , untagged , self , master )
220
+ return h .bridgeVlanModify (unix .RTM_DELLINK , link , vid , 0 , 0 , 0 , pvid , untagged , self , master )
98
221
}
99
222
100
223
// BridgeVlanDelRange adds a new vlan filter entry
@@ -106,10 +229,10 @@ func BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, mas
106
229
// BridgeVlanDelRange adds a new vlan filter entry
107
230
// Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
108
231
func (h * Handle ) BridgeVlanDelRange (link Link , vid , vidEnd uint16 , pvid , untagged , self , master bool ) error {
109
- return h .bridgeVlanModify (unix .RTM_DELLINK , link , vid , vidEnd , pvid , untagged , self , master )
232
+ return h .bridgeVlanModify (unix .RTM_DELLINK , link , vid , vidEnd , 0 , 0 , pvid , untagged , self , master )
110
233
}
111
234
112
- func (h * Handle ) bridgeVlanModify (cmd int , link Link , vid , vidEnd uint16 , pvid , untagged , self , master bool ) error {
235
+ func (h * Handle ) bridgeVlanModify (cmd int , link Link , vid , vidEnd uint16 , tunid , tunidEnd uint32 , pvid , untagged , self , master bool ) error {
113
236
base := link .Attrs ()
114
237
h .ensureIndex (base )
115
238
req := h .newNetlinkRequest (cmd , unix .NLM_F_ACK )
@@ -129,25 +252,45 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, pvid,
129
252
if flags > 0 {
130
253
br .AddRtAttr (nl .IFLA_BRIDGE_FLAGS , nl .Uint16Attr (flags ))
131
254
}
132
- vlanInfo := & nl.BridgeVlanInfo {Vid : vid }
133
- if pvid {
134
- vlanInfo .Flags |= nl .BRIDGE_VLAN_INFO_PVID
135
- }
136
- if untagged {
137
- vlanInfo .Flags |= nl .BRIDGE_VLAN_INFO_UNTAGGED
138
- }
139
255
140
- if vidEnd != 0 {
141
- vlanEndInfo := & nl.BridgeVlanInfo {Vid : vidEnd }
142
- vlanEndInfo .Flags = vlanInfo .Flags
256
+ if tunid != 0 {
257
+ if tunidEnd != 0 {
258
+ tiStart := br .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_INFO , nil )
259
+ tiStart .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_ID , nl .Uint32Attr (tunid ))
260
+ tiStart .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_VID , nl .Uint16Attr (vid ))
261
+ tiStart .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_FLAGS , nl .Uint16Attr (nl .BRIDGE_VLAN_INFO_RANGE_BEGIN ))
262
+
263
+ tiEnd := br .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_INFO , nil )
264
+ tiEnd .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_ID , nl .Uint32Attr (tunidEnd ))
265
+ tiEnd .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_VID , nl .Uint16Attr (vidEnd ))
266
+ tiEnd .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_FLAGS , nl .Uint16Attr (nl .BRIDGE_VLAN_INFO_RANGE_END ))
267
+ } else {
268
+ ti := br .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_INFO , nil )
269
+ ti .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_ID , nl .Uint32Attr (tunid ))
270
+ ti .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_VID , nl .Uint16Attr (vid ))
271
+ ti .AddRtAttr (nl .IFLA_BRIDGE_VLAN_TUNNEL_FLAGS , nl .Uint16Attr (0 ))
272
+ }
273
+ } else {
274
+ vlanInfo := & nl.BridgeVlanInfo {Vid : vid }
275
+ if pvid {
276
+ vlanInfo .Flags |= nl .BRIDGE_VLAN_INFO_PVID
277
+ }
278
+ if untagged {
279
+ vlanInfo .Flags |= nl .BRIDGE_VLAN_INFO_UNTAGGED
280
+ }
281
+
282
+ if vidEnd != 0 {
283
+ vlanEndInfo := & nl.BridgeVlanInfo {Vid : vidEnd }
284
+ vlanEndInfo .Flags = vlanInfo .Flags
143
285
144
- vlanInfo .Flags |= nl .BRIDGE_VLAN_INFO_RANGE_BEGIN
145
- br .AddRtAttr (nl .IFLA_BRIDGE_VLAN_INFO , vlanInfo .Serialize ())
286
+ vlanInfo .Flags |= nl .BRIDGE_VLAN_INFO_RANGE_BEGIN
287
+ br .AddRtAttr (nl .IFLA_BRIDGE_VLAN_INFO , vlanInfo .Serialize ())
146
288
147
- vlanEndInfo .Flags |= nl .BRIDGE_VLAN_INFO_RANGE_END
148
- br .AddRtAttr (nl .IFLA_BRIDGE_VLAN_INFO , vlanEndInfo .Serialize ())
149
- } else {
150
- br .AddRtAttr (nl .IFLA_BRIDGE_VLAN_INFO , vlanInfo .Serialize ())
289
+ vlanEndInfo .Flags |= nl .BRIDGE_VLAN_INFO_RANGE_END
290
+ br .AddRtAttr (nl .IFLA_BRIDGE_VLAN_INFO , vlanEndInfo .Serialize ())
291
+ } else {
292
+ br .AddRtAttr (nl .IFLA_BRIDGE_VLAN_INFO , vlanInfo .Serialize ())
293
+ }
151
294
}
152
295
153
296
req .AddData (br )
0 commit comments