bridge_linux.go 11 KB

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