fix: incorrect route source for on-link routes

when processing on-link routes, the source address was incorrectly set to the first address of the interface.
This caused issues when the interface had multiple addresses, as the source address may not have been valid for the route.
The source address is now set to an empty string, which allows the kernel to automatically select the appropriate source address for the route.

Signed-off-by: Orzelius <33936483+Orzelius@users.noreply.github.com>
(cherry picked from commit 3400059ccf4811140a4326397d972f68693c708c)
This commit is contained in:
Orzelius 2026-03-25 21:25:56 +01:00 committed by Andrey Smirnov
parent a8f2a0af70
commit fcdfeab2ba
No known key found for this signature in database
GPG Key ID: 322C6F63F594CE7C
5 changed files with 127 additions and 10 deletions

View File

@ -101,7 +101,7 @@ type Ethernet struct {
OnLink bool `yaml:"on-link,omitempty"`
} `yaml:"routes,omitempty"`
RoutingPolicy []struct { // TODO
From string `yaml:"froom,omitempty"`
From string `yaml:"from,omitempty"`
Table uint32 `yaml:"table,omitempty"`
} `yaml:"routing-policy,omitempty"`
}
@ -733,17 +733,10 @@ func applyNetworkConfigV2Ethernet(name string, eth Ethernet, networkConfig *runt
networkConfig.Routes = append(networkConfig.Routes, routeSpec)
if route.OnLink && gw.Is4() {
// This assumes an interface with multiple routes will never have multiple statically set ips.
ipPrefix, err := netip.ParsePrefix(eth.Address[0])
if err != nil {
return fmt.Errorf("failed to parse route source: %w", err)
}
if route.OnLink {
routeSpec := network.RouteSpecSpec{
ConfigLayer: network.ConfigPlatform,
Destination: netip.PrefixFrom(gw, gw.BitLen()),
Source: ipPrefix.Addr(),
OutLinkName: name,
Scope: nethelpers.ScopeLink,
Table: withDefault(nethelpers.RoutingTable(route.Table), nethelpers.TableMain),
@ -753,6 +746,10 @@ func applyNetworkConfigV2Ethernet(name string, eth Ethernet, networkConfig *runt
Priority: withDefault(route.Metric, network.DefaultRouteMetric),
}
if gw.Is6() {
routeSpec.Family = nethelpers.FamilyInet6
}
networkConfig.Routes = append(networkConfig.Routes, routeSpec)
}
}

View File

@ -40,6 +40,9 @@ var rawNetworkConfigV2CloudInit []byte
//go:embed testdata/in-v2-serverscom.yaml
var rawNetworkConfigV2Serverscom []byte
//go:embed testdata/in-v2-nocloud-ipv6-on-link.yaml
var rawNetworkConfigV2NocloudIPv6OnLink []byte
//go:embed testdata/expected-v1.yaml
var expectedNetworkConfigV1 string
@ -52,6 +55,9 @@ var expectedNetworkConfigV2 string
//go:embed testdata/expected-v2-serverscom.yaml
var expectedNetworkConfigV2Serverscom string
//go:embed testdata/expected-v2-nocloud-ipv6-on-link.yaml
var expectedNetworkConfigV2NocloudIPv6OnLink string
func TestParseNetworkConfig(t *testing.T) {
t.Parallel()
@ -89,6 +95,12 @@ func TestParseNetworkConfig(t *testing.T) {
raw: rawNetworkConfigV2Serverscom,
expected: expectedNetworkConfigV2Serverscom,
},
{
name: "V2-nocloud-ipv6-on-link",
raw: rawNetworkConfigV2NocloudIPv6OnLink,
expected: expectedNetworkConfigV2NocloudIPv6OnLink,
expectedNeedsRecocile: true,
},
} {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

View File

@ -0,0 +1,87 @@
addresses:
- address: 2a0c:6ec0:b00:c:0:1::/96
linkName: nic0
family: inet6
scope: global
flags: permanent
layer: platform
- address: 10.0.0.0/32
linkName: nic0
family: inet4
scope: global
flags: permanent
layer: platform
links:
- name: nic0
logical: false
up: true
mtu: 0
kind: ""
type: netrom
layer: platform
routes:
- family: inet4
dst: ""
src: ""
gateway: 169.254.0.1
outLinkName: nic0
table: main
priority: 1024
scope: global
type: unicast
flags: ""
protocol: static
layer: platform
- family: inet4
dst: 169.254.0.1/32
src: ""
gateway: ""
outLinkName: nic0
table: main
priority: 1024
scope: link
type: unicast
flags: ""
protocol: static
layer: platform
- family: inet6
dst: ""
src: ""
gateway: fe80::1
outLinkName: nic0
table: main
priority: 2048
scope: global
type: unicast
flags: ""
protocol: static
layer: platform
- family: inet6
dst: fe80::1/128
src: ""
gateway: ""
outLinkName: nic0
table: main
priority: 1024
scope: link
type: unicast
flags: ""
protocol: static
layer: platform
hostnames:
- hostname: talos
domainname: fqdn
layer: platform
resolvers:
- dnsServers:
- 1.1.1.1
- 2606:4700:4700::1111
layer: platform
timeServers: []
operators: []
externalIPs: []
metadata:
platform: nocloud
hostname: talos.fqdn
instanceId: "0"
internalDNS: talos.fqdn

View File

@ -137,7 +137,7 @@ routes:
layer: platform
- family: inet4
dst: 192.168.14.1/32
src: 10.22.14.2
src: ""
gateway: ""
outLinkName: eth1
table: main

View File

@ -0,0 +1,21 @@
version: 2
ethernets:
nic0:
match:
macaddress: "02:xx:xx:xx:xx:xx"
dhcp4: false
dhcp6: false
addresses:
- 2a0c:6ec0:b00:c:0:1::/96
- 10.0.0.0/32
routes:
- to: 0.0.0.0/0
via: 169.254.0.1
on-link: true
- to: ::/0
via: fe80::1
on-link: true
nameservers:
addresses:
- 1.1.1.1
- 2606:4700:4700::1111