diff --git a/api/resource/definitions/network/network.proto b/api/resource/definitions/network/network.proto index a9de05949..50c08ff85 100755 --- a/api/resource/definitions/network/network.proto +++ b/api/resource/definitions/network/network.proto @@ -18,6 +18,7 @@ message AddressSpecSpec { uint32 flags = 5; bool announce_with_arp = 6; talos.resource.definitions.enums.NetworkConfigLayer config_layer = 7; + uint32 priority = 8; } // AddressStatusSpec describes status of rendered secrets. @@ -32,6 +33,7 @@ message AddressStatusSpec { talos.resource.definitions.enums.NethelpersFamily family = 8; talos.resource.definitions.enums.NethelpersScope scope = 9; uint32 flags = 10; + uint32 priority = 11; } // BondMasterSpec describes bond settings if Kind == "bond". diff --git a/go.mod b/go.mod index 3f8a61c78..3fb0d6054 100644 --- a/go.mod +++ b/go.mod @@ -107,7 +107,7 @@ require ( github.com/hetznercloud/hcloud-go/v2 v2.21.0 github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 github.com/jeromer/syslogparser v1.1.0 - github.com/jsimonetti/rtnetlink/v2 v2.0.3-0.20241216183107-2d6e9f8ad3f2 + github.com/jsimonetti/rtnetlink/v2 v2.0.3 github.com/jxskiss/base62 v1.1.0 github.com/klauspost/compress v1.18.0 github.com/klauspost/cpuid/v2 v2.2.10 @@ -232,7 +232,7 @@ require ( github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/cilium/ebpf v0.16.0 // indirect + github.com/cilium/ebpf v0.17.3 // indirect github.com/cloudflare/circl v1.6.0 // indirect github.com/containerd/continuity v0.4.4 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect diff --git a/go.sum b/go.sum index a012a54e0..c15594134 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,8 @@ github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHe github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/cilium/ebpf v0.8.1/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk= -github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= -github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= +github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= +github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= @@ -408,8 +408,8 @@ github.com/jsimonetti/rtnetlink v0.0.0-20210525051524-4cc836578190/go.mod h1:NmK github.com/jsimonetti/rtnetlink v0.0.0-20211022192332-93da33804786/go.mod h1:v4hqbTdfQngbVSZJVWUhGE/lbTFf9jb+ygmNUDQMuOs= github.com/jsimonetti/rtnetlink v1.3.5 h1:hVlNQNRlLDGZz31gBPicsG7Q53rnlsz1l1Ix/9XlpVA= github.com/jsimonetti/rtnetlink v1.3.5/go.mod h1:0LFedyiTkebnd43tE4YAkWGIq9jQphow4CcwxaT2Y00= -github.com/jsimonetti/rtnetlink/v2 v2.0.3-0.20241216183107-2d6e9f8ad3f2 h1:4pspWog/mjnfv+B3rjEUfCoFL80T7J8ojK9ay8ApPCM= -github.com/jsimonetti/rtnetlink/v2 v2.0.3-0.20241216183107-2d6e9f8ad3f2/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE= +github.com/jsimonetti/rtnetlink/v2 v2.0.3 h1:Jcp7GTnTPepoUAJ9+LhTa7ZiebvNS56T1GtlEUaPNFE= +github.com/jsimonetti/rtnetlink/v2 v2.0.3/go.mod h1:atIkksp/9fqtf6rpAw45JnttnP2gtuH9X88WPfWfS9A= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw= diff --git a/internal/app/machined/pkg/controllers/network/address_spec.go b/internal/app/machined/pkg/controllers/network/address_spec.go index 84f654a45..2f528cf78 100644 --- a/internal/app/machined/pkg/controllers/network/address_spec.go +++ b/internal/app/machined/pkg/controllers/network/address_spec.go @@ -207,7 +207,7 @@ func (ctrl *AddressSpecController) syncAddress(ctx context.Context, r controller // check if existing matches the spec: if it does, skip update if existing.Scope == uint8(address.TypedSpec().Scope) && existing.Flags == uint8(address.TypedSpec().Flags) && - existing.Attributes.Flags == uint32(address.TypedSpec().Flags) { + existing.Attributes.Flags == uint32(address.TypedSpec().Flags) && existing.Attributes.Priority == address.TypedSpec().Priority { return nil } @@ -218,6 +218,8 @@ func (ctrl *AddressSpecController) syncAddress(ctx context.Context, r controller zap.Stringer("new_scope", address.TypedSpec().Scope), zap.Stringer("old_flags", nethelpers.AddressFlags(existing.Attributes.Flags)), zap.Stringer("new_flags", address.TypedSpec().Flags), + zap.Uint32("old_priority", existing.Attributes.Priority), + zap.Uint32("new_priority", address.TypedSpec().Priority), ) // delete address to get new one assigned below @@ -240,6 +242,7 @@ func (ctrl *AddressSpecController) syncAddress(ctx context.Context, r controller Local: address.TypedSpec().Address.Addr().AsSlice(), Broadcast: broadcastAddr(address.TypedSpec().Address), Flags: uint32(address.TypedSpec().Flags), + Priority: address.TypedSpec().Priority, }, }); err != nil { // ignore EEXIST error diff --git a/internal/app/machined/pkg/controllers/network/address_spec_test.go b/internal/app/machined/pkg/controllers/network/address_spec_test.go index 9e1817c15..9752c542f 100644 --- a/internal/app/machined/pkg/controllers/network/address_spec_test.go +++ b/internal/app/machined/pkg/controllers/network/address_spec_test.go @@ -6,86 +6,48 @@ package network_test import ( - "context" "fmt" "math/rand/v2" "net" "net/netip" "os" - "sync" "testing" "time" - "github.com/cosi-project/runtime/pkg/controller/runtime" "github.com/cosi-project/runtime/pkg/resource" "github.com/cosi-project/runtime/pkg/state" - "github.com/cosi-project/runtime/pkg/state/impl/inmem" - "github.com/cosi-project/runtime/pkg/state/impl/namespaced" "github.com/jsimonetti/rtnetlink/v2" - "github.com/siderolabs/go-retry/retry" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" - "go.uber.org/zap/zaptest" "golang.org/x/sys/unix" + "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/ctest" netctrl "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/network" "github.com/siderolabs/talos/pkg/machinery/nethelpers" "github.com/siderolabs/talos/pkg/machinery/resources/network" ) type AddressSpecSuite struct { - suite.Suite - - state state.State - - runtime *runtime.Runtime - wg sync.WaitGroup - - ctx context.Context //nolint:containedctx - ctxCancel context.CancelFunc -} - -func (suite *AddressSpecSuite) SetupTest() { - suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 3*time.Minute) - - suite.state = state.WrapCore(namespaced.NewState(inmem.Build)) - - var err error - - suite.runtime, err = runtime.NewRuntime(suite.state, zaptest.NewLogger(suite.T())) - suite.Require().NoError(err) - - suite.Require().NoError(suite.runtime.RegisterController(&netctrl.AddressSpecController{})) - - suite.startRuntime() + ctest.DefaultSuite } func (suite *AddressSpecSuite) uniqueDummyInterface() string { return fmt.Sprintf("dummy%02x%02x%02x", rand.Int32()&0xff, rand.Int32()&0xff, rand.Int32()&0xff) } -func (suite *AddressSpecSuite) startRuntime() { - suite.wg.Add(1) - - go func() { - defer suite.wg.Done() - - suite.Assert().NoError(suite.runtime.Run(suite.ctx)) - }() -} - -func (suite *AddressSpecSuite) assertLinkAddress(linkName, address string) error { +func assertLinkAddress(asrt *assert.Assertions, linkName, address string) { addr := netip.MustParsePrefix(address) iface, err := net.InterfaceByName(linkName) - suite.Require().NoError(err) + asrt.NoError(err) conn, err := rtnetlink.Dial(nil) - suite.Require().NoError(err) + asrt.NoError(err) defer conn.Close() //nolint:errcheck linkAddresses, err := conn.Address.List() - suite.Require().NoError(err) + asrt.NoError(err) for _, linkAddress := range linkAddresses { if linkAddress.Index != uint32(iface.Index) { @@ -100,33 +62,31 @@ func (suite *AddressSpecSuite) assertLinkAddress(linkName, address string) error continue } - return nil + return } - return retry.ExpectedErrorf("address %s not found on %q", addr, linkName) + asrt.Failf("address not found", "address %s not found on %q", addr, linkName) } -func (suite *AddressSpecSuite) assertNoLinkAddress(linkName, address string) error { +func assertNoLinkAddress(asrt *assert.Assertions, linkName, address string) { addr := netip.MustParsePrefix(address) iface, err := net.InterfaceByName(linkName) - suite.Require().NoError(err) + asrt.NoError(err) conn, err := rtnetlink.Dial(nil) - suite.Require().NoError(err) + asrt.NoError(err) defer conn.Close() //nolint:errcheck linkAddresses, err := conn.Address.List() - suite.Require().NoError(err) + asrt.NoError(err) for _, linkAddress := range linkAddresses { if linkAddress.Index == uint32(iface.Index) && int(linkAddress.PrefixLength) == addr.Bits() && linkAddress.Attributes.Address.Equal(addr.Addr().AsSlice()) { - return retry.ExpectedErrorf("address %s is assigned to %q", addr, linkName) + asrt.Failf("address is still there", "address %s is assigned to %q", addr, linkName) } } - - return nil } func (suite *AddressSpecSuite) TestLoopback() { @@ -141,33 +101,26 @@ func (suite *AddressSpecSuite) TestLoopback() { } for _, res := range []resource.Resource{loopback} { - suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec()) + suite.Create(res) } - suite.Assert().NoError( - retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry( - func() error { - return suite.assertLinkAddress("lo", "127.11.0.1/32") - }, - ), - ) + suite.Assert().EventuallyWithT(func(collect *assert.CollectT) { + assertLinkAddress(assert.New(collect), "lo", "127.11.0.1/32") + }, 3*time.Second, 10*time.Millisecond) // teardown the address - for { - ready, err := suite.state.Teardown(suite.ctx, loopback.Metadata()) - suite.Require().NoError(err) + _, err := suite.State().Teardown(suite.Ctx(), loopback.Metadata()) + suite.Require().NoError(err) - if ready { - break - } - - time.Sleep(100 * time.Millisecond) - } + _, err = suite.State().WatchFor(suite.Ctx(), loopback.Metadata(), state.WithFinalizerEmpty()) + suite.Require().NoError(err) // torn down address should be removed immediately - suite.Assert().NoError(suite.assertNoLinkAddress("lo", "127.11.0.1/32")) + suite.Assert().EventuallyWithT(func(collect *assert.CollectT) { + assertNoLinkAddress(assert.New(collect), "lo", "127.11.0.1/32") + }, 3*time.Second, 10*time.Millisecond) - suite.Require().NoError(suite.state.Destroy(suite.ctx, loopback.Metadata())) + suite.Destroy(loopback) } func (suite *AddressSpecSuite) TestDummy() { @@ -190,7 +143,7 @@ func (suite *AddressSpecSuite) TestDummy() { // it's fine to create the address before the interface is actually created for _, res := range []resource.Resource{dummy} { - suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec()) + suite.Create(res) } // create dummy interface @@ -214,28 +167,21 @@ func (suite *AddressSpecSuite) TestDummy() { defer conn.Link.Delete(uint32(iface.Index)) //nolint:errcheck - suite.Assert().NoError( - retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry( - func() error { - return suite.assertLinkAddress(dummyInterface, "10.0.0.1/8") - }, - ), - ) + suite.Assert().EventuallyWithT(func(collect *assert.CollectT) { + assertLinkAddress(assert.New(collect), dummyInterface, "10.0.0.1/8") + }, 3*time.Second, 10*time.Millisecond) // delete dummy interface, address should be unassigned automatically suite.Require().NoError(conn.Link.Delete(uint32(iface.Index))) // teardown the address - for { - ready, err := suite.state.Teardown(suite.ctx, dummy.Metadata()) - suite.Require().NoError(err) + _, err = suite.State().Teardown(suite.Ctx(), dummy.Metadata()) + suite.Require().NoError(err) - if ready { - break - } + _, err = suite.State().WatchFor(suite.Ctx(), dummy.Metadata(), state.WithFinalizerEmpty()) + suite.Require().NoError(err) - time.Sleep(100 * time.Millisecond) - } + suite.Destroy(dummy) } func (suite *AddressSpecSuite) TestDummyAlias() { @@ -261,7 +207,7 @@ func (suite *AddressSpecSuite) TestDummyAlias() { // it's fine to create the address before the interface is actually created for _, res := range []resource.Resource{dummy} { - suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec()) + suite.Create(res) } // create dummy interface @@ -297,27 +243,24 @@ func (suite *AddressSpecSuite) TestDummyAlias() { defer conn.Link.Delete(uint32(iface.Index)) //nolint:errcheck - suite.Assert().NoError( - retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry( - func() error { - return suite.assertLinkAddress(dummyInterface, "10.0.0.5/8") - }, - ), - ) -} - -func (suite *AddressSpecSuite) TearDownTest() { - suite.T().Log("tear down") - - suite.ctxCancel() - - suite.wg.Wait() + suite.Assert().EventuallyWithT(func(collect *assert.CollectT) { + assertLinkAddress(assert.New(collect), dummyInterface, "10.0.0.5/8") + }, 3*time.Second, 10*time.Millisecond) } func TestAddressSpecSuite(t *testing.T) { + t.Parallel() + if os.Geteuid() != 0 { t.Skip("requires root") } - suite.Run(t, new(AddressSpecSuite)) + suite.Run(t, &AddressSpecSuite{ + DefaultSuite: ctest.DefaultSuite{ + Timeout: 10 * time.Second, + AfterSetup: func(suite *ctest.DefaultSuite) { + suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.AddressSpecController{})) + }, + }, + }) } diff --git a/internal/app/machined/pkg/controllers/network/address_status.go b/internal/app/machined/pkg/controllers/network/address_status.go index 812015a0b..8ce671193 100644 --- a/internal/app/machined/pkg/controllers/network/address_status.go +++ b/internal/app/machined/pkg/controllers/network/address_status.go @@ -112,6 +112,7 @@ func (ctrl *AddressStatusController) Run(ctx context.Context, r controller.Runti status.Family = nethelpers.Family(addr.Family) status.Scope = nethelpers.Scope(addr.Scope) status.Flags = nethelpers.AddressFlags(addr.Attributes.Flags) + status.Priority = addr.Attributes.Priority return nil }); err != nil { diff --git a/internal/app/machined/pkg/controllers/network/address_status_test.go b/internal/app/machined/pkg/controllers/network/address_status_test.go index b5a02f721..7c8e7c15a 100644 --- a/internal/app/machined/pkg/controllers/network/address_status_test.go +++ b/internal/app/machined/pkg/controllers/network/address_status_test.go @@ -6,78 +6,34 @@ package network_test import ( - "context" - "sync" "testing" "time" - "github.com/cosi-project/runtime/pkg/controller/runtime" - "github.com/cosi-project/runtime/pkg/state" - "github.com/cosi-project/runtime/pkg/state/impl/inmem" - "github.com/cosi-project/runtime/pkg/state/impl/namespaced" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" - "go.uber.org/zap/zaptest" + "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/ctest" netctrl "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/network" "github.com/siderolabs/talos/pkg/machinery/resources/network" ) type AddressStatusSuite struct { - suite.Suite - - state state.State - - runtime *runtime.Runtime - wg sync.WaitGroup - - ctx context.Context //nolint:containedctx - ctxCancel context.CancelFunc -} - -func (suite *AddressStatusSuite) SetupTest() { - suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 3*time.Minute) - - suite.state = state.WrapCore(namespaced.NewState(inmem.Build)) - - var err error - - suite.runtime, err = runtime.NewRuntime(suite.state, zaptest.NewLogger(suite.T())) - suite.Require().NoError(err) - - suite.Require().NoError(suite.runtime.RegisterController(&netctrl.AddressStatusController{})) - - suite.startRuntime() -} - -func (suite *AddressStatusSuite) startRuntime() { - suite.wg.Add(1) - - go func() { - defer suite.wg.Done() - - suite.Assert().NoError(suite.runtime.Run(suite.ctx)) - }() -} - -func (suite *AddressStatusSuite) assertAddresses(requiredIDs []string, check func(*network.AddressStatus, *assert.Assertions)) { - assertResources(suite.ctx, suite.T(), suite.state, requiredIDs, check) + ctest.DefaultSuite } func (suite *AddressStatusSuite) TestLoopback() { - suite.assertAddresses( - []string{"lo/127.0.0.1/8"}, func(r *network.AddressStatus, asrt *assert.Assertions) {}, - ) -} - -func (suite *AddressStatusSuite) TearDownTest() { - suite.T().Log("tear down") - - suite.ctxCancel() - - suite.wg.Wait() + ctest.AssertResource(suite, "lo/127.0.0.1/8", func(r *network.AddressStatus, asrt *assert.Assertions) {}) } func TestAddressStatusSuite(t *testing.T) { - suite.Run(t, new(AddressStatusSuite)) + t.Parallel() + + suite.Run(t, &AddressStatusSuite{ + DefaultSuite: ctest.DefaultSuite{ + Timeout: 10 * time.Second, + AfterSetup: func(suite *ctest.DefaultSuite) { + suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.AddressStatusController{})) + }, + }, + }) } diff --git a/internal/app/machined/pkg/controllers/network/nftables_chain_test.go b/internal/app/machined/pkg/controllers/network/nftables_chain_test.go index d96092246..98ce5d188 100644 --- a/internal/app/machined/pkg/controllers/network/nftables_chain_test.go +++ b/internal/app/machined/pkg/controllers/network/nftables_chain_test.go @@ -8,6 +8,7 @@ import ( "net/netip" "os" "os/exec" + "slices" "strings" "testing" "time" @@ -33,23 +34,24 @@ func (s *NfTablesChainSuite) nftOutput() string { return string(out) } -func (s *NfTablesChainSuite) checkNftOutput(expected string) { +func (s *NfTablesChainSuite) checkNftOutput(expected ...string) { s.T().Helper() var prevOutput string s.Eventually(func() bool { output := s.nftOutput() + matches := slices.Contains(expected, strings.TrimSpace(output)) if output != prevOutput { - if strings.TrimSpace(output) != expected { + if !matches { s.T().Logf("nft list table inet talos-test:\n%s", output) } prevOutput = output } - return strings.TrimSpace(output) == expected + return matches }, 5*time.Second, 100*time.Millisecond) } @@ -351,12 +353,19 @@ func (s *NfTablesChainSuite) TestClampMSS() { s.Require().NoError(s.State().Create(s.Ctx(), chain)) + // several versions here for different version of `nft` CLI decoding the rules s.checkNftOutput(`table inet talos-test { chain test1 { type filter hook input priority filter; policy accept; meta nfproto ipv4 tcp flags syn / syn,rst tcp option maxseg size > 1380 tcp option maxseg size set 1380 meta nfproto ipv6 tcp flags syn / syn,rst tcp option maxseg size > 1360 tcp option maxseg size set 1360 } +}`, `table inet talos-test { + chain test1 { + type filter hook input priority filter; policy accept; + meta nfproto ipv4 tcp flags & (syn | rst) == syn tcp option maxseg size > 1380 tcp option maxseg size set 1380 + meta nfproto ipv6 tcp flags & (syn | rst) == syn tcp option maxseg size > 1360 tcp option maxseg size set 1360 + } }`) } diff --git a/internal/app/machined/pkg/controllers/network/operator/dhcp4.go b/internal/app/machined/pkg/controllers/network/operator/dhcp4.go index cfc4e77f5..7aa70959c 100644 --- a/internal/app/machined/pkg/controllers/network/operator/dhcp4.go +++ b/internal/app/machined/pkg/controllers/network/operator/dhcp4.go @@ -311,6 +311,7 @@ func (d *DHCP4) parseNetworkConfigFromAck(ack *dhcpv4.DHCPv4, useHostname bool) Family: nethelpers.FamilyInet4, Scope: nethelpers.ScopeGlobal, Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent), + Priority: d.routeMetric, ConfigLayer: network.ConfigOperator, }, } diff --git a/pkg/machinery/api/resource/definitions/network/network.pb.go b/pkg/machinery/api/resource/definitions/network/network.pb.go index 4d9fb00f1..c0609828c 100644 --- a/pkg/machinery/api/resource/definitions/network/network.pb.go +++ b/pkg/machinery/api/resource/definitions/network/network.pb.go @@ -36,6 +36,7 @@ type AddressSpecSpec struct { Flags uint32 `protobuf:"varint,5,opt,name=flags,proto3" json:"flags,omitempty"` AnnounceWithArp bool `protobuf:"varint,6,opt,name=announce_with_arp,json=announceWithArp,proto3" json:"announce_with_arp,omitempty"` ConfigLayer enums.NetworkConfigLayer `protobuf:"varint,7,opt,name=config_layer,json=configLayer,proto3,enum=talos.resource.definitions.enums.NetworkConfigLayer" json:"config_layer,omitempty"` + Priority uint32 `protobuf:"varint,8,opt,name=priority,proto3" json:"priority,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -119,6 +120,13 @@ func (x *AddressSpecSpec) GetConfigLayer() enums.NetworkConfigLayer { return enums.NetworkConfigLayer(0) } +func (x *AddressSpecSpec) GetPriority() uint32 { + if x != nil { + return x.Priority + } + return 0 +} + // AddressStatusSpec describes status of rendered secrets. type AddressStatusSpec struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -132,6 +140,7 @@ type AddressStatusSpec struct { Family enums.NethelpersFamily `protobuf:"varint,8,opt,name=family,proto3,enum=talos.resource.definitions.enums.NethelpersFamily" json:"family,omitempty"` Scope enums.NethelpersScope `protobuf:"varint,9,opt,name=scope,proto3,enum=talos.resource.definitions.enums.NethelpersScope" json:"scope,omitempty"` Flags uint32 `protobuf:"varint,10,opt,name=flags,proto3" json:"flags,omitempty"` + Priority uint32 `protobuf:"varint,11,opt,name=priority,proto3" json:"priority,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -236,6 +245,13 @@ func (x *AddressStatusSpec) GetFlags() uint32 { return 0 } +func (x *AddressStatusSpec) GetPriority() uint32 { + if x != nil { + return x.Priority + } + return 0 +} + // BondMasterSpec describes bond settings if Kind == "bond". type BondMasterSpec struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -4330,7 +4346,7 @@ var File_resource_definitions_network_network_proto protoreflect.FileDescriptor const file_resource_definitions_network_network_proto_rawDesc = "" + "\n" + - "*resource/definitions/network/network.proto\x12\"talos.resource.definitions.network\x1a\x13common/common.proto\x1a\x1egoogle/protobuf/duration.proto\x1a&resource/definitions/enums/enums.proto\"\x8d\x03\n" + + "*resource/definitions/network/network.proto\x12\"talos.resource.definitions.network\x1a\x13common/common.proto\x1a\x1egoogle/protobuf/duration.proto\x1a&resource/definitions/enums/enums.proto\"\xa9\x03\n" + "\x0fAddressSpecSpec\x12-\n" + "\aaddress\x18\x01 \x01(\v2\x13.common.NetIPPrefixR\aaddress\x12\x1b\n" + "\tlink_name\x18\x02 \x01(\tR\blinkName\x12J\n" + @@ -4338,7 +4354,8 @@ const file_resource_definitions_network_network_proto_rawDesc = "" + "\x05scope\x18\x04 \x01(\x0e21.talos.resource.definitions.enums.NethelpersScopeR\x05scope\x12\x14\n" + "\x05flags\x18\x05 \x01(\rR\x05flags\x12*\n" + "\x11announce_with_arp\x18\x06 \x01(\bR\x0fannounceWithArp\x12W\n" + - "\fconfig_layer\x18\a \x01(\x0e24.talos.resource.definitions.enums.NetworkConfigLayerR\vconfigLayer\"\xd1\x03\n" + + "\fconfig_layer\x18\a \x01(\x0e24.talos.resource.definitions.enums.NetworkConfigLayerR\vconfigLayer\x12\x1a\n" + + "\bpriority\x18\b \x01(\rR\bpriority\"\xed\x03\n" + "\x11AddressStatusSpec\x12-\n" + "\aaddress\x18\x01 \x01(\v2\x13.common.NetIPPrefixR\aaddress\x12#\n" + "\x05local\x18\x02 \x01(\v2\r.common.NetIPR\x05local\x12+\n" + @@ -4351,7 +4368,8 @@ const file_resource_definitions_network_network_proto_rawDesc = "" + "\x06family\x18\b \x01(\x0e22.talos.resource.definitions.enums.NethelpersFamilyR\x06family\x12G\n" + "\x05scope\x18\t \x01(\x0e21.talos.resource.definitions.enums.NethelpersScopeR\x05scope\x12\x14\n" + "\x05flags\x18\n" + - " \x01(\rR\x05flags\"\xa4\n" + + " \x01(\rR\x05flags\x12\x1a\n" + + "\bpriority\x18\v \x01(\rR\bpriority\"\xa4\n" + "\n" + "\x0eBondMasterSpec\x12H\n" + "\x04mode\x18\x01 \x01(\x0e24.talos.resource.definitions.enums.NethelpersBondModeR\x04mode\x12_\n" + diff --git a/pkg/machinery/api/resource/definitions/network/network_vtproto.pb.go b/pkg/machinery/api/resource/definitions/network/network_vtproto.pb.go index 6ac472946..561b85dd6 100644 --- a/pkg/machinery/api/resource/definitions/network/network_vtproto.pb.go +++ b/pkg/machinery/api/resource/definitions/network/network_vtproto.pb.go @@ -56,6 +56,11 @@ func (m *AddressSpecSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Priority != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Priority)) + i-- + dAtA[i] = 0x40 + } if m.ConfigLayer != 0 { i = protohelpers.EncodeVarint(dAtA, i, uint64(m.ConfigLayer)) i-- @@ -148,6 +153,11 @@ func (m *AddressStatusSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Priority != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Priority)) + i-- + dAtA[i] = 0x58 + } if m.Flags != 0 { i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Flags)) i-- @@ -4273,6 +4283,9 @@ func (m *AddressSpecSpec) SizeVT() (n int) { if m.ConfigLayer != 0 { n += 1 + protohelpers.SizeOfVarint(uint64(m.ConfigLayer)) } + if m.Priority != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Priority)) + } n += len(m.unknownFields) return n } @@ -4349,6 +4362,9 @@ func (m *AddressStatusSpec) SizeVT() (n int) { if m.Flags != 0 { n += 1 + protohelpers.SizeOfVarint(uint64(m.Flags)) } + if m.Priority != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Priority)) + } n += len(m.unknownFields) return n } @@ -6139,6 +6155,25 @@ func (m *AddressSpecSpec) UnmarshalVT(dAtA []byte) error { break } } + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) + } + m.Priority = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Priority |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -6518,6 +6553,25 @@ func (m *AddressStatusSpec) UnmarshalVT(dAtA []byte) error { break } } + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) + } + m.Priority = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Priority |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/pkg/machinery/go.mod b/pkg/machinery/go.mod index 4e70dbe3a..d9d2dbc4c 100644 --- a/pkg/machinery/go.mod +++ b/pkg/machinery/go.mod @@ -23,7 +23,7 @@ require ( github.com/google/cel-go v0.24.1 github.com/hashicorp/go-multierror v1.1.1 github.com/hexops/gotextdiff v1.0.3 - github.com/jsimonetti/rtnetlink/v2 v2.0.3-0.20241216183107-2d6e9f8ad3f2 + github.com/jsimonetti/rtnetlink/v2 v2.0.3 github.com/mdlayher/ethtool v0.4.0 github.com/opencontainers/runtime-spec v1.2.1 github.com/planetscale/vtprotobuf v0.6.1-0.20241121165744-79df5c4772f2 diff --git a/pkg/machinery/go.sum b/pkg/machinery/go.sum index 0290c2245..dfeb3319d 100644 --- a/pkg/machinery/go.sum +++ b/pkg/machinery/go.sum @@ -16,8 +16,8 @@ github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4= -github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM= +github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= +github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/containerd/go-cni v1.1.12 h1:wm/5VD/i255hjM4uIZjBRiEQ7y98W9ACy/mHeLi4+94= @@ -69,8 +69,8 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= -github.com/jsimonetti/rtnetlink/v2 v2.0.3-0.20241216183107-2d6e9f8ad3f2 h1:4pspWog/mjnfv+B3rjEUfCoFL80T7J8ojK9ay8ApPCM= -github.com/jsimonetti/rtnetlink/v2 v2.0.3-0.20241216183107-2d6e9f8ad3f2/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE= +github.com/jsimonetti/rtnetlink/v2 v2.0.3 h1:Jcp7GTnTPepoUAJ9+LhTa7ZiebvNS56T1GtlEUaPNFE= +github.com/jsimonetti/rtnetlink/v2 v2.0.3/go.mod h1:atIkksp/9fqtf6rpAw45JnttnP2gtuH9X88WPfWfS9A= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= diff --git a/pkg/machinery/resources/network/address_spec.go b/pkg/machinery/resources/network/address_spec.go index 44d1d7864..73eb44fdb 100644 --- a/pkg/machinery/resources/network/address_spec.go +++ b/pkg/machinery/resources/network/address_spec.go @@ -34,6 +34,7 @@ type AddressSpecSpec struct { Scope nethelpers.Scope `yaml:"scope" protobuf:"4"` Flags nethelpers.AddressFlags `yaml:"flags" protobuf:"5"` AnnounceWithARP bool `yaml:"announceWithARP,omitempty" protobuf:"6"` + Priority uint32 `yaml:"priority,omitempty" protobuf:"8"` ConfigLayer ConfigLayer `yaml:"layer" protobuf:"7"` } diff --git a/pkg/machinery/resources/network/address_status.go b/pkg/machinery/resources/network/address_status.go index 1bf8dc0bb..aaf50f084 100644 --- a/pkg/machinery/resources/network/address_status.go +++ b/pkg/machinery/resources/network/address_status.go @@ -36,6 +36,7 @@ type AddressStatusSpec struct { Family nethelpers.Family `yaml:"family" protobuf:"8"` Scope nethelpers.Scope `yaml:"scope" protobuf:"9"` Flags nethelpers.AddressFlags `yaml:"flags" protobuf:"10"` + Priority uint32 `yaml:"priority" protobuf:"11"` } // NewAddressStatus initializes a AddressStatus resource. diff --git a/website/content/v1.10/reference/api.md b/website/content/v1.10/reference/api.md index fad3e4091..332a30064 100644 --- a/website/content/v1.10/reference/api.md +++ b/website/content/v1.10/reference/api.md @@ -3702,6 +3702,7 @@ AddressSpecSpec describes status of rendered secrets. | flags | [uint32](#uint32) | | | | announce_with_arp | [bool](#bool) | | | | config_layer | [talos.resource.definitions.enums.NetworkConfigLayer](#talos.resource.definitions.enums.NetworkConfigLayer) | | | +| priority | [uint32](#uint32) | | | @@ -3726,6 +3727,7 @@ AddressStatusSpec describes status of rendered secrets. | family | [talos.resource.definitions.enums.NethelpersFamily](#talos.resource.definitions.enums.NethelpersFamily) | | | | scope | [talos.resource.definitions.enums.NethelpersScope](#talos.resource.definitions.enums.NethelpersScope) | | | | flags | [uint32](#uint32) | | | +| priority | [uint32](#uint32) | | |