From 3de762185f2e0f615c353e704d9c32a9f028026a Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Thu, 13 Jun 2024 06:14:43 +0000 Subject: [PATCH] feat: add interfaces report to support bundle --- cli/support.go | 1 + cli/support_test.go | 4 ++++ codersdk/healthsdk/interfaces.go | 11 +++++++++-- support/support.go | 16 +++++++++++++--- support/support_test.go | 2 ++ 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/cli/support.go b/cli/support.go index f66bcda13ba6f..5dfe7a45a151b 100644 --- a/cli/support.go +++ b/cli/support.go @@ -254,6 +254,7 @@ func writeBundle(src *support.Bundle, dest *zip.Writer) error { "deployment/health.json": src.Deployment.HealthReport, "network/connection_info.json": src.Network.ConnectionInfo, "network/netcheck.json": src.Network.Netcheck, + "network/interfaces.json": src.Network.Interfaces, "workspace/template.json": src.Workspace.Template, "workspace/template_version.json": src.Workspace.TemplateVersion, "workspace/parameters.json": src.Workspace.Parameters, diff --git a/cli/support_test.go b/cli/support_test.go index d9bee0fb2fb20..d53aac66c820c 100644 --- a/cli/support_test.go +++ b/cli/support_test.go @@ -197,6 +197,10 @@ func assertBundleContents(t *testing.T, path string, wantWorkspace bool, wantAge var v derphealth.Report decodeJSONFromZip(t, f, &v) require.NotEmpty(t, v, "netcheck should not be empty") + case "network/interfaces.json": + var v healthsdk.InterfacesReport + decodeJSONFromZip(t, f, &v) + require.NotEmpty(t, v, "interfaces should not be empty") case "workspace/workspace.json": var v codersdk.Workspace decodeJSONFromZip(t, f, &v) diff --git a/codersdk/healthsdk/interfaces.go b/codersdk/healthsdk/interfaces.go index 380a6a71ff1ca..6f4365aaeefac 100644 --- a/codersdk/healthsdk/interfaces.go +++ b/codersdk/healthsdk/interfaces.go @@ -8,6 +8,13 @@ import ( "github.com/coder/coder/v2/coderd/healthcheck/health" ) +// gVisor is nominally permitted to send packets up to 1280. +// Wireguard adds 30 bytes (1310) +// UDP adds 8 bytes (1318) +// IP adds 20-60 bytes (1338-1378) +// So, it really needs to be 1378 to be totally safe +const safeMTU = 1378 + // @typescript-ignore InterfacesReport type InterfacesReport struct { BaseReport @@ -61,11 +68,11 @@ func generateInterfacesReport(st *interfaces.State) (report InterfacesReport) { continue } report.Interfaces = append(report.Interfaces, healthIface) - if iface.MTU < 1378 { + if iface.MTU < safeMTU { report.Severity = health.SeverityWarning report.Warnings = append(report.Warnings, health.Messagef(health.CodeInterfaceSmallMTU, - "network interface %s has MTU %d (less than 1378), which may cause problems with direct connections", iface.Name, iface.MTU), + "network interface %s has MTU %d (less than %d), which may cause problems with direct connections", iface.Name, iface.MTU, safeMTU), ) } } diff --git a/support/support.go b/support/support.go index af3ad21200d02..5ae48ddb37cba 100644 --- a/support/support.go +++ b/support/support.go @@ -47,9 +47,10 @@ type Deployment struct { type Network struct { ConnectionInfo workspacesdk.AgentConnectionInfo - CoordinatorDebug string `json:"coordinator_debug"` - Netcheck *derphealth.Report `json:"netcheck"` - TailnetDebug string `json:"tailnet_debug"` + CoordinatorDebug string `json:"coordinator_debug"` + Netcheck *derphealth.Report `json:"netcheck"` + TailnetDebug string `json:"tailnet_debug"` + Interfaces healthsdk.InterfacesReport `json:"interfaces"` } type Netcheck struct { @@ -194,6 +195,15 @@ func NetworkInfo(ctx context.Context, client *codersdk.Client, log slog.Logger) return nil }) + eg.Go(func() error { + rpt, err := healthsdk.RunInterfacesReport() + if err != nil { + return xerrors.Errorf("run interfaces report: %w", err) + } + n.Interfaces = rpt + return nil + }) + if err := eg.Wait(); err != nil { log.Error(ctx, "fetch network information", slog.Error(err)) } diff --git a/support/support_test.go b/support/support_test.go index 55eb6a1f23bd9..cdd62ceeb8f9b 100644 --- a/support/support_test.go +++ b/support/support_test.go @@ -66,6 +66,7 @@ func TestRun(t *testing.T) { assertNotNilNotEmpty(t, bun.Network.CoordinatorDebug, "network coordinator debug should be present") assertNotNilNotEmpty(t, bun.Network.Netcheck, "network netcheck should be present") assertNotNilNotEmpty(t, bun.Network.TailnetDebug, "network tailnet debug should be present") + assertNotNilNotEmpty(t, bun.Network.Interfaces, "network interfaces health should be present") assertNotNilNotEmpty(t, bun.Workspace.Workspace, "workspace should be present") assertSanitizedWorkspace(t, bun.Workspace.Workspace) assertNotNilNotEmpty(t, bun.Workspace.BuildLogs, "workspace build logs should be present") @@ -114,6 +115,7 @@ func TestRun(t *testing.T) { assertNotNilNotEmpty(t, bun.Network.CoordinatorDebug, "network coordinator debug should be present") assertNotNilNotEmpty(t, bun.Network.Netcheck, "network netcheck should be present") assertNotNilNotEmpty(t, bun.Network.TailnetDebug, "network tailnet debug should be present") + assertNotNilNotEmpty(t, bun.Network.Interfaces, "network interfaces health should be present") assert.Empty(t, bun.Workspace.Workspace, "did not expect workspace to be present") assert.Empty(t, bun.Agent, "did not expect agent to be present") assertNotNilNotEmpty(t, bun.Logs, "bundle logs should be present")