diff --git a/config/default/manager/manager.yaml b/config/default/manager/manager.yaml index 3ea729446..5beaa235a 100644 --- a/config/default/manager/manager.yaml +++ b/config/default/manager/manager.yaml @@ -17,7 +17,7 @@ metadata: controller-tools.k8s.io: "1.0" data: RANGE_START: 02:00:00:00:00:00 - RANGE_END: FD:FF:FF:FF:FF:FF + RANGE_END: 02:FF:FF:FF:FF:FF --- apiVersion: apps/v1 kind: Deployment diff --git a/config/release/kubemacpool.yaml b/config/release/kubemacpool.yaml index 40128bfdc..0d4385ca5 100644 --- a/config/release/kubemacpool.yaml +++ b/config/release/kubemacpool.yaml @@ -127,7 +127,7 @@ subjects: --- apiVersion: v1 data: - RANGE_END: FD:FF:FF:FF:FF:FF + RANGE_END: 02:FF:FF:FF:FF:FF RANGE_START: "02:00:00:00:00:00" kind: ConfigMap metadata: diff --git a/config/test/kubemacpool.yaml b/config/test/kubemacpool.yaml index a1e168b05..13b7507b1 100644 --- a/config/test/kubemacpool.yaml +++ b/config/test/kubemacpool.yaml @@ -127,7 +127,7 @@ subjects: --- apiVersion: v1 data: - RANGE_END: FD:FF:FF:FF:FF:FF + RANGE_END: 02:FF:FF:FF:FF:FF RANGE_START: "02:00:00:00:00:00" kind: ConfigMap metadata: diff --git a/pkg/pool-manager/pool.go b/pkg/pool-manager/pool.go index a0fa139c1..b3792813e 100644 --- a/pkg/pool-manager/pool.go +++ b/pkg/pool-manager/pool.go @@ -59,6 +59,14 @@ func NewPoolManager(kubeClient kubernetes.Interface, rangeStart, rangeEnd net.Ha if err != nil { return nil, err } + err = checkCast(rangeStart) + if err != nil { + return nil, fmt.Errorf("RangeStart is invalid: %v", err) + } + err = checkCast(rangeEnd) + if err != nil { + return nil, fmt.Errorf("RangeEnd is invalid: %v", err) + } currentMac := make(net.HardwareAddr, len(rangeStart)) copy(currentMac, rangeStart) @@ -140,7 +148,17 @@ func checkRange(startMac, endMac net.HardwareAddr) error { } } - return fmt.Errorf("Invalid range start: %s end: %s", startMac.String(), endMac.String()) + return fmt.Errorf("Invalid range. rangeStart: %s rangeEnd: %s", startMac.String(), endMac.String()) +} + +func checkCast(mac net.HardwareAddr) error { + // A bitwise AND between 00000001 and the mac address first octet. + // In case where the LSB of the first octet (the multicast bit) is on, it will return 1, and 0 otherwise. + multicastBit := 1 & mac[0] + if multicastBit != 1 { + return nil + } + return fmt.Errorf("invalid mac address. Multicast addressing is not supported. Unicast addressing must be used. The first octet is %#0X", mac[0]) } func getNextMac(currentMac net.HardwareAddr) net.HardwareAddr { diff --git a/pkg/pool-manager/pool_test.go b/pkg/pool-manager/pool_test.go index 168f393c2..dd8d54fa4 100644 --- a/pkg/pool-manager/pool_test.go +++ b/pkg/pool-manager/pool_test.go @@ -24,7 +24,7 @@ import ( "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/fake" kubevirt "kubevirt.io/kubevirt/pkg/api/v1" @@ -77,6 +77,24 @@ var _ = Describe("Pool", func() { table.Entry("Start: 02:00:00:00:00:00 End: 02:10:00:00:00:00", "02:00:00:00:00:00", "02:10:00:00:00:00", false), table.Entry("Start: 02:FF:00:00:00:00 End: 02:00:00:00:00:00", "02:FF:00:00:00:00", "00:00:00:00:00:00", true), ) + + table.DescribeTable("should check that the multicast bit is off", func(MacAddr string, shouldFail bool) { + MacAddrHW, err := net.ParseMAC(MacAddr) + Expect(err).ToNot(HaveOccurred()) + err = checkCast(MacAddrHW) + if shouldFail { + Expect(err).To(HaveOccurred()) + } else { + Expect(err).ToNot(HaveOccurred()) + } + }, + table.Entry("Valid address: 02:00:00:00:00:00", "02:00:00:00:00:00", false), + table.Entry("Valid address: 06:00:00:00:00:00", "06:00:00:00:00:00", false), + table.Entry("Valid address: 0A:00:00:00:00:00", "0A:00:00:00:00:00", false), + table.Entry("Valid address: 0E:00:00:00:00:00", "0E:00:00:00:00:00", false), + table.Entry("Invalid address: 01:FF:00:00:00:00, the first octet is not 02, 06, 0A or 0E", "01:FF:00:00:00:00", true), + table.Entry("Invalid address: FF:FF:00:00:00:00, the first octet is not 02, 06, 0A or 0E", "FF:FF:00:00:00:00", true), + ) }) Describe("Pool Manager General Functions ", func() { @@ -84,20 +102,45 @@ var _ = Describe("Pool", func() { fakeClient := fake.NewSimpleClientset() startPoolRangeEnv, err := net.ParseMAC("02:00:00:00:00:00") Expect(err).ToNot(HaveOccurred()) - endPoolRangeEnv, err := net.ParseMAC("FD:FF:FF:FF:FF:FF") + endPoolRangeEnv, err := net.ParseMAC("02:FF:FF:FF:FF:FF") Expect(err).ToNot(HaveOccurred()) _, err = NewPoolManager(fakeClient, startPoolRangeEnv, endPoolRangeEnv, false) Expect(err).ToNot(HaveOccurred()) }) - It("should fail to pool manager because of the invalid range", func() { + It("should fail to create pool manager when rangeStart is greater than rangeEnd", func() { fakeClient := fake.NewSimpleClientset() - startPoolRangeEnv, err := net.ParseMAC("03:00:00:00:00:00") + startPoolRangeEnv, err := net.ParseMAC("0A:00:00:00:00:00") Expect(err).ToNot(HaveOccurred()) endPoolRangeEnv, err := net.ParseMAC("02:00:00:00:00:00") Expect(err).ToNot(HaveOccurred()) _, err = NewPoolManager(fakeClient, startPoolRangeEnv, endPoolRangeEnv, false) Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(Equal("Invalid range. rangeStart: 0a:00:00:00:00:00 rangeEnd: 02:00:00:00:00:00")) + + }) + + It("should fail to pool manager because of the first octet of RangeStart is not 2, 6, A, E", func() { + fakeClient := fake.NewSimpleClientset() + startPoolRangeEnv, err := net.ParseMAC("03:00:00:00:00:00") + Expect(err).ToNot(HaveOccurred()) + endPoolRangeEnv, err := net.ParseMAC("06:00:00:00:00:00") + Expect(err).ToNot(HaveOccurred()) + _, err = NewPoolManager(fakeClient, startPoolRangeEnv, endPoolRangeEnv, false) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(Equal("RangeStart is invalid: invalid mac address. Multicast addressing is not supported. Unicast addressing must be used. The first octet is 0X3")) + + }) + + It("should fail to create a pool manager object when the first octet of RangeEnd is not 2, 6, A, E", func() { + fakeClient := fake.NewSimpleClientset() + startPoolRangeEnv, err := net.ParseMAC("02:00:00:00:00:00") + Expect(err).ToNot(HaveOccurred()) + endPoolRangeEnv, err := net.ParseMAC("05:00:00:00:00:00") + Expect(err).ToNot(HaveOccurred()) + _, err = NewPoolManager(fakeClient, startPoolRangeEnv, endPoolRangeEnv, false) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(Equal("RangeEnd is invalid: invalid mac address. Multicast addressing is not supported. Unicast addressing must be used. The first octet is 0X5")) }) }) diff --git a/pkg/pool-manager/virtualmachine_pool.go b/pkg/pool-manager/virtualmachine_pool.go index ae0551630..6a9a720c1 100644 --- a/pkg/pool-manager/virtualmachine_pool.go +++ b/pkg/pool-manager/virtualmachine_pool.go @@ -18,9 +18,10 @@ package pool_manager import ( "fmt" - "k8s.io/apimachinery/pkg/api/errors" "net" + "k8s.io/apimachinery/pkg/api/errors" + corev1 "k8s.io/api/core/v1" kubevirt "kubevirt.io/kubevirt/pkg/api/v1" )