2017-06-06 09:09:16 +00:00
|
|
|
package netlink
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/vishvananda/netlink/nl"
|
2017-10-20 20:38:07 +00:00
|
|
|
"golang.org/x/sys/unix"
|
2017-06-06 09:09:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// BridgeVlanList gets a map of device id to bridge vlan infos.
|
|
|
|
// Equivalent to: `bridge vlan show`
|
|
|
|
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`
|
|
|
|
func (h *Handle) BridgeVlanList() (map[int32][]*nl.BridgeVlanInfo, error) {
|
2017-10-20 20:38:07 +00:00
|
|
|
req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
|
|
|
|
msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
|
2017-06-06 09:09:16 +00:00
|
|
|
req.AddData(msg)
|
2018-02-23 16:59:06 +00:00
|
|
|
req.AddData(nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(uint32(nl.RTEXT_FILTER_BRVLAN))))
|
2017-06-06 09:09:16 +00:00
|
|
|
|
2017-10-20 20:38:07 +00:00
|
|
|
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
|
2017-06-06 09:09:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
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 {
|
2018-02-23 16:59:06 +00:00
|
|
|
case unix.IFLA_AF_SPEC:
|
2017-06-06 09:09:16 +00:00
|
|
|
//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, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 {
|
2017-10-20 20:38:07 +00:00
|
|
|
return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, pvid, untagged, self, master)
|
2017-06-06 09:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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 {
|
2017-10-20 20:38:07 +00:00
|
|
|
return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, pvid, untagged, self, master)
|
2017-06-06 09:09:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error {
|
|
|
|
base := link.Attrs()
|
|
|
|
h.ensureIndex(base)
|
2017-10-20 20:38:07 +00:00
|
|
|
req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK)
|
2017-06-06 09:09:16 +00:00
|
|
|
|
2017-10-20 20:38:07 +00:00
|
|
|
msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
|
2017-06-06 09:09:16 +00:00
|
|
|
msg.Index = int32(base.Index)
|
|
|
|
req.AddData(msg)
|
|
|
|
|
2018-02-23 16:59:06 +00:00
|
|
|
br := nl.NewRtAttr(unix.IFLA_AF_SPEC, nil)
|
2017-06-06 09:09:16 +00:00
|
|
|
var flags uint16
|
|
|
|
if self {
|
|
|
|
flags |= nl.BRIDGE_FLAGS_SELF
|
|
|
|
}
|
|
|
|
if master {
|
|
|
|
flags |= nl.BRIDGE_FLAGS_MASTER
|
|
|
|
}
|
|
|
|
if flags > 0 {
|
2018-09-30 20:46:00 +00:00
|
|
|
br.AddRtAttr(nl.IFLA_BRIDGE_FLAGS, nl.Uint16Attr(flags))
|
2017-06-06 09:09:16 +00:00
|
|
|
}
|
|
|
|
vlanInfo := &nl.BridgeVlanInfo{Vid: vid}
|
|
|
|
if pvid {
|
|
|
|
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_PVID
|
|
|
|
}
|
|
|
|
if untagged {
|
|
|
|
vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED
|
|
|
|
}
|
2018-09-30 20:46:00 +00:00
|
|
|
br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize())
|
2017-06-06 09:09:16 +00:00
|
|
|
req.AddData(br)
|
2017-10-20 20:38:07 +00:00
|
|
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
2018-11-14 09:26:18 +00:00
|
|
|
return err
|
2017-06-06 09:09:16 +00:00
|
|
|
}
|