Skip to content

Commit

Permalink
Add support to manage the vlan protocol on a vf
Browse files Browse the repository at this point in the history
This allows users to get and set the vlan protocol on a vf
Signed-off-by: Marcelo Guerrero <[email protected]>
  • Loading branch information
mlguerrero12 authored and aboch committed Sep 5, 2023
1 parent 6afddb3 commit 63484bb
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 4 deletions.
4 changes: 4 additions & 0 deletions handle_unspecified.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
return ErrNotImplemented
}

func (h *Handle) LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
return ErrNotImplemented
}

func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
return ErrNotImplemented
}
Expand Down
1 change: 1 addition & 0 deletions link.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ type VfInfo struct {
Mac net.HardwareAddr
Vlan int
Qos int
VlanProto int
TxRate int // IFLA_VF_TX_RATE Max TxRate
Spoofchk bool
LinkState uint32
Expand Down
54 changes: 51 additions & 3 deletions link_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,43 @@ func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
return err
}

// LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link.
// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto`
func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
return pkgHandle.LinkSetVfVlanQosProto(link, vf, vlan, qos, proto)
}

// LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link.
// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto`
func (h *Handle) LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
base := link.Attrs()
h.ensureIndex(base)
req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)

msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Index = int32(base.Index)
req.AddData(msg)

data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
vfInfo := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
vfVlanList := vfInfo.AddRtAttr(nl.IFLA_VF_VLAN_LIST, nil)

vfmsg := nl.VfVlanInfo{
VfVlan: nl.VfVlan{
Vf: uint32(vf),
Vlan: uint32(vlan),
Qos: uint32(qos),
},
VlanProto: (uint16(proto)>>8)&0xFF | (uint16(proto)&0xFF)<<8,
}

vfVlanList.AddRtAttr(nl.IFLA_VF_VLAN_INFO, vfmsg.Serialize())
req.AddData(data)

_, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err
}

// LinkSetVfTxRate sets the tx rate of a vf for the link.
// Equivalent to: `ip link set $link vf $vf rate $rate`
func LinkSetVfTxRate(link Link, vf, rate int) error {
Expand Down Expand Up @@ -3371,12 +3408,17 @@ func parseVfInfoList(data []syscall.NetlinkRouteAttr) ([]VfInfo, error) {
if err != nil {
return nil, err
}
vfs = append(vfs, parseVfInfo(vfAttrs, i))

vf, err := parseVfInfo(vfAttrs, i)
if err != nil {
return nil, err
}
vfs = append(vfs, vf)
}
return vfs, nil
}

func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) (VfInfo, error) {
vf := VfInfo{ID: id}
for _, element := range data {
switch element.Attr.Type {
Expand All @@ -3387,6 +3429,12 @@ func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
vl := nl.DeserializeVfVlan(element.Value[:])
vf.Vlan = int(vl.Vlan)
vf.Qos = int(vl.Qos)
case nl.IFLA_VF_VLAN_LIST:
vfVlanInfoList, err := nl.DeserializeVfVlanList(element.Value[:])
if err != nil {
return vf, err
}
vf.VlanProto = int(vfVlanInfoList[0].VlanProto)
case nl.IFLA_VF_TX_RATE:
txr := nl.DeserializeVfTxRate(element.Value[:])
vf.TxRate = int(txr.Rate)
Expand Down Expand Up @@ -3420,7 +3468,7 @@ func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
vf.Trust = result.Setting
}
}
return vf
return vf, nil
}

func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) {
Expand Down
4 changes: 4 additions & 0 deletions netlink_unspecified.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
return ErrNotImplemented
}

func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error {
return ErrNotImplemented
}

func LinkSetVfTxRate(link Link, vf, rate int) error {
return ErrNotImplemented
}
Expand Down
55 changes: 54 additions & 1 deletion nl/link_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package nl
import (
"bytes"
"encoding/binary"
"fmt"
"unsafe"
)

Expand Down Expand Up @@ -274,7 +275,15 @@ const (
IFLA_VF_TRUST /* Trust state of VF */
IFLA_VF_IB_NODE_GUID /* VF Infiniband node GUID */
IFLA_VF_IB_PORT_GUID /* VF Infiniband port GUID */
IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID
IFLA_VF_VLAN_LIST /* nested list of vlans, option for QinQ */

IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID
)

const (
IFLA_VF_VLAN_INFO_UNSPEC = iota
IFLA_VF_VLAN_INFO /* VLAN ID, QoS and VLAN protocol */
__IFLA_VF_VLAN_INFO_MAX
)

const (
Expand All @@ -299,6 +308,7 @@ const (
const (
SizeofVfMac = 0x24
SizeofVfVlan = 0x0c
SizeofVfVlanInfo = 0x0e
SizeofVfTxRate = 0x08
SizeofVfRate = 0x0c
SizeofVfSpoofchk = 0x08
Expand Down Expand Up @@ -354,6 +364,49 @@ func (msg *VfVlan) Serialize() []byte {
return (*(*[SizeofVfVlan]byte)(unsafe.Pointer(msg)))[:]
}

func DeserializeVfVlanList(b []byte) ([]*VfVlanInfo, error) {
var vfVlanInfoList []*VfVlanInfo
attrs, err := ParseRouteAttr(b)
if err != nil {
return nil, err
}

for _, element := range attrs {
if element.Attr.Type == IFLA_VF_VLAN_INFO {
vfVlanInfoList = append(vfVlanInfoList, DeserializeVfVlanInfo(element.Value))
}
}

if len(vfVlanInfoList) == 0 {
return nil, fmt.Errorf("VF vlan list is defined but no vf vlan info elements were found")
}

return vfVlanInfoList, nil
}

// struct ifla_vf_vlan_info {
// __u32 vf;
// __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
// __u32 qos;
// __be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */
// };

type VfVlanInfo struct {
VfVlan
VlanProto uint16
}

func DeserializeVfVlanInfo(b []byte) *VfVlanInfo {
return &VfVlanInfo{
*(*VfVlan)(unsafe.Pointer(&b[0:SizeofVfVlan][0])),
binary.BigEndian.Uint16(b[SizeofVfVlan:SizeofVfVlanInfo]),
}
}

func (msg *VfVlanInfo) Serialize() []byte {
return (*(*[SizeofVfVlanInfo]byte)(unsafe.Pointer(msg)))[:]
}

// struct ifla_vf_tx_rate {
// __u32 vf;
// __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */
Expand Down

0 comments on commit 63484bb

Please sign in to comment.