github.com/sagernet/netlink@v0.0.0-20240612041022-b9a21c07ac6a/bridge_linux.go (about)

     1  package netlink
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/sagernet/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, pvid, untagged, self, master)
    67  }
    68  
    69  // BridgeVlanDel adds a new vlan filter entry
    70  // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
    71  func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
    72  	return pkgHandle.BridgeVlanDel(link, vid, pvid, untagged, self, master)
    73  }
    74  
    75  // BridgeVlanDel adds a new vlan filter entry
    76  // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]`
    77  func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error {
    78  	return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, pvid, untagged, self, master)
    79  }
    80  
    81  func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error {
    82  	base := link.Attrs()
    83  	h.ensureIndex(base)
    84  	req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK)
    85  
    86  	msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
    87  	msg.Index = int32(base.Index)
    88  	req.AddData(msg)
    89  
    90  	br := nl.NewRtAttr(unix.IFLA_AF_SPEC, nil)
    91  	var flags uint16
    92  	if self {
    93  		flags |= nl.BRIDGE_FLAGS_SELF
    94  	}
    95  	if master {
    96  		flags |= nl.BRIDGE_FLAGS_MASTER
    97  	}
    98  	if flags > 0 {
    99  		br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags))
   100  	}
   101  	vlanInfo := &nl.BridgeVlanInfo{Vid: vid}
   102  	if pvid {
   103  		vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_PVID
   104  	}
   105  	if untagged {
   106  		vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
   107  	}
   108  	br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
   109  	req.AddData(br)
   110  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   111  	return err
   112  }