Skip to content

Commit 619a50e

Browse files
committed
WIP: added triangle network; no MTU changes
1 parent 8093d65 commit 619a50e

File tree

2 files changed

+109
-116
lines changed

2 files changed

+109
-116
lines changed

tailnet/test/integration/integration_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ var topologies = []integration.TestTopology{
109109
StartClient: integration.StartClientDirect,
110110
RunTests: integration.TestSuite,
111111
},
112+
{
113+
// Test that direct over normal MTU works.
114+
Name: "DirectMTU1500",
115+
SetupNetworking: integration.SetupNetworkingWithDirectMTU1500,
116+
Server: integration.SimpleServerOptions{},
117+
StartClient: integration.StartClientDirect,
118+
RunTests: integration.TestSuite,
119+
},
112120
{
113121
// Test that DERP over WebSocket (as well as DERPForceWebSockets works).
114122
// This does not test the actual DERP failure detection code and

tailnet/test/integration/network.go

Lines changed: 101 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ func SetupNetworkingEasyNATWithSTUN(t *testing.T, _ slog.Logger) TestNetworking
178178
return internet.Net
179179
}
180180

181+
func SetupNetworkingWithDirectMTU1500(t *testing.T, _ slog.Logger) TestNetworking {
182+
triNet := createFakeTriangleNetwork(t)
183+
return triNet.Net
184+
}
185+
181186
// hardNAT creates a fake internet with multiple STUN servers and sets up "hard
182187
// NAT" forwarding rules. If bothHard is false, only the first client will have
183188
// hard NAT rules, and the second client will have easy NAT rules.
@@ -464,137 +469,117 @@ type fakeTriangleNetwork struct {
464469
// . └──────────────┘10.0.1.1 └─────────────┘
465470
func createFakeTriangleNetwork(t *testing.T) fakeTriangleNetwork {
466471
t.Helper()
467-
const (
468-
bridgePrefix = "10.0.0."
469-
serverIP = bridgePrefix + "1"
470-
client1Prefix = "10.0.2."
471-
client2Prefix = "10.0.3."
472-
)
473472
var (
474473
namePrefix = uniqNetName(t) + "_"
475474
network = fakeTriangleNetwork{
476475
NamePrefix: namePrefix,
477476
}
478477
)
479478

480-
// Create bridge namespace and bridge interface.
481-
router.BridgeNetNS = createNetNS(t, router.BridgeName)
482-
err := createBridge(router.BridgeNetNS, router.BridgeName)
483-
require.NoError(t, err, "create bridge in netns")
484-
485-
// Create server namespace and veth pair between bridge and server.
486-
router.ServerNetNS = createNetNS(t, namePrefix+"s")
487-
router.ServerVethPair = vethPair{
488-
Outer: namePrefix + "b-s",
489-
Inner: namePrefix + "s-b",
490-
}
491-
err = joinBridge(joinBridgeOpts{
492-
bridgeNetNS: router.BridgeNetNS,
493-
netNS: router.ServerNetNS,
494-
bridgeName: router.BridgeName,
495-
vethPair: router.ServerVethPair,
496-
ip: serverIP,
497-
})
498-
require.NoError(t, err, "join bridge with server")
499-
500-
leaves := []struct {
501-
leaf *fakeRouterLeaf
502-
routerName string
503-
clientName string
504-
routerBridgeIP string
505-
routerClientIP string
506-
clientIP string
479+
// Create three network namespaces for server, client1, and client2
480+
network.ServerNetNS = createNetNS(t, namePrefix+"server")
481+
network.Client1NetNS = createNetNS(t, namePrefix+"client1")
482+
network.Client2NetNS = createNetNS(t, namePrefix+"client2")
483+
484+
// Create veth pair between server and client1
485+
network.ServerClient1VethPair = vethPair{
486+
Outer: namePrefix + "server-client1",
487+
Inner: namePrefix + "client1-server",
488+
}
489+
err := createVethPair(network.ServerClient1VethPair.Outer, network.ServerClient1VethPair.Inner)
490+
require.NoErrorf(t, err, "create veth pair %q <-> %q",
491+
network.ServerClient1VethPair.Outer, network.ServerClient1VethPair.Inner)
492+
493+
// Move server-client1 veth ends to their respective namespaces
494+
err = setVethNetNS(network.ServerClient1VethPair.Outer, int(network.ServerNetNS.Fd()))
495+
require.NoErrorf(t, err, "set veth %q to server NetNS", network.ServerClient1VethPair.Outer)
496+
err = setVethNetNS(network.ServerClient1VethPair.Inner, int(network.Client1NetNS.Fd()))
497+
require.NoErrorf(t, err, "set veth %q to client1 NetNS", network.ServerClient1VethPair.Inner)
498+
499+
// Create veth pair between server and client2
500+
network.ServerClient2VethPair = vethPair{
501+
Outer: namePrefix + "s-2",
502+
Inner: namePrefix + "2-s",
503+
}
504+
err = createVethPair(network.ServerClient2VethPair.Outer, network.ServerClient2VethPair.Inner)
505+
require.NoErrorf(t, err, "create veth pair %q <-> %q",
506+
network.ServerClient2VethPair.Outer, network.ServerClient2VethPair.Inner)
507+
508+
// Move server-client2 veth ends to their respective namespaces
509+
err = setVethNetNS(network.ServerClient2VethPair.Outer, int(network.ServerNetNS.Fd()))
510+
require.NoErrorf(t, err, "set veth %q to server NetNS", network.ServerClient2VethPair.Outer)
511+
err = setVethNetNS(network.ServerClient2VethPair.Inner, int(network.Client2NetNS.Fd()))
512+
require.NoErrorf(t, err, "set veth %q to client2 NetNS", network.ServerClient2VethPair.Inner)
513+
514+
// Create veth pair between client1 and client2
515+
network.Client1Client2VethPair = vethPair{
516+
Outer: namePrefix + "1-2",
517+
Inner: namePrefix + "2-1",
518+
}
519+
err = createVethPair(network.Client1Client2VethPair.Outer, network.Client1Client2VethPair.Inner)
520+
require.NoErrorf(t, err, "create veth pair %q <-> %q",
521+
network.Client1Client2VethPair.Outer, network.Client1Client2VethPair.Inner)
522+
523+
// Move client1-client2 veth ends to their respective namespaces
524+
err = setVethNetNS(network.Client1Client2VethPair.Outer, int(network.Client1NetNS.Fd()))
525+
require.NoErrorf(t, err, "set veth %q to client1 NetNS", network.Client1Client2VethPair.Outer)
526+
err = setVethNetNS(network.Client1Client2VethPair.Inner, int(network.Client2NetNS.Fd()))
527+
require.NoErrorf(t, err, "set veth %q to client2 NetNS", network.Client1Client2VethPair.Inner)
528+
529+
// Set IP addresses according to the diagram:
530+
// Server has 10.0.2.3 and 10.0.3.3 on its interfaces
531+
err = setInterfaceIP(network.ServerNetNS, network.ServerClient1VethPair.Outer, "10.0.2.3")
532+
require.NoErrorf(t, err, "set IP on server-client1 interface")
533+
err = setInterfaceIP(network.ServerNetNS, network.ServerClient2VethPair.Outer, "10.0.3.3")
534+
require.NoErrorf(t, err, "set IP on server-client2 interface")
535+
536+
// Client1 has 10.0.2.1 (to server) and 10.0.1.1 (to client2)
537+
err = setInterfaceIP(network.Client1NetNS, network.ServerClient1VethPair.Inner, "10.0.2.1")
538+
require.NoErrorf(t, err, "set IP on client1-server interface")
539+
err = setInterfaceIP(network.Client1NetNS, network.Client1Client2VethPair.Outer, "10.0.1.1")
540+
require.NoErrorf(t, err, "set IP on client1-client2 interface")
541+
542+
// Client2 has 10.0.3.2 (to server) and 10.0.1.2 (to client1)
543+
err = setInterfaceIP(network.Client2NetNS, network.ServerClient2VethPair.Inner, "10.0.3.2")
544+
require.NoErrorf(t, err, "set IP on client2-server interface")
545+
err = setInterfaceIP(network.Client2NetNS, network.Client1Client2VethPair.Inner, "10.0.1.2")
546+
require.NoErrorf(t, err, "set IP on client2-client1 interface")
547+
548+
// Bring up all interfaces
549+
interfaces := []struct {
550+
netNS *os.File
551+
ifaceName string
507552
}{
508-
{
509-
leaf: &router.Client1,
510-
routerName: "c1r",
511-
clientName: "c1",
512-
routerBridgeIP: bridgePrefix + "2",
513-
routerClientIP: client1Prefix + "1",
514-
clientIP: client1Prefix + "2",
515-
},
516-
{
517-
leaf: &router.Client2,
518-
routerName: "c2r",
519-
clientName: "c2",
520-
routerBridgeIP: bridgePrefix + "3",
521-
routerClientIP: client2Prefix + "1",
522-
clientIP: client2Prefix + "2",
523-
},
524-
}
525-
526-
for _, leaf := range leaves {
527-
leaf.leaf.RouterIP = leaf.routerBridgeIP
528-
leaf.leaf.ClientIP = leaf.clientIP
529-
530-
// Create two network namespaces for each leaf: one for the router and
531-
// one for the "client".
532-
leaf.leaf.RouterNetNS = createNetNS(t, namePrefix+leaf.routerName)
533-
leaf.leaf.ClientNetNS = createNetNS(t, namePrefix+leaf.clientName)
534-
535-
// Join the bridge.
536-
leaf.leaf.OuterVethPair = vethPair{
537-
Outer: namePrefix + "b-" + leaf.routerName,
538-
Inner: namePrefix + leaf.routerName + "-b",
539-
}
540-
err = joinBridge(joinBridgeOpts{
541-
bridgeNetNS: router.BridgeNetNS,
542-
netNS: leaf.leaf.RouterNetNS,
543-
bridgeName: router.BridgeName,
544-
vethPair: leaf.leaf.OuterVethPair,
545-
ip: leaf.routerBridgeIP,
546-
})
547-
require.NoError(t, err, "join bridge with router")
548-
549-
// Create inner veth pair between the router and the client.
550-
leaf.leaf.InnerVethPair = vethPair{
551-
Outer: namePrefix + leaf.routerName + "-" + leaf.clientName,
552-
Inner: namePrefix + leaf.clientName + "-" + leaf.routerName,
553-
}
554-
err = createVethPair(leaf.leaf.InnerVethPair.Outer, leaf.leaf.InnerVethPair.Inner)
555-
require.NoErrorf(t, err, "create veth pair %q <-> %q", leaf.leaf.InnerVethPair.Outer, leaf.leaf.InnerVethPair.Inner)
556-
557-
// Move the network interfaces to the respective network namespaces.
558-
err = setVethNetNS(leaf.leaf.InnerVethPair.Outer, int(leaf.leaf.RouterNetNS.Fd()))
559-
require.NoErrorf(t, err, "set veth %q to NetNS", leaf.leaf.InnerVethPair.Outer)
560-
err = setVethNetNS(leaf.leaf.InnerVethPair.Inner, int(leaf.leaf.ClientNetNS.Fd()))
561-
require.NoErrorf(t, err, "set veth %q to NetNS", leaf.leaf.InnerVethPair.Inner)
562-
563-
// Set router's "local" IP on the veth.
564-
err = setInterfaceIP(leaf.leaf.RouterNetNS, leaf.leaf.InnerVethPair.Outer, leaf.routerClientIP)
565-
require.NoErrorf(t, err, "set IP %q on interface %q", leaf.routerClientIP, leaf.leaf.InnerVethPair.Outer)
566-
// Set client's IP on the veth.
567-
err = setInterfaceIP(leaf.leaf.ClientNetNS, leaf.leaf.InnerVethPair.Inner, leaf.clientIP)
568-
require.NoErrorf(t, err, "set IP %q on interface %q", leaf.clientIP, leaf.leaf.InnerVethPair.Inner)
569-
570-
// Bring up the interfaces.
571-
err = setInterfaceUp(leaf.leaf.RouterNetNS, leaf.leaf.InnerVethPair.Outer)
572-
require.NoErrorf(t, err, "bring up interface %q", leaf.leaf.OuterVethPair.Outer)
573-
err = setInterfaceUp(leaf.leaf.ClientNetNS, leaf.leaf.InnerVethPair.Inner)
574-
require.NoErrorf(t, err, "bring up interface %q", leaf.leaf.InnerVethPair.Inner)
575-
576-
// We don't need to add a route from parent to peer since the kernel
577-
// already adds a default route for the /24. We DO need to add a default
578-
// route from peer to parent, however.
579-
err = addRouteInNetNS(leaf.leaf.ClientNetNS, []string{"default", "via", leaf.routerClientIP, "dev", leaf.leaf.InnerVethPair.Inner})
580-
require.NoErrorf(t, err, "add peer default route to %q", leaf.leaf.InnerVethPair.Inner)
581-
}
582-
583-
router.Net = TestNetworking{
553+
{network.ServerNetNS, network.ServerClient1VethPair.Outer},
554+
{network.ServerNetNS, network.ServerClient2VethPair.Outer},
555+
{network.Client1NetNS, network.ServerClient1VethPair.Inner},
556+
{network.Client1NetNS, network.Client1Client2VethPair.Outer},
557+
{network.Client2NetNS, network.ServerClient2VethPair.Inner},
558+
{network.Client2NetNS, network.Client1Client2VethPair.Inner},
559+
}
560+
for _, iface := range interfaces {
561+
err = setInterfaceUp(iface.netNS, iface.ifaceName)
562+
require.NoErrorf(t, err, "bring up interface %q", iface.ifaceName)
563+
// Note: routes are not needed as the interfaces are defined as /24, and we are fully connected, so nothing
564+
// needs to forward IP to a further destination.
565+
}
566+
567+
// Set up the TestNetworking structure
568+
network.Net = TestNetworking{
584569
Server: TestNetworkingServer{
585-
Process: TestNetworkingProcess{NetNS: router.ServerNetNS},
586-
ListenAddr: serverIP + ":8080",
570+
Process: TestNetworkingProcess{NetNS: network.ServerNetNS},
571+
ListenAddr: "0.0.0.0:8080", // Server listens on all IPs
587572
},
588573
Client1: TestNetworkingClient{
589-
Process: TestNetworkingProcess{NetNS: router.Client1.ClientNetNS},
590-
ServerAccessURL: "http://" + serverIP + ":8080",
574+
Process: TestNetworkingProcess{NetNS: network.Client1NetNS},
575+
ServerAccessURL: "http://10.0.2.3:8080", // Client1 accesses server directly
591576
},
592577
Client2: TestNetworkingClient{
593-
Process: TestNetworkingProcess{NetNS: router.Client2.ClientNetNS},
594-
ServerAccessURL: "http://" + serverIP + ":8080",
578+
Process: TestNetworkingProcess{NetNS: network.Client2NetNS},
579+
ServerAccessURL: "http://10.0.3.3:8080", // Client2 accesses server directly
595580
},
596581
}
597-
return router
582+
return network
598583
}
599584

600585
func uniqNetName(t *testing.T) string {

0 commit comments

Comments
 (0)