Skip to content

Commit 4317e32

Browse files
jasonjoo2010aboch
authored andcommitted
feat: add LinkSetBondSlaveActive()/LinkDelBondSlave()
Signed-off-by: Jason Joo <[email protected]>
1 parent a57a7bd commit 4317e32

File tree

2 files changed

+134
-5
lines changed

2 files changed

+134
-5
lines changed

link_linux.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3704,19 +3704,46 @@ func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) {
37043704
}
37053705
}
37063706

3707-
// LinkSetBondSlave add slave to bond link via ioctl interface.
3708-
func LinkSetBondSlave(link Link, master *Bond) error {
3707+
func ioctlBondSlave(cmd uintptr, link Link, master *Bond) error {
37093708
fd, err := getSocketUDP()
37103709
if err != nil {
37113710
return err
37123711
}
37133712
defer syscall.Close(fd)
37143713

37153714
ifreq := newIocltSlaveReq(link.Attrs().Name, master.Attrs().Name)
3716-
3717-
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), unix.SIOCBONDENSLAVE, uintptr(unsafe.Pointer(ifreq)))
3715+
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(ifreq)))
37183716
if errno != 0 {
3719-
return fmt.Errorf("Failed to enslave %q to %q, errno=%v", link.Attrs().Name, master.Attrs().Name, errno)
3717+
return fmt.Errorf("errno=%v", errno)
3718+
}
3719+
return nil
3720+
}
3721+
3722+
// LinkSetBondSlaveActive sets specified slave to ACTIVE in an `active-backup` bond link via ioctl interface.
3723+
//
3724+
// Multiple calls keeps the status unchanged(shown in the unit test).
3725+
func LinkSetBondSlaveActive(link Link, master *Bond) error {
3726+
err := ioctlBondSlave(unix.SIOCBONDCHANGEACTIVE, link, master)
3727+
if err != nil {
3728+
return fmt.Errorf("Failed to set slave %q active in %q, %v", link.Attrs().Name, master.Attrs().Name, err)
3729+
}
3730+
return nil
3731+
}
3732+
3733+
// LinkSetBondSlave add slave to bond link via ioctl interface.
3734+
func LinkSetBondSlave(link Link, master *Bond) error {
3735+
err := ioctlBondSlave(unix.SIOCBONDENSLAVE, link, master)
3736+
if err != nil {
3737+
return fmt.Errorf("Failed to enslave %q to %q, %v", link.Attrs().Name, master.Attrs().Name, err)
3738+
}
3739+
return nil
3740+
}
3741+
3742+
// LinkSetBondSlave removes specified slave from bond link via ioctl interface.
3743+
func LinkDelBondSlave(link Link, master *Bond) error {
3744+
err := ioctlBondSlave(unix.SIOCBONDRELEASE, link, master)
3745+
if err != nil {
3746+
return fmt.Errorf("Failed to del slave %q from %q, %v", link.Attrs().Name, master.Attrs().Name, err)
37203747
}
37213748
return nil
37223749
}

link_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3205,6 +3205,108 @@ func TestLinkSetBondSlave(t *testing.T) {
32053205
}
32063206
}
32073207

3208+
func testFailover(t *testing.T, slaveName, bondName string) {
3209+
slaveLink, err := LinkByName(slaveName)
3210+
if err != nil {
3211+
t.Fatal(err)
3212+
}
3213+
3214+
bondLink, err := LinkByName(bondName)
3215+
if err != nil {
3216+
t.Fatal(err)
3217+
}
3218+
3219+
err = LinkSetBondSlaveActive(slaveLink, &Bond{LinkAttrs: *bondLink.Attrs()})
3220+
if err != nil {
3221+
t.Errorf("set slave link active failed: %v", err)
3222+
return
3223+
}
3224+
3225+
bondLink, err = LinkByName(bondName)
3226+
if err != nil {
3227+
t.Fatal(err)
3228+
}
3229+
bond := bondLink.(*Bond)
3230+
if bond.ActiveSlave != slaveLink.Attrs().Index {
3231+
t.Errorf("the current active slave %d is not expected as %d", bond.ActiveSlave, slaveLink.Attrs().Index)
3232+
}
3233+
}
3234+
3235+
func TestLinkFailover(t *testing.T) {
3236+
minKernelRequired(t, 3, 13)
3237+
3238+
tearDown := setUpNetlinkTest(t)
3239+
defer tearDown()
3240+
3241+
const (
3242+
bondName = "foo"
3243+
slaveOneName = "fooFoo"
3244+
slaveTwoName = "fooBar"
3245+
)
3246+
3247+
bond := NewLinkBond(LinkAttrs{Name: bondName})
3248+
bond.Mode = StringToBondModeMap["active-backup"]
3249+
bond.Miimon = 100
3250+
3251+
if err := LinkAdd(bond); err != nil {
3252+
t.Fatal(err)
3253+
}
3254+
3255+
bondLink, err := LinkByName(bondName)
3256+
if err != nil {
3257+
t.Fatal(err)
3258+
}
3259+
defer LinkDel(bondLink)
3260+
3261+
if err := LinkAdd(&Dummy{LinkAttrs{Name: slaveOneName}}); err != nil {
3262+
t.Fatal(err)
3263+
}
3264+
3265+
slaveOneLink, err := LinkByName(slaveOneName)
3266+
if err != nil {
3267+
t.Fatal(err)
3268+
}
3269+
defer LinkDel(slaveOneLink)
3270+
3271+
if err := LinkAdd(&Dummy{LinkAttrs{Name: slaveTwoName}}); err != nil {
3272+
t.Fatal(err)
3273+
}
3274+
slaveTwoLink, err := LinkByName(slaveTwoName)
3275+
if err != nil {
3276+
t.Fatal(err)
3277+
}
3278+
defer LinkDel(slaveTwoLink)
3279+
3280+
if err := LinkSetBondSlave(slaveOneLink, &Bond{LinkAttrs: *bondLink.Attrs()}); err != nil {
3281+
t.Fatal(err)
3282+
}
3283+
3284+
if err := LinkSetBondSlave(slaveTwoLink, &Bond{LinkAttrs: *bondLink.Attrs()}); err != nil {
3285+
t.Fatal(err)
3286+
}
3287+
3288+
testFailover(t, slaveOneName, bondName)
3289+
testFailover(t, slaveTwoName, bondName)
3290+
testFailover(t, slaveTwoName, bondName)
3291+
3292+
// del slave from bond
3293+
slaveOneLink, err = LinkByName(slaveOneName)
3294+
if err != nil {
3295+
t.Fatal(err)
3296+
}
3297+
err = LinkDelBondSlave(slaveOneLink, &Bond{LinkAttrs: *bondLink.Attrs()})
3298+
if err != nil {
3299+
t.Errorf("Remove slave %s from bond failed: %v", slaveOneName, err)
3300+
}
3301+
slaveOneLink, err = LinkByName(slaveOneName)
3302+
if err != nil {
3303+
t.Fatal(err)
3304+
}
3305+
if slaveOneLink.Attrs().MasterIndex > 0 {
3306+
t.Errorf("The nic %s is still a slave of %d", slaveOneName, slaveOneLink.Attrs().MasterIndex)
3307+
}
3308+
}
3309+
32083310
func TestLinkSetAllmulticast(t *testing.T) {
32093311
tearDown := setUpNetlinkTest(t)
32103312
defer tearDown()

0 commit comments

Comments
 (0)