Skip to content

Commit

Permalink
fix: shorten VLAN link names to fit into the limit of 15 characters
Browse files Browse the repository at this point in the history
Fixes #7679

This should be no-op if the link name is <= 10 chars, but with
predictable interface names based on MAC addresses, they have to be
shortened to make some space for VLAN ID.

Signed-off-by: Andrey Smirnov <[email protected]>
  • Loading branch information
smira committed Sep 5, 2023
1 parent 9c2f765 commit 6058c36
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ func (ctrl *AddressConfigController) processDevicesConfiguration(logger *zap.Log
address := network.AddressSpecSpec{
Address: ipPrefix,
Scope: nethelpers.ScopeGlobal,
LinkName: fmt.Sprintf("%s.%d", device.Interface(), vlan.ID()),
LinkName: nethelpers.VLANLinkName(device.Interface(), vlan.ID()),
ConfigLayer: network.ConfigMachineConfiguration,
Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent),
}
Expand Down
2 changes: 1 addition & 1 deletion internal/app/machined/pkg/controllers/network/cmdline.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ func ParseCmdlineNetwork(cmdline *procfs.Cmdline) (CmdlineNetworking, error) {
Protocol: nethelpers.VLANProtocol8021Q,
}

vlanName = fmt.Sprintf("%s.%d", phyDevice, vlanID)
vlanName = nethelpers.VLANLinkName(phyDevice, uint16(vlanID))

linkSpecUpdated := false

Expand Down
4 changes: 2 additions & 2 deletions internal/app/machined/pkg/controllers/network/link_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ func (ctrl *LinkConfigController) processDevicesConfiguration(logger *zap.Logger
}

for _, vlan := range device.Vlans() {
vlanName := fmt.Sprintf("%s.%d", device.Interface(), vlan.ID())
vlanName := nethelpers.VLANLinkName(device.Interface(), vlan.ID())

linkMap[vlanName] = &network.LinkSpecSpec{
Name: device.Interface(),
Expand Down Expand Up @@ -403,7 +403,7 @@ type vlaner interface {
}

func vlanLink(link *network.LinkSpecSpec, linkName string, vlan vlaner) {
link.Name = fmt.Sprintf("%s.%d", linkName, vlan.ID())
link.Name = nethelpers.VLANLinkName(linkName, vlan.ID())
link.Logical = true
link.Up = true
link.MTU = vlan.MTU()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"go.uber.org/zap"

talosconfig "github.com/siderolabs/talos/pkg/machinery/config/config"
"github.com/siderolabs/talos/pkg/machinery/nethelpers"
"github.com/siderolabs/talos/pkg/machinery/resources/network"
)

Expand Down Expand Up @@ -176,7 +177,7 @@ func (ctrl *OperatorConfigController) Run(ctx context.Context, r controller.Runt

specs = append(specs, network.OperatorSpecSpec{
Operator: network.OperatorDHCP4,
LinkName: fmt.Sprintf("%s.%d", device.Interface(), vlan.ID()),
LinkName: nethelpers.VLANLinkName(device.Interface(), vlan.ID()),
RequireUp: true,
DHCP4: network.DHCP4OperatorSpec{
RouteMetric: routeMetric,
Expand All @@ -193,7 +194,7 @@ func (ctrl *OperatorConfigController) Run(ctx context.Context, r controller.Runt

specs = append(specs, network.OperatorSpecSpec{
Operator: network.OperatorDHCP6,
LinkName: fmt.Sprintf("%s.%d", device.Interface(), vlan.ID()),
LinkName: nethelpers.VLANLinkName(device.Interface(), vlan.ID()),
RequireUp: true,
DHCP6: network.DHCP6OperatorSpec{
RouteMetric: routeMetric,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

"github.com/siderolabs/talos/internal/app/machined/pkg/controllers/network/operator/vip"
talosconfig "github.com/siderolabs/talos/pkg/machinery/config/config"
"github.com/siderolabs/talos/pkg/machinery/nethelpers"
"github.com/siderolabs/talos/pkg/machinery/resources/network"
)

Expand Down Expand Up @@ -118,7 +119,7 @@ func (ctrl *OperatorVIPConfigController) Run(ctx context.Context, r controller.R

for _, vlan := range device.Vlans() {
if vlan.VIPConfig() != nil {
linkName := fmt.Sprintf("%s.%d", device.Interface(), vlan.ID())
linkName := nethelpers.VLANLinkName(device.Interface(), vlan.ID())
if spec, specErr := handleVIP(ctx, vlan.VIPConfig(), linkName, logger); specErr != nil {
specErrors = multierror.Append(specErrors, specErr)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ func (ctrl *RouteConfigController) processDevicesConfiguration(logger *zap.Logge
}

for _, vlan := range device.Vlans() {
vlanLinkName := fmt.Sprintf("%s.%d", device.Interface(), vlan.ID())
vlanLinkName := nethelpers.VLANLinkName(device.Interface(), vlan.ID())

for _, route := range vlan.Routes() {
routeSpec, err := convert(vlanLinkName, route)
Expand Down
32 changes: 32 additions & 0 deletions pkg/machinery/nethelpers/vlan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package nethelpers

import (
"crypto/sha256"
"fmt"
)

const maxLinkNameLength = 15

// VLANLinkName builds a VLAN link name out of the base device name and VLAN ID.
//
// The function takes care of the maximum length of the link name.
func VLANLinkName(base string, vlanID uint16) string {
// VLAN ID is actually 12-bit, so the allowed values are 0-4095.
// In ".%d" format, vlanID can be up to 5 characters long.
if len(base)+5 <= maxLinkNameLength {
return fmt.Sprintf("%s.%d", base, vlanID)
}

// If the base name is too long, we need to truncate it, but simply
// truncating might lead to ambiguous link name, so take some hash of the original
// name.
prefix := base[:4]

hash := sha256.Sum256([]byte(base))

return fmt.Sprintf("%s%x.%d", prefix, hash[:(maxLinkNameLength-len(prefix)-5)/2], vlanID)
}
70 changes: 70 additions & 0 deletions pkg/machinery/nethelpers/vlan_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package nethelpers_test

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"

"github.com/siderolabs/talos/pkg/machinery/nethelpers"
)

func TestVLANLinkName(t *testing.T) {
t.Parallel()

for _, test := range []struct {
base string
vlanID uint16

expected string
}{
{
base: "eth0",
vlanID: 1,

expected: "eth0.1",
},
{
base: "en9s0",
vlanID: 4095,

expected: "en9s0.4095",
},
{
base: "0123456789",
vlanID: 4095,

expected: "0123456789.4095",
},
{
base: "enx12545f8c99cd",
vlanID: 25,

expected: "enx1ee6413.25",
},
{
base: "enx12545f8c99cd",
vlanID: 4095,

expected: "enx1ee6413.4095",
},
{
base: "enx12545f8c99ce",
vlanID: 4095,

expected: "enx1ef972f.4095",
},
} {
test := test

t.Run(fmt.Sprintf("%s.%d", test.base, test.vlanID), func(t *testing.T) {
t.Parallel()

assert.Equal(t, test.expected, nethelpers.VLANLinkName(test.base, test.vlanID))
})
}
}

0 comments on commit 6058c36

Please sign in to comment.