From 814340fc9d5d9c78098ec4689fe65fb1733014c7 Mon Sep 17 00:00:00 2001 From: Yuval Goldberg Date: Sun, 26 Jul 2020 18:02:47 +0300 Subject: [PATCH] Set MacAddress on returned objects from WithOptions functions --- macvlan_linux.go | 7 ++++ macvlan_linux_test.go | 70 +++++++++++++++++++++++++++++++++++++ macvtap_linux.go | 7 ++++ macvtap_linux_test.go | 70 +++++++++++++++++++++++++++++++++++++ vlan_linux.go | 7 ++++ vlan_linux_test.go | 81 +++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 240 insertions(+), 2 deletions(-) diff --git a/macvlan_linux.go b/macvlan_linux.go index 132ccf1..14b6c29 100644 --- a/macvlan_linux.go +++ b/macvlan_linux.go @@ -127,6 +127,13 @@ func NewMacVlanLinkWithOptions(masterDev string, opts MacVlanOptions) (MacVlaner return nil, fmt.Errorf("Incorrect options specified. Attempt to delete the link failed: %s", errDel) } } + + hwaddr, err := net.ParseMAC(opts.MacAddr) + if err != nil { + return nil, err + } + + macVlanIfc.HardwareAddr = hwaddr } masterIfc, err := net.InterfaceByName(masterDev) diff --git a/macvlan_linux_test.go b/macvlan_linux_test.go index 389d875..989c418 100644 --- a/macvlan_linux_test.go +++ b/macvlan_linux_test.go @@ -64,3 +64,73 @@ func Test_NewMacVlanLink(t *testing.T) { } } } + +type macvlnWithOptionsTest struct { + masterDev string + opts *MacVlanOptions +} + +var macvlnWithOptionsTests = []macvlnWithOptionsTest{ + {"master01", &MacVlanOptions{Dev: "test", MacAddr: "aa:aa:aa:aa:aa:aa", Mode: "bridge"}}, +} + +func Test_NewMacVlanLinkWithOptions(t *testing.T) { + for _, tt := range macvlnWithOptionsTests { + var iface *net.Interface + + tl := &testLink{} + + if err := tl.prepTestLink(tt.masterDev, "dummy"); err != nil { + t.Skipf("NewMacVlanLinkWithOptions test requries external command: %v", err) + } + + if err := tl.create(); err != nil { + t.Fatalf("testLink.create failed: %v", err) + } else { + time.Sleep(10 * time.Millisecond) + } + + mvln, err := NewMacVlanLinkWithOptions(tt.masterDev, *tt.opts) + if err != nil { + t.Fatalf("NewMacVlanLinkWithOptions(%s, %s) failed to run: %s", tt.masterDev, *tt.opts, err) + } + + iface = mvln.NetInterface() + + if iface.HardwareAddr.String() != tt.opts.MacAddr { + tl.teardown() + t.Fatalf("NewMacVlanLinkWithOptions(%s, %s) failed: expected %s, returned %s", + tt.masterDev, *tt.opts, tt.opts.MacAddr, iface.HardwareAddr.String()) + } + + mvlnName := iface.Name + if _, err := net.InterfaceByName(mvlnName); err != nil { + tl.teardown() + t.Fatalf("Could not find %s on the host: %s", mvlnName, err) + } + + testRes, err := linkInfo(mvlnName, "macvlan") + if err != nil { + tl.teardown() + t.Fatalf("Failed to list %s operation mode: %s", mvlnName, err) + } + + if testRes.linkType != "macvlan" { + tl.teardown() + t.Fatalf("NewMacVlanLinkWithOptions(%s, %s) failed: expected macvlan, returned %s", + tt.masterDev, *tt.opts, testRes.linkType) + } + + if testRes.linkData != "bridge" { + tl.teardown() + t.Fatalf("NewMacVlanLinkWithOptions(%s, %s) failed: expected bridge, returned %s", + tt.masterDev, *tt.opts, testRes.linkData) + } + + if err := tl.teardown(); err != nil { + t.Fatalf("testLink.teardown failed: %v", err) + } else { + time.Sleep(10 * time.Millisecond) + } + } +} diff --git a/macvtap_linux.go b/macvtap_linux.go index 1be2371..5d22b57 100644 --- a/macvtap_linux.go +++ b/macvtap_linux.go @@ -97,6 +97,13 @@ func NewMacVtapLinkWithOptions(masterDev string, opts MacVlanOptions) (MacVtaper errDel) } } + + hwaddr, err := net.ParseMAC(opts.MacAddr) + if err != nil { + return nil, err + } + + macVtapIfc.HardwareAddr = hwaddr } masterIfc, err := net.InterfaceByName(masterDev) diff --git a/macvtap_linux_test.go b/macvtap_linux_test.go index c6bcf9f..badbe67 100644 --- a/macvtap_linux_test.go +++ b/macvtap_linux_test.go @@ -64,3 +64,73 @@ func Test_NewMacVtapLink(t *testing.T) { } } } + +type macvtpWithOptionsTest struct { + masterDev string + opts *MacVlanOptions +} + +var macvtpWithOptionsTests = []macvtpWithOptionsTest{ + {"master01", &MacVlanOptions{Dev: "test", MacAddr: "aa:aa:aa:aa:aa:aa", Mode: "bridge"}}, +} + +func Test_NewMacVtapLinkWithOptions(t *testing.T) { + for _, tt := range macvtpWithOptionsTests { + var iface *net.Interface + + tl := &testLink{} + + if err := tl.prepTestLink(tt.masterDev, "dummy"); err != nil { + t.Skipf("NewMacVtapLinkWithOptions test requries external command: %v", err) + } + + if err := tl.create(); err != nil { + t.Fatalf("testLink.create failed: %v", err) + } else { + time.Sleep(10 * time.Millisecond) + } + + macvtp, err := NewMacVtapLinkWithOptions(tt.masterDev, *tt.opts) + if err != nil { + t.Fatalf("NewMacVtapLinkWithOptions(%s, %s) failed to run: %s", tt.masterDev, *tt.opts, err) + } + + iface = macvtp.NetInterface() + + if iface.HardwareAddr.String() != tt.opts.MacAddr { + tl.teardown() + t.Fatalf("NewMacVtapLinkWithOptions(%s, %s) failed: expected %s, returned %s", + tt.masterDev, *tt.opts, tt.opts.MacAddr, iface.HardwareAddr.String()) + } + + mvtpName := iface.Name + if _, err := net.InterfaceByName(mvtpName); err != nil { + tl.teardown() + t.Fatalf("Could not find %s on the host: %s", mvtpName, err) + } + + testRes, err := linkInfo(mvtpName, "macvtap") + if err != nil { + tl.teardown() + t.Fatalf("Failed to list %s operation mode: %s", mvtpName, err) + } + + if testRes.linkType != "macvtap" { + tl.teardown() + t.Fatalf("NewMacVtapLinkWithOptions(%s, %s) failed: expected macvtap, returned %s", + tt.masterDev, *tt.opts, testRes.linkType) + } + + if testRes.linkData != "bridge" { + tl.teardown() + t.Fatalf("NewMacVtapLinkWithOptions(%s, %s) failed: expected bridge, returned %s", + tt.masterDev, *tt.opts, testRes.linkData) + } + + if err := tl.teardown(); err != nil { + t.Fatalf("testLink.teardown failed: %v", err) + } else { + time.Sleep(10 * time.Millisecond) + } + } +} diff --git a/vlan_linux.go b/vlan_linux.go index f85d141..2085804 100644 --- a/vlan_linux.go +++ b/vlan_linux.go @@ -119,6 +119,13 @@ func NewVlanLinkWithOptions(masterDev string, opts VlanOptions) (Vlaner, error) errDel) } } + + hwaddr, err := net.ParseMAC(opts.MacAddr) + if err != nil { + return nil, err + } + + vlanIfc.HardwareAddr = hwaddr } masterIfc, err := net.InterfaceByName(masterDev) diff --git a/vlan_linux_test.go b/vlan_linux_test.go index e0dff07..926a320 100644 --- a/vlan_linux_test.go +++ b/vlan_linux_test.go @@ -50,7 +50,7 @@ func Test_NewVlanLink(t *testing.T) { if testRes.linkType != "vlan" { tl.teardown() - t.Fatalf("NewMacVlanLink(%s, %d) failed: expected vlan, returned %s", + t.Fatalf("NewVlanLink(%s, %d) failed: expected vlan, returned %s", tt.masterDev, tt.id, testRes.linkType) } @@ -62,7 +62,7 @@ func Test_NewVlanLink(t *testing.T) { if uint16(id) != tt.id { tl.teardown() - t.Fatalf("NewMacVlanLink(%s, %d) failed: expected %d, returned %d", + t.Fatalf("NewVlanLink(%s, %d) failed: expected %d, returned %d", tt.masterDev, tt.id, tt.id, id) } @@ -73,3 +73,80 @@ func Test_NewVlanLink(t *testing.T) { } } } + +type vlnWithOptionsTest struct { + masterDev string + opts *VlanOptions +} + +var vlnWithOptionsTests = []vlnWithOptionsTest{ + {"master01", &VlanOptions{Dev: "test", MacAddr: "aa:aa:aa:aa:aa:aa", Id: 10}}, + {"master02", &VlanOptions{Dev: "test", MacAddr: "aa:aa:aa:aa:aa:aa", Id: 20}}, +} + +func Test_NewVlanLinkWithOptions(t *testing.T) { + for _, tt := range vlnWithOptionsTests { + var iface *net.Interface + + tl := &testLink{} + + if err := tl.prepTestLink(tt.masterDev, "dummy"); err != nil { + t.Skipf("NewVlanLinkWithOptions test requries external command: %v", err) + } + + if err := tl.create(); err != nil { + t.Fatalf("testLink.create failed: %v", err) + } else { + time.Sleep(10 * time.Millisecond) + } + + vln, err := NewVlanLinkWithOptions(tt.masterDev, *tt.opts) + if err != nil { + t.Fatalf("NewVlanLinkWithOptions(%s, %v) failed to run: %s", tt.masterDev, *tt.opts, err) + } + + iface = vln.NetInterface() + + if iface.HardwareAddr.String() != tt.opts.MacAddr { + tl.teardown() + t.Fatalf("NewVlanLinkWithOptions(%s, %v) failed: expected %s, returned %s", + tt.masterDev, *tt.opts, tt.opts.MacAddr, iface.HardwareAddr.String()) + } + + vlnName := vln.NetInterface().Name + if _, err := net.InterfaceByName(vlnName); err != nil { + tl.teardown() + t.Fatalf("Could not find %s on the host: %s", vlnName, err) + } + + testRes, err := linkInfo(vlnName, "vlan") + if err != nil { + tl.teardown() + t.Fatalf("Failed to list %s operation mode: %s", vlnName, err) + } + + if testRes.linkType != "vlan" { + tl.teardown() + t.Fatalf("NewVlanLinkWithOptions(%s, %v) failed: expected vlan, returned %s", + tt.masterDev, *tt.opts, testRes.linkType) + } + + id, err := strconv.Atoi(testRes.linkData) + if err != nil { + tl.teardown() + t.Fatalf("Failed to convert link data %s : %s", testRes.linkData, err) + } + + if uint16(id) != tt.opts.Id { + tl.teardown() + t.Fatalf("NewVlanLinkWithOptions(%s, %v) failed: expected %d, returned %d", + tt.masterDev, *tt.opts, tt.opts.Id, id) + } + + if err := tl.teardown(); err != nil { + t.Fatalf("testLink.teardown failed: %v", err) + } else { + time.Sleep(10 * time.Millisecond) + } + } +}