m/test/launch/cluster: add pcap dump

Dump all network traffic by default to help debug failed tests.

Change-Id: I5466639fa00501373690bd95452b85b61fb5b172
Reviewed-on: https://review.monogon.dev/c/monogon/+/1076
Reviewed-by: Leopold Schabel <leo@monogon.tech>
Tested-by: Leopold Schabel <leo@monogon.tech>
diff --git a/metropolis/test/launch/cluster/cluster.go b/metropolis/test/launch/cluster/cluster.go
index 18cab25..bd71f06 100644
--- a/metropolis/test/launch/cluster/cluster.go
+++ b/metropolis/test/launch/cluster/cluster.go
@@ -16,6 +16,7 @@
 	"net"
 	"os"
 	"os/exec"
+	"path"
 	"path/filepath"
 	"syscall"
 	"time"
@@ -60,6 +61,10 @@
 	// configurations.
 	ConnectToSocket *os.File
 
+	// When PcapDump is set, all traffic is dumped to a pcap file in the
+	// runtime directory (e.g. "net0.pcap" for the first interface).
+	PcapDump bool
+
 	// SerialPort is an io.ReadWriter over which you can communicate with the serial
 	// port of the machine. It can be set to an existing file descriptor (like
 	// os.Stdout/os.Stderr) or any Go structure implementing this interface.
@@ -293,6 +298,19 @@
 		qemuArgs = append(qemuArgs, "-fw_cfg", "name=dev.monogon.metropolis/parameters.pb,file="+parametersPath)
 	}
 
+	if options.PcapDump {
+		var qemuNetDump launch.QemuValue
+		pcapPath := filepath.Join(r.ld, "net0.pcap")
+		if options.PcapDump {
+			qemuNetDump = launch.QemuValue{
+				"id":     {"net0"},
+				"netdev": {"net0"},
+				"file":   {pcapPath},
+			}
+		}
+		qemuArgs = append(qemuArgs, "-object", qemuNetDump.ToOption("filter-dump"))
+	}
+
 	// Start TPM emulator as a subprocess
 	tpmCtx, tpmCancel := context.WithCancel(options.Runtime.ctxT)
 	defer tpmCancel()
@@ -653,6 +671,7 @@
 			},
 		},
 		SerialPort: newPrefixedStdio(0),
+		PcapDump:   true,
 	}
 
 	// Start the first node.
@@ -681,6 +700,7 @@
 			ExtraNetworkInterfaces: switchPorts,
 			PortMap:                portMap,
 			SerialPort:             newPrefixedStdio(99),
+			PcapDump:               path.Join(ld, "nanoswitch.pcap"),
 		}); err != nil {
 			if !errors.Is(err, ctxT.Err()) {
 				log.Fatalf("Failed to launch nanoswitch: %v", err)