From 0198d5dd0f9d2e83a6ce03ff29b9a160fb69e71b Mon Sep 17 00:00:00 2001 From: Michal Rostecki Date: Fri, 15 Oct 2021 20:08:45 +0200 Subject: [PATCH] vxlan: Generate MAC address before creating a link systemd 242+ assigns MAC addresses for all virtual devices which don't have the address assigned already. That resulted in systemd overriding MAC addresses of flannel.* interfaces. The fix which prevents systemd from setting the address is to define the concrete MAC address when creating the link. Fixes: #1155 Ref: k3s-io/k3s#4188 Signed-off-by: Michal Rostecki --- backend/vxlan/device.go | 12 +++++++++--- pkg/mac/mac.go | 35 +++++++++++++++++++++++++++++++++++ pkg/mac/mac_test.go | 28 ++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 pkg/mac/mac.go create mode 100644 pkg/mac/mac_test.go diff --git a/backend/vxlan/device.go b/backend/vxlan/device.go index 3fa215e96..1bf2dbc87 100644 --- a/backend/vxlan/device.go +++ b/backend/vxlan/device.go @@ -13,7 +13,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +build !windows package vxlan @@ -24,6 +23,7 @@ import ( "github.com/containernetworking/plugins/pkg/utils/sysctl" "github.com/flannel-io/flannel/pkg/ip" + "github.com/flannel-io/flannel/pkg/mac" "github.com/vishvananda/netlink" log "k8s.io/klog" ) @@ -44,9 +44,15 @@ type vxlanDevice struct { } func newVXLANDevice(devAttrs *vxlanDeviceAttrs) (*vxlanDevice, error) { + hardwareAddr, err := mac.NewHardwareAddr() + if err != nil { + return nil, err + } + link := &netlink.Vxlan{ LinkAttrs: netlink.LinkAttrs{ - Name: devAttrs.name, + Name: devAttrs.name, + HardwareAddr: hardwareAddr, }, VxlanId: int(devAttrs.vni), VtepDevIndex: devAttrs.vtepIndex, @@ -56,7 +62,7 @@ func newVXLANDevice(devAttrs *vxlanDeviceAttrs) (*vxlanDevice, error) { GBP: devAttrs.gbp, } - link, err := ensureLink(link) + link, err = ensureLink(link) if err != nil { return nil, err } diff --git a/pkg/mac/mac.go b/pkg/mac/mac.go new file mode 100644 index 000000000..b88f3e1f4 --- /dev/null +++ b/pkg/mac/mac.go @@ -0,0 +1,35 @@ +// Copyright 2021 flannel authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mac + +import ( + "crypto/rand" + "fmt" + "net" +) + +// NewHardwareAddr generates a new random hardware (MAC) address, local and +// unicast. +func NewHardwareAddr() (net.HardwareAddr, error) { + hardwareAddr := make(net.HardwareAddr, 6) + if _, err := rand.Read(hardwareAddr); err != nil { + return nil, fmt.Errorf("could not generate random MAC address: %w", err) + } + + // Ensure that address is locally administered and unicast. + hardwareAddr[0] = (hardwareAddr[0] & 0xfe) | 0x02 + + return hardwareAddr, nil +} diff --git a/pkg/mac/mac_test.go b/pkg/mac/mac_test.go new file mode 100644 index 000000000..719e082bf --- /dev/null +++ b/pkg/mac/mac_test.go @@ -0,0 +1,28 @@ +// Copyright 2021 flannel authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mac + +import ( + "testing" +) + +func TestNewHardwareAddr(t *testing.T) { + // Ignore the actual address, since it's random. + // But an error should never be returned. + _, err := NewHardwareAddr() + if err != nil { + t.Fatalf(err) + } +}