feat: add LinkSetBondSlaveActive()/LinkDelBondSlave()

Signed-off-by: Jason Joo <hblzxsj@gmail.com>
This commit is contained in:
Jason Joo
2024-07-30 15:58:16 +07:00
committed by Alessandro Boch
parent a57a7bd6b2
commit 4317e32776
2 changed files with 134 additions and 5 deletions

View File

@@ -3704,8 +3704,7 @@ func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
// LinkSetBondSlave add slave to bond link via ioctl interface.
func LinkSetBondSlave(link Link, master *Bond) error {
func ioctlBondSlave(cmd uintptr, link Link, master *Bond) error {
fd, err := getSocketUDP()
if err != nil {
return err
@@ -3713,10 +3712,38 @@ func LinkSetBondSlave(link Link, master *Bond) error {
defer syscall.Close(fd)
ifreq := newIocltSlaveReq(link.Attrs().Name, master.Attrs().Name)
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), unix.SIOCBONDENSLAVE, uintptr(unsafe.Pointer(ifreq)))
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(ifreq)))
if errno != 0 {
return fmt.Errorf("Failed to enslave %q to %q, errno=%v", link.Attrs().Name, master.Attrs().Name, errno)
return fmt.Errorf("errno=%v", errno)
}
return nil
}
// LinkSetBondSlaveActive sets specified slave to ACTIVE in an `active-backup` bond link via ioctl interface.
//
// Multiple calls keeps the status unchanged(shown in the unit test).
func LinkSetBondSlaveActive(link Link, master *Bond) error {
err := ioctlBondSlave(unix.SIOCBONDCHANGEACTIVE, link, master)
if err != nil {
return fmt.Errorf("Failed to set slave %q active in %q, %v", link.Attrs().Name, master.Attrs().Name, err)
}
return nil
}
// LinkSetBondSlave add slave to bond link via ioctl interface.
func LinkSetBondSlave(link Link, master *Bond) error {
err := ioctlBondSlave(unix.SIOCBONDENSLAVE, link, master)
if err != nil {
return fmt.Errorf("Failed to enslave %q to %q, %v", link.Attrs().Name, master.Attrs().Name, err)
}
return nil
}
// LinkSetBondSlave removes specified slave from bond link via ioctl interface.
func LinkDelBondSlave(link Link, master *Bond) error {
err := ioctlBondSlave(unix.SIOCBONDRELEASE, link, master)
if err != nil {
return fmt.Errorf("Failed to del slave %q from %q, %v", link.Attrs().Name, master.Attrs().Name, err)
}
return nil
}

View File

@@ -3205,6 +3205,108 @@ func TestLinkSetBondSlave(t *testing.T) {
}
}
func testFailover(t *testing.T, slaveName, bondName string) {
slaveLink, err := LinkByName(slaveName)
if err != nil {
t.Fatal(err)
}
bondLink, err := LinkByName(bondName)
if err != nil {
t.Fatal(err)
}
err = LinkSetBondSlaveActive(slaveLink, &Bond{LinkAttrs: *bondLink.Attrs()})
if err != nil {
t.Errorf("set slave link active failed: %v", err)
return
}
bondLink, err = LinkByName(bondName)
if err != nil {
t.Fatal(err)
}
bond := bondLink.(*Bond)
if bond.ActiveSlave != slaveLink.Attrs().Index {
t.Errorf("the current active slave %d is not expected as %d", bond.ActiveSlave, slaveLink.Attrs().Index)
}
}
func TestLinkFailover(t *testing.T) {
minKernelRequired(t, 3, 13)
tearDown := setUpNetlinkTest(t)
defer tearDown()
const (
bondName = "foo"
slaveOneName = "fooFoo"
slaveTwoName = "fooBar"
)
bond := NewLinkBond(LinkAttrs{Name: bondName})
bond.Mode = StringToBondModeMap["active-backup"]
bond.Miimon = 100
if err := LinkAdd(bond); err != nil {
t.Fatal(err)
}
bondLink, err := LinkByName(bondName)
if err != nil {
t.Fatal(err)
}
defer LinkDel(bondLink)
if err := LinkAdd(&Dummy{LinkAttrs{Name: slaveOneName}}); err != nil {
t.Fatal(err)
}
slaveOneLink, err := LinkByName(slaveOneName)
if err != nil {
t.Fatal(err)
}
defer LinkDel(slaveOneLink)
if err := LinkAdd(&Dummy{LinkAttrs{Name: slaveTwoName}}); err != nil {
t.Fatal(err)
}
slaveTwoLink, err := LinkByName(slaveTwoName)
if err != nil {
t.Fatal(err)
}
defer LinkDel(slaveTwoLink)
if err := LinkSetBondSlave(slaveOneLink, &Bond{LinkAttrs: *bondLink.Attrs()}); err != nil {
t.Fatal(err)
}
if err := LinkSetBondSlave(slaveTwoLink, &Bond{LinkAttrs: *bondLink.Attrs()}); err != nil {
t.Fatal(err)
}
testFailover(t, slaveOneName, bondName)
testFailover(t, slaveTwoName, bondName)
testFailover(t, slaveTwoName, bondName)
// del slave from bond
slaveOneLink, err = LinkByName(slaveOneName)
if err != nil {
t.Fatal(err)
}
err = LinkDelBondSlave(slaveOneLink, &Bond{LinkAttrs: *bondLink.Attrs()})
if err != nil {
t.Errorf("Remove slave %s from bond failed: %v", slaveOneName, err)
}
slaveOneLink, err = LinkByName(slaveOneName)
if err != nil {
t.Fatal(err)
}
if slaveOneLink.Attrs().MasterIndex > 0 {
t.Errorf("The nic %s is still a slave of %d", slaveOneName, slaveOneLink.Attrs().MasterIndex)
}
}
func TestLinkSetAllmulticast(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()