mirror of
https://github.com/vishvananda/netlink.git
synced 2025-09-26 20:01:13 +08:00
feat: add LinkSetBondSlaveActive()/LinkDelBondSlave()
Signed-off-by: Jason Joo <hblzxsj@gmail.com>
This commit is contained in:

committed by
Alessandro Boch

parent
a57a7bd6b2
commit
4317e32776
@@ -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
|
||||
}
|
||||
|
102
link_test.go
102
link_test.go
@@ -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()
|
||||
|
Reference in New Issue
Block a user