metropolis/test/nanoswitch: use osbase/bringup
Change-Id: I061371d271414f6474448450c9183a93d0abf3b7
Reviewed-on: https://review.monogon.dev/c/monogon/+/4055
Tested-by: Jenkins CI
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/metropolis/test/nanoswitch/nanoswitch.go b/metropolis/test/nanoswitch/nanoswitch.go
index 39e5026..59c4b59 100644
--- a/metropolis/test/nanoswitch/nanoswitch.go
+++ b/metropolis/test/nanoswitch/nanoswitch.go
@@ -27,12 +27,11 @@
"github.com/insomniacslk/dhcp/dhcpv4"
"github.com/insomniacslk/dhcp/dhcpv4/server4"
"github.com/vishvananda/netlink"
- "golang.org/x/sys/unix"
common "source.monogon.dev/metropolis/node"
"source.monogon.dev/metropolis/node/core/network/dhcp4c"
dhcpcb "source.monogon.dev/metropolis/node/core/network/dhcp4c/callback"
- "source.monogon.dev/osbase/logtree"
+ "source.monogon.dev/osbase/bringup"
"source.monogon.dev/osbase/supervisor"
"source.monogon.dev/osbase/test/qemu"
)
@@ -188,135 +187,107 @@
}
func main() {
- lt := logtree.New()
- reader, err := lt.Read("", logtree.WithChildren(), logtree.WithStream())
+ bringup.Runnable(root).Run()
+}
+
+func root(ctx context.Context) (err error) {
+ logger := supervisor.Logger(ctx)
+ logger.Info("Starting NanoSwitch, a tiny TOR switch emulator")
+
+ c := &nftables.Conn{}
+
+ links, err := netlink.LinkList()
if err != nil {
- panic(fmt.Sprintf("could not set up root log reader: %v", err))
+ logger.Fatalf("Failed to list links: %v", err)
}
- go func() {
- for p := range reader.Stream {
- fmt.Fprintf(os.Stderr, "%s\n", p.ConciseString(nil, 120))
- }
- }()
- supervisor.New(context.Background(), func(ctx context.Context) error {
- logger := supervisor.Logger(ctx)
- logger.Info("Starting NanoSwitch, a tiny TOR switch emulator")
-
- // Set up target filesystems.
- for _, el := range []struct {
- dir string
- fs string
- flags uintptr
- }{
- {"/sys", "sysfs", unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV},
- {"/proc", "proc", unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV},
- {"/dev", "devtmpfs", unix.MS_NOEXEC | unix.MS_NOSUID},
- {"/dev/pts", "devpts", unix.MS_NOEXEC | unix.MS_NOSUID},
- } {
- if err := os.Mkdir(el.dir, 0755); err != nil && !os.IsExist(err) {
- return fmt.Errorf("could not make %s: %w", el.dir, err)
+ var externalLink netlink.Link
+ var vmLinks []netlink.Link
+ for _, link := range links {
+ attrs := link.Attrs()
+ if link.Type() == "device" && len(attrs.HardwareAddr) > 0 {
+ if attrs.Flags&net.FlagUp != net.FlagUp {
+ netlink.LinkSetUp(link) // Attempt to take up all ethernet links
}
- if err := unix.Mount(el.fs, el.dir, el.fs, el.flags, ""); err != nil {
- return fmt.Errorf("could not mount %s on %s: %w", el.fs, el.dir, err)
+ if bytes.Equal(attrs.HardwareAddr, qemu.HostInterfaceMAC) {
+ externalLink = link
+ } else {
+ vmLinks = append(vmLinks, link)
}
}
+ }
+ vmBridgeLink := &netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: "vmbridge", Flags: net.FlagUp}}
+ if err := netlink.LinkAdd(vmBridgeLink); err != nil {
+ logger.Fatalf("Failed to create vmbridge: %v", err)
+ }
+ for _, link := range vmLinks {
+ if err := netlink.LinkSetMaster(link, vmBridgeLink); err != nil {
+ logger.Fatalf("Failed to add VM interface to bridge: %v", err)
+ }
+ logger.Infof("Assigned interface %s to bridge", link.Attrs().Name)
+ }
+ if err := netlink.AddrReplace(vmBridgeLink, &netlink.Addr{IPNet: &net.IPNet{IP: switchIP, Mask: switchSubnetMask}}); err != nil {
+ logger.Fatalf("Failed to assign static IP to vmbridge: %v", err)
+ }
+ if externalLink != nil {
+ nat := c.AddTable(&nftables.Table{
+ Family: nftables.TableFamilyIPv4,
+ Name: "nat",
+ })
- c := &nftables.Conn{}
+ postrouting := c.AddChain(&nftables.Chain{
+ Name: "postrouting",
+ Hooknum: nftables.ChainHookPostrouting,
+ Priority: nftables.ChainPriorityNATSource,
+ Table: nat,
+ Type: nftables.ChainTypeNAT,
+ })
- links, err := netlink.LinkList()
- if err != nil {
- logger.Fatalf("Failed to list links: %v", err)
- }
- var externalLink netlink.Link
- var vmLinks []netlink.Link
- for _, link := range links {
- attrs := link.Attrs()
- if link.Type() == "device" && len(attrs.HardwareAddr) > 0 {
- if attrs.Flags&net.FlagUp != net.FlagUp {
- netlink.LinkSetUp(link) // Attempt to take up all ethernet links
- }
- if bytes.Equal(attrs.HardwareAddr, qemu.HostInterfaceMAC) {
- externalLink = link
- } else {
- vmLinks = append(vmLinks, link)
- }
- }
- }
- vmBridgeLink := &netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: "vmbridge", Flags: net.FlagUp}}
- if err := netlink.LinkAdd(vmBridgeLink); err != nil {
- logger.Fatalf("Failed to create vmbridge: %v", err)
- }
- for _, link := range vmLinks {
- if err := netlink.LinkSetMaster(link, vmBridgeLink); err != nil {
- logger.Fatalf("Failed to add VM interface to bridge: %v", err)
- }
- logger.Infof("Assigned interface %s to bridge", link.Attrs().Name)
- }
- if err := netlink.AddrReplace(vmBridgeLink, &netlink.Addr{IPNet: &net.IPNet{IP: switchIP, Mask: switchSubnetMask}}); err != nil {
- logger.Fatalf("Failed to assign static IP to vmbridge: %v", err)
- }
- if externalLink != nil {
- nat := c.AddTable(&nftables.Table{
- Family: nftables.TableFamilyIPv4,
- Name: "nat",
- })
-
- postrouting := c.AddChain(&nftables.Chain{
- Name: "postrouting",
- Hooknum: nftables.ChainHookPostrouting,
- Priority: nftables.ChainPriorityNATSource,
- Table: nat,
- Type: nftables.ChainTypeNAT,
- })
-
- // Masquerade/SNAT all traffic going out of the external interface
- c.AddRule(&nftables.Rule{
- Table: nat,
- Chain: postrouting,
- Exprs: []expr.Any{
- &expr.Meta{Key: expr.MetaKeyOIFNAME, Register: 1},
- &expr.Cmp{
- Op: expr.CmpOpEq,
- Register: 1,
- Data: nfifname(externalLink.Attrs().Name),
- },
- &expr.Masq{},
+ // Masquerade/SNAT all traffic going out of the external interface
+ c.AddRule(&nftables.Rule{
+ Table: nat,
+ Chain: postrouting,
+ Exprs: []expr.Any{
+ &expr.Meta{Key: expr.MetaKeyOIFNAME, Register: 1},
+ &expr.Cmp{
+ Op: expr.CmpOpEq,
+ Register: 1,
+ Data: nfifname(externalLink.Attrs().Name),
},
- })
+ &expr.Masq{},
+ },
+ })
- if err := c.Flush(); err != nil {
- panic(err)
- }
-
- netIface := &net.Interface{
- Name: externalLink.Attrs().Name,
- MTU: externalLink.Attrs().MTU,
- Index: externalLink.Attrs().Index,
- Flags: externalLink.Attrs().Flags,
- HardwareAddr: externalLink.Attrs().HardwareAddr,
- }
- dhcpClient, err := dhcp4c.NewClient(netIface)
- if err != nil {
- logger.Fatalf("Failed to create DHCP client: %v", err)
- }
- dhcpClient.RequestedOptions = []dhcpv4.OptionCode{dhcpv4.OptionRouter}
- dhcpClient.LeaseCallback = dhcpcb.Compose(dhcpcb.ManageIP(externalLink), dhcpcb.ManageRoutes(externalLink))
- supervisor.Run(ctx, "dhcp-client", dhcpClient.Run)
- if err := os.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte("1\n"), 0644); err != nil {
- logger.Fatalf("Failed to write ip forwards: %v", err)
- }
- } else {
- logger.Info("No upstream interface detected")
+ if err := c.Flush(); err != nil {
+ panic(err)
}
- supervisor.Run(ctx, "dhcp-server", runDHCPServer(vmBridgeLink))
- supervisor.Run(ctx, "proxy-cur1", userspaceProxy(net.IPv4(10, 1, 0, 2), common.CuratorServicePort))
- supervisor.Run(ctx, "proxy-dbg1", userspaceProxy(net.IPv4(10, 1, 0, 2), common.DebugServicePort))
- supervisor.Run(ctx, "proxy-k8s-api1", userspaceProxy(net.IPv4(10, 1, 0, 2), common.KubernetesAPIPort))
- supervisor.Run(ctx, "proxy-k8s-api-wrapped1", userspaceProxy(net.IPv4(10, 1, 0, 2), common.KubernetesAPIWrappedPort))
- supervisor.Run(ctx, "socks", runSOCKSProxy)
- supervisor.Signal(ctx, supervisor.SignalHealthy)
- supervisor.Signal(ctx, supervisor.SignalDone)
- return nil
- }, supervisor.WithExistingLogtree(lt))
- select {}
+
+ netIface := &net.Interface{
+ Name: externalLink.Attrs().Name,
+ MTU: externalLink.Attrs().MTU,
+ Index: externalLink.Attrs().Index,
+ Flags: externalLink.Attrs().Flags,
+ HardwareAddr: externalLink.Attrs().HardwareAddr,
+ }
+ dhcpClient, err := dhcp4c.NewClient(netIface)
+ if err != nil {
+ logger.Fatalf("Failed to create DHCP client: %v", err)
+ }
+ dhcpClient.RequestedOptions = []dhcpv4.OptionCode{dhcpv4.OptionRouter}
+ dhcpClient.LeaseCallback = dhcpcb.Compose(dhcpcb.ManageIP(externalLink), dhcpcb.ManageRoutes(externalLink))
+ supervisor.Run(ctx, "dhcp-client", dhcpClient.Run)
+ if err := os.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte("1\n"), 0644); err != nil {
+ logger.Fatalf("Failed to write ip forwards: %v", err)
+ }
+ } else {
+ logger.Info("No upstream interface detected")
+ }
+ supervisor.Run(ctx, "dhcp-server", runDHCPServer(vmBridgeLink))
+ supervisor.Run(ctx, "proxy-cur1", userspaceProxy(net.IPv4(10, 1, 0, 2), common.CuratorServicePort))
+ supervisor.Run(ctx, "proxy-dbg1", userspaceProxy(net.IPv4(10, 1, 0, 2), common.DebugServicePort))
+ supervisor.Run(ctx, "proxy-k8s-api1", userspaceProxy(net.IPv4(10, 1, 0, 2), common.KubernetesAPIPort))
+ supervisor.Run(ctx, "proxy-k8s-api-wrapped1", userspaceProxy(net.IPv4(10, 1, 0, 2), common.KubernetesAPIWrappedPort))
+ supervisor.Run(ctx, "socks", runSOCKSProxy)
+ supervisor.Signal(ctx, supervisor.SignalHealthy)
+ supervisor.Signal(ctx, supervisor.SignalDone)
+ return nil
}