Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ All notable changes to this project will be documented in this file.
- Reject BGP martian addresses (CGNAT, multicast, reserved, benchmarking, etc.) as client IP during `connect`
- Controller
- detect duplicate (UnderlaySrcIP, UnderlayDstIP) pairs for tunnels and only render the first to the device config and write a log error for the second
- allow MTU to be configurable
- Onchain Programs
- Serviceability: skip field validation for users in `Deleting` status to prevent accounts from getting stuck during cleanup when validation rules change
- Serviceability: require foundation_allowlist privileges to update node_segment_idx on a device interface
Expand Down
3 changes: 3 additions & 0 deletions controlplane/controller/internal/controller/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type Interface struct {
VlanId uint16
Ip netip.Prefix
NodeSegmentIdx uint16
Mtu uint16
IsSubInterface bool
IsSubInterfaceParent bool
InterfaceType InterfaceType
Expand Down Expand Up @@ -91,6 +92,7 @@ func toInterface(iface serviceability.Interface) (Interface, error) {
VlanId: iface.VlanId,
Ip: prefix,
NodeSegmentIdx: iface.NodeSegmentIdx,
Mtu: iface.Mtu,
IsSubInterface: subIntf,
IsSubInterfaceParent: false,
InterfaceType: ifType,
Expand Down Expand Up @@ -151,6 +153,7 @@ func (i Interface) GetParent() (Interface, error) {
}
return Interface{
Name: parentName,
Mtu: i.Mtu,
IsSubInterface: false,
IsSubInterfaceParent: true,
InterfaceType: i.InterfaceType,
Expand Down
14 changes: 14 additions & 0 deletions controlplane/controller/internal/controller/render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,20 +448,23 @@ func TestRenderConfig(t *testing.T) {
{
Name: "Switch1/1/1",
Ip: netip.MustParsePrefix("172.16.0.0/31"),
Mtu: 2048,
InterfaceType: InterfaceTypePhysical,
Metric: 40000,
IsLink: true,
LinkStatus: serviceability.LinkStatusActivated,
},
{
Name: "Switch1/1/2",
Mtu: 2048,
IsSubInterfaceParent: true,
InterfaceType: InterfaceTypePhysical,
},
{
Name: "Switch1/1/2.100",
Ip: netip.MustParsePrefix("172.16.0.2/31"),
VlanId: 100,
Mtu: 2048,
IsSubInterface: true,
InterfaceType: InterfaceTypePhysical,
Metric: 0,
Expand All @@ -471,6 +474,7 @@ func TestRenderConfig(t *testing.T) {
Name: "Switch1/1/2.200",
Ip: netip.MustParsePrefix("172.16.0.6/31"),
VlanId: 200,
Mtu: 2048,
IsSubInterface: true,
InterfaceType: InterfaceTypePhysical,
Metric: 40000, // Metric w/ IsLink false should not render isis config
Expand All @@ -480,6 +484,7 @@ func TestRenderConfig(t *testing.T) {
Name: "Switch1/1/2.300",
Ip: netip.MustParsePrefix("172.16.0.8/31"),
VlanId: 300,
Mtu: 2048,
IsSubInterface: true,
InterfaceType: InterfaceTypePhysical,
Metric: 40000,
Expand All @@ -489,6 +494,7 @@ func TestRenderConfig(t *testing.T) {
{
Name: "Vlan4001",
Ip: netip.MustParsePrefix("172.16.0.4/31"),
Mtu: 2048,
InterfaceType: InterfaceTypePhysical,
Metric: 10000,
IsLink: true,
Expand All @@ -497,6 +503,7 @@ func TestRenderConfig(t *testing.T) {
{
Name: "Switch1/1/3",
Ip: netip.MustParsePrefix("172.16.0.10/31"),
Mtu: 2048,
InterfaceType: InterfaceTypePhysical,
Metric: 1000000,
IsLink: true,
Expand All @@ -505,6 +512,7 @@ func TestRenderConfig(t *testing.T) {
{
Name: "Switch1/1/4",
Ip: netip.MustParsePrefix("172.16.0.12/31"),
Mtu: 2048,
InterfaceType: InterfaceTypePhysical,
Metric: 30000,
IsLink: true,
Expand All @@ -513,6 +521,7 @@ func TestRenderConfig(t *testing.T) {
{
Name: "Switch1/1/5",
Ip: netip.MustParsePrefix("172.16.0.14/31"),
Mtu: 2048,
InterfaceType: InterfaceTypePhysical,
Metric: 20000,
IsLink: true,
Expand All @@ -522,6 +531,7 @@ func TestRenderConfig(t *testing.T) {
{
Name: "Switch1/1/6",
Ip: netip.MustParsePrefix("172.16.0.16/31"),
Mtu: 2048,
InterfaceType: InterfaceTypePhysical,
Metric: 25000,
IsLink: true,
Expand Down Expand Up @@ -562,13 +572,15 @@ func TestRenderConfig(t *testing.T) {
Name: "Ethernet1/1",
InterfaceType: InterfaceTypePhysical,
Ip: netip.MustParsePrefix("172.16.0.2/31"),
Mtu: 2048,
Metric: 40000,
IsLink: true,
},
{
Name: "Ethernet1/2",
InterfaceType: InterfaceTypePhysical,
Ip: netip.MustParsePrefix("172.16.0.4/31"),
Mtu: 2048,
},
},
Vpn4vLoopbackIntfName: "Loopback255",
Expand Down Expand Up @@ -618,13 +630,15 @@ func TestRenderConfig(t *testing.T) {
Name: "Ethernet1/1",
InterfaceType: InterfaceTypePhysical,
Ip: netip.MustParsePrefix("172.16.0.2/31"),
Mtu: 2048,
Metric: 40000,
IsLink: true,
},
{
Name: "Ethernet1/2",
InterfaceType: InterfaceTypePhysical,
Ip: netip.MustParsePrefix("172.16.0.4/31"),
Mtu: 2048,
},
},
Vpn4vLoopbackIntfName: "Loopback255",
Expand Down
3 changes: 3 additions & 0 deletions controlplane/controller/internal/controller/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,9 @@ func (c *Controller) updateStateCache(ctx context.Context) error {
}

d.Interfaces[i].Metric = uint32(microseconds)
if link.Mtu > 0 {
d.Interfaces[i].Mtu = uint16(link.Mtu)
Comment thread
bgm-malbeclabs marked this conversation as resolved.
}
d.Interfaces[i].IsLink = true
d.Interfaces[i].LinkStatus = link.Status
linkMetrics.WithLabelValues(device.Code, iface.Name, d.PubKey).Set(float64(d.Interfaces[i].Metric))
Expand Down
17 changes: 17 additions & 0 deletions controlplane/controller/internal/controller/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -472,13 +472,15 @@ func TestGetConfig(t *testing.T) {
Name: "Ethernet1/1",
InterfaceType: InterfaceTypePhysical,
Ip: netip.MustParsePrefix("172.16.0.2/31"),
Mtu: 2048,
Metric: 40000,
IsLink: true,
},
{
Name: "Ethernet1/2",
InterfaceType: InterfaceTypePhysical,
Ip: netip.MustParsePrefix("172.16.0.4/31"),
Mtu: 2048,
Metric: 40000,
IsLink: false, // make sure we don't render an isis config since it's not in a link
},
Expand Down Expand Up @@ -851,18 +853,21 @@ func TestStateCache(t *testing.T) {
InterfaceType: serviceability.InterfaceTypePhysical,
Name: "Ethernet1/1",
IpNet: [5]uint8{172, 16, 0, 2, 31},
Mtu: 2048,
Status: serviceability.InterfaceStatusActivated,
},
{
InterfaceType: serviceability.InterfaceTypePhysical,
Name: "Ethernet1/2",
IpNet: [5]uint8{172, 16, 0, 4, 31},
Mtu: 2048,
Status: serviceability.InterfaceStatusActivated,
},
{
InterfaceType: serviceability.InterfaceTypePhysical,
Name: "Ethernet1/3",
IpNet: [5]uint8{172, 16, 0, 6, 31},
Mtu: 2048,
Status: serviceability.InterfaceStatusActivated,
},
},
Expand All @@ -877,6 +882,7 @@ func TestStateCache(t *testing.T) {
Owner: [32]uint8{},
SideAPubKey: [32]uint8{1},
SideZPubKey: [32]uint8{2},
Mtu: 2048,
DelayNs: 400000000,
DelayOverrideNs: 0,
Status: serviceability.LinkStatusActivated,
Expand All @@ -888,6 +894,7 @@ func TestStateCache(t *testing.T) {
Owner: [32]uint8{},
SideAPubKey: [32]uint8{1},
SideZPubKey: [32]uint8{2},
Mtu: 2048,
DelayNs: 1000,
DelayOverrideNs: 0,
Status: serviceability.LinkStatusActivated,
Expand All @@ -899,6 +906,7 @@ func TestStateCache(t *testing.T) {
Owner: [32]uint8{},
SideAPubKey: [32]uint8{1},
SideZPubKey: [32]uint8{2},
Mtu: 2048,
DelayNs: 1000,
DelayOverrideNs: 50000,
Status: serviceability.LinkStatusActivated,
Expand Down Expand Up @@ -976,6 +984,7 @@ func TestStateCache(t *testing.T) {
{
InterfaceType: InterfaceTypePhysical,
Ip: netip.MustParsePrefix("172.16.0.2/31"),
Mtu: 2048,
Name: "Ethernet1/1",
IsLink: true,
Metric: 400000,
Expand All @@ -984,6 +993,7 @@ func TestStateCache(t *testing.T) {
{
InterfaceType: InterfaceTypePhysical,
Ip: netip.MustParsePrefix("172.16.0.4/31"),
Mtu: 2048,
Name: "Ethernet1/2",
IsLink: true,
Metric: 1,
Expand All @@ -992,6 +1002,7 @@ func TestStateCache(t *testing.T) {
{
InterfaceType: InterfaceTypePhysical,
Ip: netip.MustParsePrefix("172.16.0.6/31"),
Mtu: 2048,
Name: "Ethernet1/3",
IsLink: true,
Metric: 50,
Expand Down Expand Up @@ -1727,17 +1738,20 @@ func TestEndToEnd(t *testing.T) {
Name: "Switch1/1/1",
InterfaceType: serviceability.InterfaceTypePhysical,
IpNet: [5]uint8{172, 16, 0, 0, 31},
Mtu: 2048,
},
{
Name: "Switch1/1/2.100",
InterfaceType: serviceability.InterfaceTypePhysical,
VlanId: 100,
IpNet: [5]uint8{172, 16, 0, 2, 31},
Mtu: 2048,
},
{
Name: "Switch1/1/3",
InterfaceType: serviceability.InterfaceTypePhysical,
IpNet: [5]uint8{172, 16, 0, 4, 31},
Mtu: 2048,
},
},
},
Expand All @@ -1748,6 +1762,7 @@ func TestEndToEnd(t *testing.T) {
Owner: [32]uint8{},
SideAPubKey: [32]uint8{1},
SideZPubKey: [32]uint8{2},
Mtu: 2048,
DelayNs: 400000000,
Status: serviceability.LinkStatusActivated,
SideAIfaceName: "Switch1/1/1",
Expand All @@ -1758,6 +1773,7 @@ func TestEndToEnd(t *testing.T) {
Owner: [32]uint8{},
SideAPubKey: [32]uint8{1},
SideZPubKey: [32]uint8{2},
Mtu: 2048,
DelayNs: 1000,
Status: serviceability.LinkStatusActivated,
SideAIfaceName: "Switch1/1/2.100",
Expand All @@ -1768,6 +1784,7 @@ func TestEndToEnd(t *testing.T) {
Owner: [32]uint8{},
SideAPubKey: [32]uint8{1},
SideZPubKey: [32]uint8{2},
Mtu: 2048,
DelayNs: 1000,
DelayOverrideNs: 50000,
Status: serviceability.LinkStatusActivated,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ system control-plane
{{- range .Device.Interfaces }}
interface {{ .Name }}
{{- if .IsPhysical }}
{{- if .Mtu }}
mtu {{ .Mtu }}
{{- else }}
mtu 2048
{{- end }}
{{- end }}
{{- if and .IsPhysical (not .IsSubInterface) (not .IsVlanInterface) }}
no switchport
Expand Down
14 changes: 7 additions & 7 deletions e2e/allocation_lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,11 +440,11 @@ func TestE2E_MultipleLinks_AllocationLifecycle(t *testing.T) {
doublezero device update --pubkey test-dz01 --max-users 128 2>&1
doublezero device update --pubkey test-dz02 --max-users 128 2>&1
doublezero device update --pubkey test-dz03 --max-users 128 2>&1
doublezero device interface create test-dz01 "Ethernet1" --bandwidth 10G 2>&1
doublezero device interface create test-dz01 "Ethernet2" --bandwidth 10G 2>&1
doublezero device interface create test-dz02 "Ethernet1" --bandwidth 10G 2>&1
doublezero device interface create test-dz02 "Ethernet2" --bandwidth 10G 2>&1
doublezero device interface create test-dz03 "Ethernet1" --bandwidth 10G 2>&1
doublezero device interface create test-dz01 "Ethernet1" --bandwidth 10G --mtu 2048 2>&1
doublezero device interface create test-dz01 "Ethernet2" --bandwidth 10G --mtu 2048 2>&1
doublezero device interface create test-dz02 "Ethernet1" --bandwidth 10G --mtu 2048 2>&1
doublezero device interface create test-dz02 "Ethernet2" --bandwidth 10G --mtu 2048 2>&1
doublezero device interface create test-dz03 "Ethernet1" --bandwidth 10G --mtu 2048 2>&1
`})
log.Debug("Device creation output", "output", string(output))
require.NoError(t, err, "Device creation failed")
Expand Down Expand Up @@ -486,8 +486,8 @@ func TestE2E_MultipleLinks_AllocationLifecycle(t *testing.T) {
log.Debug("==> Creating multiple links")
_, err = dn.Manager.Exec(ctx, []string{"bash", "-c", `
set -euo pipefail
doublezero link create wan --code "test-dz01:test-dz02" --contributor co01 --side-a test-dz01 --side-a-interface Ethernet1 --side-z test-dz02 --side-z-interface Ethernet1 --bandwidth "10 Gbps" --mtu 9000 --delay-ms 10 --jitter-ms 1 --desired-status activated -w
doublezero link create wan --code "test-dz02:test-dz03" --contributor co01 --side-a test-dz02 --side-a-interface Ethernet2 --side-z test-dz03 --side-z-interface Ethernet1 --bandwidth "10 Gbps" --mtu 9000 --delay-ms 15 --jitter-ms 1 --desired-status activated -w
doublezero link create wan --code "test-dz01:test-dz02" --contributor co01 --side-a test-dz01 --side-a-interface Ethernet1 --side-z test-dz02 --side-z-interface Ethernet1 --bandwidth "10 Gbps" --mtu 2048 --delay-ms 10 --jitter-ms 1 --desired-status activated -w
doublezero link create wan --code "test-dz02:test-dz03" --contributor co01 --side-a test-dz02 --side-a-interface Ethernet2 --side-z test-dz03 --side-z-interface Ethernet1 --bandwidth "10 Gbps" --mtu 2048 --delay-ms 15 --jitter-ms 1 --desired-status activated -w
`})
require.NoError(t, err)

Expand Down
12 changes: 6 additions & 6 deletions e2e/compatibility_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1068,10 +1068,10 @@ func runWriteWorkflows(

// Interface creates use counter-based PDA derivation — must be sequential.
{name: "create_interfaces", parallel: false, steps: []writeStep{
{name: "device_interface_create", cmd: cli + " device interface create " + deviceCode + " " + ifaceName + " --bandwidth 10G"},
{name: "device_interface_create_2", cmd: cli + " device interface create " + deviceCode2 + " " + ifaceName + " --bandwidth 10G"},
{name: "device_interface_create_3", cmd: cli + " device interface create " + deviceCode + " " + ifaceName2 + " --bandwidth 10G"},
{name: "device_interface_create_4", cmd: cli + " device interface create " + deviceCode2 + " " + ifaceName2 + " --bandwidth 10G"},
{name: "device_interface_create", cmd: cli + " device interface create " + deviceCode + " " + ifaceName + " --bandwidth 10G --mtu 2048"},
{name: "device_interface_create_2", cmd: cli + " device interface create " + deviceCode2 + " " + ifaceName + " --bandwidth 10G --mtu 2048"},
{name: "device_interface_create_3", cmd: cli + " device interface create " + deviceCode + " " + ifaceName2 + " --bandwidth 10G --mtu 2048"},
{name: "device_interface_create_4", cmd: cli + " device interface create " + deviceCode2 + " " + ifaceName2 + " --bandwidth 10G --mtu 2048"},
}},

// Transition all 4 interfaces to "unlinked" (required before link creation).
Expand All @@ -1093,13 +1093,13 @@ func runWriteWorkflows(
" --contributor " + contributorCode +
" --side-a " + deviceCode + " --side-a-interface " + ifaceName +
" --side-z " + deviceCode2 + " --side-z-interface " + ifaceName +
` --bandwidth "10 Gbps" --mtu 9000 --delay-ms 1 --jitter-ms 0.01`},
` --bandwidth "10 Gbps" --mtu 2048 --delay-ms 1 --jitter-ms 0.01`},
{name: "link_create_dzx", cmd: cli + " link create dzx" +
" --code " + dzxLinkCode +
" --contributor " + contributorCode +
" --side-a " + deviceCode + " --side-a-interface " + ifaceName2 +
" --side-z " + deviceCode2 +
` --bandwidth "10 Gbps" --mtu 9000 --delay-ms 1 --jitter-ms 0.01`},
` --bandwidth "10 Gbps" --mtu 2048 --delay-ms 1 --jitter-ms 0.01`},
{name: "multicast_group_create", cmd: cli + " multicast group create --code " + multicastCode +
" --max-bandwidth 100Mbps --owner me", noCascade: true},
{name: "accesspass_set", cmd: cli + " access-pass set --accesspass-type prepaid --client-ip " + userClientIP +
Expand Down
25 changes: 21 additions & 4 deletions e2e/contributor_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,15 +272,32 @@ func TestE2E_ContributorAuth(t *testing.T) {
log.Debug("==> Updating interface as contributor owner")
_, err = dn.Manager.Exec(t.Context(), []string{"bash", "-c", fmt.Sprintf(`
set -euo pipefail
DOUBLEZERO_KEYPAIR=/tmp/co-owner.json doublezero device interface update test-dev-co04 Ethernet1 --mtu 9000 2>&1
DOUBLEZERO_KEYPAIR=/tmp/co-owner.json doublezero device interface update test-dev-co04 Ethernet1 --bandwidth 20G 2>&1
`)})
require.NoError(t, err, "contributor owner should be able to update interface on their own device")

// Step 9: Verify the update via Go SDK
log.Debug("==> Verifying interface update via SDK")
iface, err := waitForInterfaceUpdate(t.Context(), dn, "test-dev-co04", "Ethernet1", serviceability.LoopbackTypeNone, 9000, 30*time.Second)
require.NoError(t, err, "timed out waiting for interface update")
require.Equal(t, uint16(9000), iface.Mtu, "mtu should be updated to 9000")
require.Eventually(t, func() bool {
client, err := dn.Ledger.GetServiceabilityClient()
if err != nil {
return false
}
data, err := client.GetProgramData(t.Context())
if err != nil {
return false
}
for _, device := range data.Devices {
if device.Code == "test-dev-co04" {
for _, iface := range device.Interfaces {
if iface.Name == "Ethernet1" && iface.Bandwidth == 20_000_000_000 {
return true
}
}
}
}
return false
}, 30*time.Second, 2*time.Second, "bandwidth should be updated to 20G")

// Step 10: Negative test - random third keypair should be rejected
log.Debug("==> Testing that random keypair is rejected")
Expand Down
Loading
Loading