Add bond slave information

This PR refers to PR@lebauce and add some changes.
- Added some tests to retrieve bond slave information.
- Link.BondSlave is changed to LinkSlave interface.
- BondSlaveState.String() returns UPPER case. (same as iproute2)
- BondSlaveMiiStatus.String() returns UPPER case. (same as iproute2)
This commit is contained in:
Takushi Fujiwara 2019-09-16 12:08:06 +00:00 committed by Alessandro Boch
parent e906d22624
commit 205a160d2e
4 changed files with 234 additions and 5 deletions

68
link.go
View File

@ -4,6 +4,7 @@ import (
"fmt"
"net"
"os"
"strconv"
)
// Link represents a link device from netlink. Shared link attributes
@ -45,6 +46,12 @@ type LinkAttrs struct {
GSOMaxSegs uint32
Vfs []VfInfo // virtual functions available on link
Group uint32
Slave LinkSlave
}
// LinkSlave represents a slave device.
type LinkSlave interface {
SlaveType() string
}
// VfInfo represents configuration of virtual function
@ -749,6 +756,67 @@ func (bond *Bond) Type() string {
return "bond"
}
// BondSlaveState represents the values of the IFLA_BOND_SLAVE_STATE bond slave
// attribute, which contains the state of the bond slave.
type BondSlaveState uint8
const (
BondStateActive = iota // Link is active.
BondStateBackup // Link is backup.
)
func (s BondSlaveState) String() string {
switch s {
case BondStateActive:
return "ACTIVE"
case BondStateBackup:
return "BACKUP"
default:
return strconv.Itoa(int(s))
}
}
// BondSlaveState represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave
// attribute, which contains the status of MII link monitoring
type BondSlaveMiiStatus uint8
const (
BondLinkUp = iota // link is up and running.
BondLinkFail // link has just gone down.
BondLinkDown // link has been down for too long time.
BondLinkBack // link is going back.
)
func (s BondSlaveMiiStatus) String() string {
switch s {
case BondLinkUp:
return "UP"
case BondLinkFail:
return "GOING_DOWN"
case BondLinkDown:
return "DOWN"
case BondLinkBack:
return "GOING_BACK"
default:
return strconv.Itoa(int(s))
}
}
type BondSlave struct {
State BondSlaveState
MiiStatus BondSlaveMiiStatus
LinkFailureCount uint32
PermHardwareAddr net.HardwareAddr
QueueId uint16
AggregatorId uint16
AdActorOperPortState uint8
AdPartnerOperPortState uint16
}
func (b *BondSlave) SlaveType() string {
return "bond"
}
// Gretap devices must specify LocalIP and RemoteIP on create
type Gretap struct {
LinkAttrs

View File

@ -1476,10 +1476,12 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
base.Promisc = 1
}
var (
link Link
stats32 []byte
stats64 []byte
linkType string
link Link
stats32 []byte
stats64 []byte
linkType string
linkSlave LinkSlave
slaveType string
)
for _, attr := range attrs {
switch attr.Attr.Type {
@ -1585,6 +1587,21 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
case "ipoib":
parseIPoIBData(link, data)
}
case nl.IFLA_INFO_SLAVE_KIND:
slaveType = string(info.Value[:len(info.Value)-1])
switch slaveType {
case "bond":
linkSlave = &BondSlave{}
}
case nl.IFLA_INFO_SLAVE_DATA:
switch slaveType {
case "bond":
data, err := nl.ParseRouteAttr(info.Value)
if err != nil {
return nil, err
}
parseBondSlaveData(linkSlave, data)
}
}
}
case unix.IFLA_ADDRESS:
@ -1667,6 +1684,7 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Device{}
}
*link.Attrs() = base
link.Attrs().Slave = linkSlave
// If the tuntap attributes are not updated by netlink due to
// an older driver, use sysfs
@ -2131,6 +2149,46 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
func addBondSlaveAttrs(bondSlave *BondSlave, linkInfo *nl.RtAttr) {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil)
data.AddRtAttr(nl.IFLA_BOND_SLAVE_STATE, nl.Uint8Attr(uint8(bondSlave.State)))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_MII_STATUS, nl.Uint8Attr(uint8(bondSlave.MiiStatus)))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, nl.Uint32Attr(bondSlave.LinkFailureCount))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(bondSlave.QueueId))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, nl.Uint16Attr(bondSlave.AggregatorId))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, nl.Uint8Attr(bondSlave.AdActorOperPortState))
data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, nl.Uint16Attr(bondSlave.AdPartnerOperPortState))
if mac := bondSlave.PermHardwareAddr; mac != nil {
data.AddRtAttr(nl.IFLA_BOND_SLAVE_PERM_HWADDR, []byte(mac))
}
}
func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
bondSlave := slave.(*BondSlave)
for i := range data {
switch data[i].Attr.Type {
case nl.IFLA_BOND_SLAVE_STATE:
bondSlave.State = BondSlaveState(data[i].Value[0])
case nl.IFLA_BOND_SLAVE_MII_STATUS:
bondSlave.MiiStatus = BondSlaveMiiStatus(data[i].Value[0])
case nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT:
bondSlave.LinkFailureCount = native.Uint32(data[i].Value[0:4])
case nl.IFLA_BOND_SLAVE_PERM_HWADDR:
bondSlave.PermHardwareAddr = net.HardwareAddr(data[i].Value[0:6])
case nl.IFLA_BOND_SLAVE_QUEUE_ID:
bondSlave.QueueId = native.Uint16(data[i].Value[0:2])
case nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID:
bondSlave.AggregatorId = native.Uint16(data[i].Value[0:2])
case nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE:
bondSlave.AdActorOperPortState = uint8(data[i].Value[0])
case nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE:
bondSlave.AdPartnerOperPortState = native.Uint16(data[i].Value[0:2])
}
}
}
func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
ipv := link.(*IPVlan)
for _, datum := range data {
@ -2725,6 +2783,30 @@ func LinkSetBondSlave(link Link, master *Bond) error {
return nil
}
// LinkSetBondSlaveQueueId modify bond slave queue-id.
func (h *Handle) LinkSetBondSlaveQueueId(link Link, queueId uint16) 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)
linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil)
data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(queueId))
req.AddData(linkInfo)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
return err
}
// LinkSetBondSlaveQueueId modify bond slave queue-id.
func LinkSetBondSlaveQueueId(link Link, queueId uint16) error {
return pkgHandle.LinkSetBondSlaveQueueId(link, queueId)
}
// VethPeerIndex get veth peer index.
func VethPeerIndex(link *Veth) (int, error) {
fd, err := getSocketUDP()

View File

@ -2035,6 +2035,81 @@ func TestVethPeerIndex(t *testing.T) {
}
}
func TestLinkSlaveBond(t *testing.T) {
minKernelRequired(t, 3, 13)
tearDown := setUpNetlinkTest(t)
defer tearDown()
const (
bondName = "foo"
slaveName = "fooFoo"
)
bond := NewLinkBond(LinkAttrs{Name: bondName})
bond.Mode = BOND_MODE_BALANCE_RR
if err := LinkAdd(bond); err != nil {
t.Fatal(err)
}
defer LinkDel(bond)
slaveDummy := &Dummy{LinkAttrs{Name: slaveName}}
if err := LinkAdd(slaveDummy); err != nil {
t.Fatal(err)
}
defer LinkDel(slaveDummy)
if err := LinkSetBondSlave(slaveDummy, bond); err != nil {
t.Fatal(err)
}
slaveLink, err := LinkByName(slaveName)
if err != nil {
t.Fatal(err)
}
slave := slaveLink.Attrs().Slave
if slave == nil {
t.Errorf("for %s expected slave is not nil.", slaveName)
}
if slaveType := slave.SlaveType(); slaveType != "bond" {
t.Errorf("for %s expected slave type is 'bond', but '%s'", slaveName, slaveType)
}
}
func TestLinkSetBondSlaveQueueId(t *testing.T) {
minKernelRequired(t, 3, 13)
tearDown := setUpNetlinkTest(t)
defer tearDown()
const (
bondName = "foo"
slave1Name = "fooFoo"
)
bond := NewLinkBond(LinkAttrs{Name: bondName})
if err := LinkAdd(bond); err != nil {
t.Fatal(err)
}
defer LinkDel(bond)
slave := &Dummy{LinkAttrs{Name: slave1Name}}
if err := LinkAdd(slave); err != nil {
t.Fatal(err)
}
defer LinkDel(slave)
if err := LinkSetBondSlave(slave, bond); err != nil {
t.Fatal(err)
}
if err := pkgHandle.LinkSetBondSlaveQueueId(slave, 1); err != nil {
t.Fatal(err)
}
}
func TestLinkSetBondSlave(t *testing.T) {
minKernelRequired(t, 3, 13)

View File

@ -13,7 +13,9 @@ const (
IFLA_INFO_KIND
IFLA_INFO_DATA
IFLA_INFO_XSTATS
IFLA_INFO_MAX = IFLA_INFO_XSTATS
IFLA_INFO_SLAVE_KIND
IFLA_INFO_SLAVE_DATA
IFLA_INFO_MAX = IFLA_INFO_SLAVE_DATA
)
const (
@ -165,6 +167,8 @@ const (
IFLA_BOND_SLAVE_PERM_HWADDR
IFLA_BOND_SLAVE_QUEUE_ID
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE
)
const (