Skip to content

Commit c92fbb2

Browse files
committed
Avoid handling mac duplication
The bond-cni should not attempt to modify the mac addresses of slaves during both, creation and deletion of the bond interface. During deletion, the bond driver takes care of reverting any modifications. Only balance-tlb and balance-alb do not support slaves with same mac addresses. The plugin now returns an error if this is the case for these modes. Signed-off-by: Marcelo Guerrero <[email protected]>
1 parent d996cc5 commit c92fbb2

File tree

3 files changed

+44
-121
lines changed

3 files changed

+44
-121
lines changed

bond/bond.go

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ import (
2929
"github.com/containernetworking/cni/pkg/version"
3030
"github.com/containernetworking/plugins/pkg/ipam"
3131
"github.com/containernetworking/plugins/pkg/ns"
32-
"github.com/intel/bond-cni/bond/util"
3332
"github.com/vishvananda/netlink"
3433
"github.com/vishvananda/netns"
34+
35+
"github.com/intel/bond-cni/bond/util"
3536
)
3637

3738
type bondingConfig struct {
@@ -71,6 +72,10 @@ func loadConfigFile(bytes []byte) (*bondingConfig, string, error) {
7172
return nil, "", fmt.Errorf("allSlavesActive should be 0 or 1, actual: %+v", *bondConf.AllSlavesActive)
7273
}
7374

75+
if bondConf.FailOverMac < 0 || bondConf.FailOverMac > 2 {
76+
return nil, "", fmt.Errorf("FailOverMac mode should be 0, 1 or 2 actual: %+v", bondConf.FailOverMac)
77+
}
78+
7479
return bondConf, bondConf.CNIVersion, nil
7580
}
7681

