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 }