| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- package netlink
- import (
- "errors"
- "fmt"
- "syscall"
- "github.com/vishvananda/netlink/nl"
- "golang.org/x/sys/unix"
- )
- // BridgeVlanTunnelShow gets vlanid-tunnelid mapping.
- // Equivalent to: `bridge vlan tunnelshow`
- //
- // If the returned error is [ErrDumpInterrupted], results may be inconsistent
- // or incomplete.
- func BridgeVlanTunnelShow() ([]nl.TunnelInfo, error) {
- return pkgHandle.BridgeVlanTunnelShow()
- }
- func (h *Handle) BridgeVlanTunnelShow() ([]nl.TunnelInfo, error) {
- req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
- msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
- req.AddData(msg)
- req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN))))
- msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
- if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
- return nil, executeErr
- }
- ret := make([]nl.TunnelInfo, 0)
- for _, m := range msgs {
- msg := nl.DeserializeIfInfomsg(m)
- attrs, err := nl.ParseRouteAttr(m[msg.Len():])
- if err != nil {
- return nil, err
- }
- for _, attr := range attrs {
- switch attr.Attr.Type {
- case unix.IFLA_AF_SPEC:
- nestedAttrs, err := nl.ParseRouteAttr(attr.Value)
- if err != nil {
- return nil, fmt.Errorf("failed to parse nested attr %v", err)
- }
- for _, nestAttr := range nestedAttrs {
- switch nestAttr.Attr.Type {
- case nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO:
- ret, err = parseTunnelInfo(&nestAttr, ret)
- if err != nil {
- return nil, fmt.Errorf("failed to parse tunnelinfo %v", err)
- }
- }
- }
- }
- }
- }
- return ret, executeErr
- }
- func parseTunnelInfo(nestAttr *syscall.NetlinkRouteAttr, results []nl.TunnelInfo) ([]nl.TunnelInfo, error) {
- tunnelInfos, err := nl.ParseRouteAttr(nestAttr.Value)
- if err != nil {
- return nil, fmt.Errorf("failed to parse nested attr %v", err)
- }
- var tunnelId uint32
- var vid uint16
- var flag uint16
- for _, tunnelInfo := range tunnelInfos {
- switch tunnelInfo.Attr.Type {
- case nl.IFLA_BRIDGE_VLAN_TUNNEL_ID:
- tunnelId = native.Uint32(tunnelInfo.Value)
- case nl.IFLA_BRIDGE_VLAN_TUNNEL_VID:
- vid = native.Uint16(tunnelInfo.Value)
- case nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS:
- flag = native.Uint16(tunnelInfo.Value)
- }
- }
- if flag == nl.BRIDGE_VLAN_INFO_RANGE_END {
- lastTi := results[len(results)-1]
- vni := lastTi.TunId + 1
- for i := lastTi.Vid + 1; i < vid; i++ {
- t := nl.TunnelInfo{
- TunId: vni,
- Vid: i,
- }
- results = append(results, t)
- vni++
- }
- }
- t := nl.TunnelInfo{
- TunId: tunnelId,
- Vid: vid,
- }
- results = append(results, t)
- return results, nil
- }
- // BridgeVlanList gets a map of device id to bridge vlan infos.
- // Equivalent to: `bridge vlan show`
- //
- // If the returned error is [ErrDumpInterrupted], results may be inconsistent
- // or incomplete.
- func BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
- return pkgHandle.BridgeVlanList()
- }
- // BridgeVlanList gets a map of device id to bridge vlan infos.
- // Equivalent to: `bridge vlan show`
- //
- // If the returned error is [ErrDumpInterrupted], results may be inconsistent
- // or incomplete.
- func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
- req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
- msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
- req.AddData(msg)
- req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN))))
- msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
- if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
- return nil, executeErr
- }
- ret := make(map[int32][]*nl.BridgeVlanInfo)
- for _, m := range msgs {
- msg := nl.DeserializeIfInfomsg(m)
- attrs, err := nl.ParseRouteAttr(m[msg.Len():])
- if err != nil {
- return nil, err
- }
- for _, attr := range attrs {
- switch attr.Attr.Type {
- case unix.IFLA_AF_SPEC:
- //nested attr
- nestAttrs, err := nl.ParseRouteAttr(attr.Value)
- if err != nil {
- return nil, fmt.Errorf("failed to parse nested attr %v", err)
- }
- for _, nestAttr := range nestAttrs {
- switch nestAttr.Attr.Type {
- case nl.IFLA_BRIDGE_VLAN_INFO:
- vlanInfo := nl.DeserializeBridgeVlanInfo(nestAttr.Value)
- ret[msg.Index] = append(ret[msg.Index], vlanInfo)
- }
- }
- }
- }
- }
- return ret, executeErr
- }
- // BridgeVlanAddTunnelInfo adds a new vlan filter entry
- // Equivalent to: `bridge vlan add dev DEV vid VID tunnel_info id TUNID [ self ] [ master ]`
- func BridgeVlanAddTunnelInfo(link Link, vid uint16, tunid uint32, self, master bool) error {
- return pkgHandle.BridgeVlanAddTunnelInfo(link, vid, 0, tunid, 0, self, master)
- }
- // BridgeVlanAddRangeTunnelInfoRange adds a new vlan filter entry
- // Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND tunnel_info id VIN-VINEND [ self ] [ master ]`
- func BridgeVlanAddRangeTunnelInfoRange(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error {
- return pkgHandle.BridgeVlanAddTunnelInfo(link, vid, vidEnd, tunid, tunidEnd, self, master)
- }
- func (h *Handle) BridgeVlanAddTunnelInfo(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error {
- return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, vidEnd, tunid, tunidEnd, false, false, self, master)
- }
- // BridgeVlanDelTunnelInfo adds a new vlan filter entry
- // Equivalent to: `bridge vlan del dev DEV vid VID tunnel_info id TUNID [ self ] [ master ]`
- func BridgeVlanDelTunnelInfo(link Link, vid uint16, tunid uint32, self, master bool) error {
- return pkgHandle.BridgeVlanDelTunnelInfo(link, vid, 0, tunid, 0, self, master)
- }
- // BridgeVlanDelRangeTunnelInfoRange adds a new vlan filter entry
- // Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND tunnel_info id VIN-VINEND [ self ] [ master ]`
- func BridgeVlanDelRangeTunnelInfoRange(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error {
- return pkgHandle.BridgeVlanDelTunnelInfo(link, vid, vidEnd, tunid, tunidEnd, self, master)
- }
- func (h *Handle) BridgeVlanDelTunnelInfo(link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, self, master bool) error {
- return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, vidEnd, tunid, tunidEnd, false, false, self, master)
- }
- // BridgeVlanAdd adds a new vlan filter entry
- // Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
- func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
- return pkgHandle.BridgeVlanAdd(link, vid, pvid, untagged, self, master)
- }
- // BridgeVlanAdd adds a new vlan filter entry
- // Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
- func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
- return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, 0, 0, 0, pvid, untagged, self, master)
- }
- // BridgeVlanAddRange adds a new vlan filter entry
- // Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
- func BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
- return pkgHandle.BridgeVlanAddRange(link, vid, vidEnd, pvid, untagged, self, master)
- }
- // BridgeVlanAddRange adds a new vlan filter entry
- // Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
- func (h *Handle) BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
- return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, vidEnd, 0, 0, pvid, untagged, self, master)
- }
- // BridgeVlanDel adds a new vlan filter entry
- // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
- func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
- return pkgHandle.BridgeVlanDel(link, vid, pvid, untagged, self, master)
- }
- // BridgeVlanDel adds a new vlan filter entry
- // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
- func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
- return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, 0, 0, 0, pvid, untagged, self, master)
- }
- // BridgeVlanDelRange adds a new vlan filter entry
- // Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
- func BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
- return pkgHandle.BridgeVlanDelRange(link, vid, vidEnd, pvid, untagged, self, master)
- }
- // BridgeVlanDelRange adds a new vlan filter entry
- // Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
- func (h *Handle) BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
- return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, vidEnd, 0, 0, pvid, untagged, self, master)
- }
- func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, tunid, tunidEnd uint32, pvid, untagged, self, master bool) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- br := nl.NewRtAttr(unix.IFLA_AF_SPEC, nil)
- var flags uint16
- if self {
- flags |= nl.BRIDGE_FLAGS_SELF
- }
- if master {
- flags |= nl.BRIDGE_FLAGS_MASTER
- }
- if flags > 0 {
- br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags))
- }
- if tunid != 0 {
- if tunidEnd != 0 {
- tiStart := br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO, nil)
- tiStart.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_ID, nl.Uint32Attr(tunid))
- tiStart.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_VID, nl.Uint16Attr(vid))
- tiStart.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, nl.Uint16Attr(nl.BRIDGE_VLAN_INFO_RANGE_BEGIN))
- tiEnd := br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO, nil)
- tiEnd.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_ID, nl.Uint32Attr(tunidEnd))
- tiEnd.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_VID, nl.Uint16Attr(vidEnd))
- tiEnd.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, nl.Uint16Attr(nl.BRIDGE_VLAN_INFO_RANGE_END))
- } else {
- ti := br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_INFO, nil)
- ti.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_ID, nl.Uint32Attr(tunid))
- ti.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_VID, nl.Uint16Attr(vid))
- ti.AddRtAttr(nl.IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, nl.Uint16Attr(0))
- }
- } else {
- vlanInfo := &nl.BridgeVlanInfo{Vid: vid}
- if pvid {
- vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_PVID
- }
- if untagged {
- vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
- }
- if vidEnd != 0 {
- vlanEndInfo := &nl.BridgeVlanInfo{Vid: vidEnd}
- vlanEndInfo.Flags = vlanInfo.Flags
- vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_BEGIN
- br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
- vlanEndInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_END
- br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanEndInfo.Serialize())
- } else {
- br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
- }
- }
- req.AddData(br)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
|