github.com/vishvananda/netlink@v1.3.0/bridge_linux.go (about)

     1  package netlink
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/vishvananda/netlink/nl"
     7  	"golang.org/x/sys/unix"
     8  )
     9  
    10  // BridgeVlanList gets a map of device id to bridge vlan infos.
    11  // Equivalent to: `bridge vlan show`
    12  func BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
    13  	return pkgHandle.BridgeVlanList()
    14  }
    15  
    16  // BridgeVlanList gets a map of device id to bridge vlan infos.
    17  // Equivalent to: `bridge vlan show`
    18  func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
    19  	req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
    20  	msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
    21  	req.AddData(msg)
    22  	req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN))))
    23  
    24  	msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  	ret := make(map[int32][]*nl.BridgeVlanInfo)
    29  	for _, m := range msgs {
    30  		msg := nl.DeserializeIfInfomsg(m)
    31  
    32  		attrs, err := nl.ParseRouteAttr(m[msg.Len():])
    33  		if err != nil {
    34  			return nil, err
    35  		}
    36  		for _, attr := range attrs {
    37  			switch attr.Attr.Type {
    38  			case unix.IFLA_AF_SPEC:
    39  				//nested attr
    40  				nestAttrs, err := nl.ParseRouteAttr(attr.Value)
    41  				if err != nil {
    42  					return nil, fmt.Errorf("failed to parse nested attr %v", err)
    43  				}
    44  				for _, nestAttr := range nestAttrs {
    45  					switch nestAttr.Attr.Type {
    46  					case nl.IFLA_BRIDGE_VLAN_INFO:
    47  						vlanInfo := nl.DeserializeBridgeVlanInfo(nestAttr.Value)
    48  						ret[msg.Index] = append(ret[msg.Index], vlanInfo)
    49  					}
    50  				}
    51  			}
    52  		}
    53  	}
    54  	return ret, nil
    55  }
    56  
    57  // BridgeVlanAdd adds a new vlan filter entry
    58  // Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
    59  func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
    60  	return pkgHandle.BridgeVlanAdd(link, vid, pvid, untagged, self, master)
    61  }
    62  
    63  // BridgeVlanAdd adds a new vlan filter entry
    64  // Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
    65  func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error {
    66  	return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, 0, pvid, untagged, self, master)
    67  }
    68  
    69  // BridgeVlanAddRange adds a new vlan filter entry
    70  // Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
    71  func BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
    72  	return pkgHandle.BridgeVlanAddRange(link, vid, vidEnd, pvid, untagged, self, master)
    73  }
    74  
    75  // BridgeVlanAddRange adds a new vlan filter entry
    76  // Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
    77  func (h *Handle) BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
    78  	return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, vidEnd, pvid, untagged, self, master)
    79  }
    80  
    81  // BridgeVlanDel adds a new vlan filter entry
    82  // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
    83  func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
    84  	return pkgHandle.BridgeVlanDel(link, vid, pvid, untagged, self, master)
    85  }
    86  
    87  // BridgeVlanDel adds a new vlan filter entry
    88  // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
    89  func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
    90  	return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, 0, pvid, untagged, self, master)
    91  }
    92  
    93  // BridgeVlanDelRange adds a new vlan filter entry
    94  // Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
    95  func BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
    96  	return pkgHandle.BridgeVlanDelRange(link, vid, vidEnd, pvid, untagged, self, master)
    97  }
    98  
    99  // BridgeVlanDelRange adds a new vlan filter entry
   100  // Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]`
   101  func (h *Handle) BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
   102  	return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, vidEnd, pvid, untagged, self, master)
   103  }
   104  
   105  func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error {
   106  	base := link.Attrs()
   107  	h.ensureIndex(base)
   108  	req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK)
   109  
   110  	msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
   111  	msg.Index = int32(base.Index)
   112  	req.AddData(msg)
   113  
   114  	br := nl.NewRtAttr(unix.IFLA_AF_SPEC, nil)
   115  	var flags uint16
   116  	if self {
   117  		flags |= nl.BRIDGE_FLAGS_SELF
   118  	}
   119  	if master {
   120  		flags |= nl.BRIDGE_FLAGS_MASTER
   121  	}
   122  	if flags > 0 {
   123  		br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags))
   124  	}
   125  	vlanInfo := &nl.BridgeVlanInfo{Vid: vid}
   126  	if pvid {
   127  		vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_PVID
   128  	}
   129  	if untagged {
   130  		vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
   131  	}
   132  
   133  	if vidEnd != 0 {
   134  		vlanEndInfo := &nl.BridgeVlanInfo{Vid: vidEnd}
   135  		vlanEndInfo.Flags = vlanInfo.Flags
   136  
   137  		vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_BEGIN
   138  		br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
   139  
   140  		vlanEndInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_END
   141  		br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanEndInfo.Serialize())
   142  	} else { 
   143  		br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
   144  	}
   145  
   146  	req.AddData(br)
   147  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   148  	return err
   149  }