@@ -144,10 +149,7 @@ func createBondedLink(bondName string, bondConf *bondingConfig, netNsHandle *net
144149
// loop over the linkObjectsToBond, set each DOWN, update the interface MASTER & set it UP again.
145150
// again we use the netNsHandle to interfact with these links in the namespace provided. return error
146151
func attachLinksToBond(bondLinkObj *netlink.Bond, linkObjectsToBond []netlink.Link, netNsHandle *netlink.Handle) error {
147-
err := util.HandleMacDuplicates(linkObjectsToBond, netNsHandle)
148-
if err != nil {
149-
return fmt.Errorf("failed to handle duplicated macs on link slaves, error: %+v", err)
150-
}
152+
var err error
151153

152154
bondLinkIndex := bondLinkObj.Index
153155
for _, linkObject := range linkObjectsToBond {
@@ -275,14 +277,11 @@ func createBond(bondName string, bondConf *bondingConfig, nspath string, ns ns.N
275277
return nil, fmt.Errorf("failed to retrieve link objects from configuration file (%+v), error: %+v", bondConf, err)
276278
}
277279

278-
err = util.ValidateMTU(linkObjectsToBond, bondConf.MTU)
280+
err = util.ValidateSlaveLinks(linkObjectsToBond, bondConf.MTU, bondConf.Mode)
279281
if err != nil {
280-
return nil, err
282+
return nil, fmt.Errorf("failed to validate slave links (%+v), error: %w", linkObjectsToBond, err)
281283
}
282284

283-
if bondConf.FailOverMac < 0 || bondConf.FailOverMac > 2 {
284-
return nil, fmt.Errorf("FailOverMac mode should be 0, 1 or 2 actual: %+v", bondConf.FailOverMac)
285-
}
286285
bondLinkObj, err := createBondedLink(bondName, bondConf, netNsHandle)
287286
if err != nil {
288287
return nil, fmt.Errorf("failed to create bonded link (%+v), error: %+v", bondName, err)
@@ -433,19 +432,6 @@ func cmdDel(args *skel.CmdArgs) error {
433432
return fmt.Errorf("failed to deattached links from bond, error: %+v", err)
434433
}
435434

436-
// Fetch slave links again to have the latest state
437-
// For instance, Active-backup mode with fail_over_mac=0 reverts the mac address of backup slaves
438-
for i := range linkObjectsToDeattach {
439-
linkObjectsToDeattach[i], err = netNsHandle.LinkByName(linkObjectsToDeattach[i].Attrs().Name)
440-
if err != nil {
441-
return fmt.Errorf("failed to find link (%+v), error: %+v", linkObjectsToDeattach[i].Attrs().Name, err)
442-
}
443-
}
444-
445-
if err = util.HandleMacDuplicates(linkObjectsToDeattach, netNsHandle); err != nil {
446-
return fmt.Errorf("failed to validate deattached links macs, error: %+v", err)
447-
}
448-
449435
err = netNsHandle.LinkDel(linkObjToDel)
450436
if err != nil {
451437
return fmt.Errorf("failed to delete bonded link (%+v), error: %+v", linkObjToDel.Attrs().Name, err)

bond/bond_test.go

Lines changed: 7 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
package main
1616

1717
import (
18+
"errors"
1819
"fmt"
20+
"github.com/intel/bond-cni/bond/util"
1921
"strconv"
2022

2123
"github.com/containernetworking/cni/pkg/skel"
@@ -198,7 +200,7 @@ var _ = Describe("bond plugin", func() {
198200
Entry("When Version is 0.1.0", "0.1.0"),
199201
)
200202

201-
It("verifies the plugin copes with duplicated macs in balance-tlb mode", func() {
203+
It("verifies the plugin fails with duplicated macs in balance-tlb mode", func() {
202204
args.StdinData = []byte(fmt.Sprintf(config, "0.3.1", BalanceTlbMode, 1, strconv.FormatBool(linksInContainer), strconv.Itoa(DefaultMTU)))
203205

204206
err := podNS.Do(func(ns.NetNS) error {
@@ -217,66 +219,13 @@ var _ = Describe("bond plugin", func() {
217219
Expect(err).NotTo(HaveOccurred())
218220

219221
By("creating the plugin")
220-
r, _, err := testutils.CmdAddWithArgs(args, func() error {
221-
return cmdAdd(args)
222-
})
223-
Expect(err).NotTo(HaveOccurred())
224-
225-
By("checking the bond was created")
226-
checkAddReturnResult(&r, IfName)
227-
228-
Expect(err).NotTo(HaveOccurred())
229-
})
230-
231-
It("verifies the plugin handles duplicated macs on delete", func() {
232-
var slave1, slave2 netlink.Link
233-
var err error
234-
235-
err = podNS.Do(func(ns.NetNS) error {
236-
defer GinkgoRecover()
237-
slave1, err = netlink.LinkByName(Slave1)
238-
Expect(err).NotTo(HaveOccurred())
239-
240-
slave2, err = netlink.LinkByName(Slave2)
241-
Expect(err).NotTo(HaveOccurred())
242-
243-
err = netlink.LinkSetHardwareAddr(slave2, slave1.Attrs().HardwareAddr)
244-
Expect(err).NotTo(HaveOccurred())
245-
return nil
246-
})
247-
248-
By("creating the plugin")
249-
r, _, err := testutils.CmdAddWithArgs(args, func() error {
222+
_, _, err = testutils.CmdAddWithArgs(args, func() error {
250223
return cmdAdd(args)
251224
})
252-
Expect(err).NotTo(HaveOccurred())
253-
254-
By("checking the bond was created")
255-
checkAddReturnResult(&r, IfName)
256-
257-
err = podNS.Do(func(ns.NetNS) error {
258-
defer GinkgoRecover()
259-
By("duplicating the macs on the slaves")
260-
err = netlink.LinkSetHardwareAddr(slave2, slave1.Attrs().HardwareAddr)
261-
Expect(err).NotTo(HaveOccurred())
262-
return nil
263-
})
264-
By("deleting the plugin")
265-
err = testutils.CmdDel(podNS.Path(),
266-
args.ContainerID, "", func() error { return cmdDel(args) })
267-
Expect(err).NotTo(HaveOccurred())
225+
Expect(err).To(HaveOccurred())
268226

269-
err = podNS.Do(func(ns.NetNS) error {
270-
defer GinkgoRecover()
271-
By("validating the macs are not duplicated")
272-
slave1, err = netlink.LinkByName(Slave1)
273-
Expect(err).NotTo(HaveOccurred())
274-
slave2, err = netlink.LinkByName(Slave2)
275-
Expect(err).NotTo(HaveOccurred())
276-
Expect(slave1.Attrs().HardwareAddr.String()).NotTo(Equal(slave2.Attrs().HardwareAddr.String()))
277-
return nil
278-
})
279-
Expect(err).NotTo(HaveOccurred())
227+
var dupMacErr *util.ErrorDuplicateMac
228+
Expect(errors.As(err, &dupMacErr)).To(BeTrue())
280229
})
281230

282231
It("verifies that mac addresses are restored correctly in active-backup with fail_over_mac 0", func() {

bond/util/validation.go

Lines changed: 28 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package util
22

33
import (
44
"bytes"
5-
"crypto/rand"
65
"fmt"
6+
77
"github.com/vishvananda/netlink"
88
)
99

@@ -13,6 +13,31 @@ const (
1313
minMtuIpv4Packet = 68
1414
)
1515

16+
type ErrorDuplicateMac struct {
17+
Mac string
18+
}
19+
20+
func (e *ErrorDuplicateMac) Error() string {
21+
return fmt.Sprintf("duplicate MAC address found: %s", e.Mac)
22+
}
23+
24+
func ValidateSlaveLinks(slaveLinks []netlink.Link, mtu int, mode string) error {
25+
err := ValidateMTU(slaveLinks, mtu)
26+
if err != nil {
27+
return fmt.Errorf("failed to validate MTU, error: %w", err)
28+
}
29+
30+
bondMode := netlink.StringToBondMode(mode)
31+
if bondMode == netlink.BOND_MODE_BALANCE_TLB || bondMode == netlink.BOND_MODE_BALANCE_ALB {
32+
err = ValidateMacDuplicates(slaveLinks)
33+
if err != nil {
34+
return fmt.Errorf("failed to validate mac address uniqueness, bond mode: %s, error: %w", mode, err)
35+
}
36+
}
37+
38+
return nil
39+
}
40+
1641
func ValidateMTU(slaveLinks []netlink.Link, mtu int) error {
1742
// if not specified set MTU to default
1843
if mtu == 0 {
@@ -57,16 +82,12 @@ func ValidateMTU(slaveLinks []netlink.Link, mtu int) error {
5782
return nil
5883
}
5984

60-
func HandleMacDuplicates(linkObjectsToBond []netlink.Link, netNsHandle *netlink.Handle) error {
85+
func ValidateMacDuplicates(linkObjectsToBond []netlink.Link) error {
6186
macsInUse := []string{}
62-
var err error
6387
for _, link := range linkObjectsToBond {
6488
linkMac := link.Attrs().HardwareAddr.String()
6589
if isMacDuplicated(linkMac, macsInUse) {
66-
linkMac, err = updateDuplicateMac(link, netNsHandle, macsInUse)
67-
if err != nil {
68-
return err
69-
}
90+
return &ErrorDuplicateMac{Mac: linkMac}
7091
}
7192
macsInUse = append(macsInUse, linkMac)
7293
}
@@ -81,36 +102,3 @@ func isMacDuplicated(mac string, macsInUse []string) bool {
81102
}
82103
return false
83104
}
84-
85-
func updateDuplicateMac(link netlink.Link, netNsHandle *netlink.Handle, macsInUse []string) (string, error) {
86-
newMac, err := generateUnusedMac(macsInUse)
87-
if err != nil {
88-
return "", err
89-
}
90-
err = netNsHandle.LinkSetHardwareAddr(link, []byte(newMac))
91-
if err != nil {
92-
return "newMac", nil
93-
}
94-
return newMac, nil
95-
}
96-
97-
func generateUnusedMac(macsInUse []string) (string, error) {
98-
var newMac string
99-
var err error
100-
for duplicated := true; duplicated; duplicated = isMacDuplicated(newMac, macsInUse) {
101-
newMac, err = randomMac()
102-
if err != nil {
103-
return "", err
104-
}
105-
}
106-
return newMac, nil
107-
}
108-
109-
func randomMac() (string, error) {
110-
buf := make([]byte, 5)
111-
_, err := rand.Read(buf)
112-
if err != nil {
113-
return "", err
114-
}
115-
return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x\n", byte(2), buf[0], buf[1], buf[2], buf[3], buf[4]), nil
116-
}

0 commit comments

Comments
 (0)