Add support to manage the vlan protocol on a vf

This allows users to get and set the vlan protocol on a vf
Signed-off-by: Marcelo Guerrero <marguerr@redhat.com>
This commit is contained in:
Marcelo Guerrero 2023-07-07 18:04:35 +02:00 committed by Alessandro Boch
parent 6afddb37c1
commit 63484bbf69
5 changed files with 114 additions and 4 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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 {
@ -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 {
@ -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)
@ -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) {

View File

@ -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
}

View File

@ -3,6 +3,7 @@ package nl
import (
"bytes"
"encoding/binary"
"fmt"
"unsafe"
)
@ -274,9 +275,17 @@ 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_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 (
IFLA_VF_LINK_STATE_AUTO = iota /* link state of the uplink */
IFLA_VF_LINK_STATE_ENABLE /* link always up */
@ -299,6 +308,7 @@ const (
const (
SizeofVfMac = 0x24
SizeofVfVlan = 0x0c
SizeofVfVlanInfo = 0x0e
SizeofVfTxRate = 0x08
SizeofVfRate = 0x0c
SizeofVfSpoofchk = 0x08
@ -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 */