@@ -3,11 +3,102 @@ package netlink
33import (
44 "errors"
55 "fmt"
6+ "syscall"
67
78 "github.com/vishvananda/netlink/nl"
89 "golang.org/x/sys/unix"
910)
1011
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+
11102// BridgeVlanList gets a map of device id to bridge vlan infos.
12103// Equivalent to: `bridge vlan show`
13104//
@@ -61,6 +152,38 @@ func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
61152 return ret , executeErr
62153}
63154
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+
64187// BridgeVlanAdd adds a new vlan filter entry
65188// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
66189func 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
70193// BridgeVlanAdd adds a new vlan filter entry
71194// Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
72195func (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 )
74197}
75198
76199// BridgeVlanAddRange adds a new vlan filter entry
@@ -82,7 +205,7 @@ func BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, mas
82205// BridgeVlanAddRange adds a new vlan filter entry
83206// Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
84207func (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 )
86209}
87210
88211// BridgeVlanDel adds a new vlan filter entry
@@ -94,7 +217,7 @@ func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) err
94217// BridgeVlanDel adds a new vlan filter entry
95218// Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
96219func (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 )
98221}
99222
100223// BridgeVlanDelRange adds a new vlan filter entry
@@ -106,10 +229,10 @@ func BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, mas
106229// BridgeVlanDelRange adds a new vlan filter entry
107230// Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
108231func (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 )
110233}
111234
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 {
113236 base := link .Attrs ()
114237 h .ensureIndex (base )
115238 req := h .newNetlinkRequest (cmd , unix .NLM_F_ACK )
@@ -129,25 +252,45 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, pvid,
129252 if flags > 0 {
130253 br .AddRtAttr (nl .IFLA_BRIDGE_FLAGS , nl .Uint16Attr (flags ))
131254 }
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- }
139255
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
143285
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 ())
146288
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+ }
151294 }
152295
153296 req .AddData (br )
0 commit comments