RouxAntoine
a9979519da
Co-authored-by: RouxAntoine <antoinroux@hotmail.fr> Co-committed-by: RouxAntoine <antoinroux@hotmail.fr>
163 lines
3.6 KiB
Go
163 lines
3.6 KiB
Go
//go:build linux
|
|
|
|
package main
|
|
|
|
// inspired by https://github.com/firecracker-microvm/firectl/blob/main/main.go#L64
|
|
|
|
import (
|
|
"antoine-roux.tk/projects/go/firecracker-netns/internal/netlink"
|
|
"antoine-roux.tk/projects/go/firecracker-netns/internal/netns"
|
|
"context"
|
|
"fmt"
|
|
"github.com/firecracker-microvm/firecracker-go-sdk"
|
|
"github.com/firecracker-microvm/firecracker-go-sdk/client/models"
|
|
"github.com/sirupsen/logrus"
|
|
"net"
|
|
"os"
|
|
"runtime"
|
|
)
|
|
|
|
func setupEnv() int {
|
|
log := logrus.New()
|
|
log.SetLevel(logrus.DebugLevel)
|
|
|
|
newNs, err := netns.New()
|
|
if err != nil {
|
|
fmt.Println("new ns error", err)
|
|
return 1
|
|
}
|
|
|
|
defer func(handle netns.NsHandle) {
|
|
err := handle.Close()
|
|
if err != nil {
|
|
fmt.Println("close ns error", err)
|
|
}
|
|
}(newNs)
|
|
|
|
defer func(ns netns.NsHandle) {
|
|
err := netns.Delete(ns)
|
|
if err != nil {
|
|
fmt.Println("delete ns error", err)
|
|
}
|
|
}(newNs)
|
|
|
|
vethPair, err := netlink.NewVirtualPairing(newNs, "wlp3s0")
|
|
if err != nil {
|
|
fmt.Println("new Veth error", err)
|
|
return 1
|
|
}
|
|
|
|
defer func(veth *netlink.PairLink) {
|
|
err = veth.DeleteVirtualPairing()
|
|
if err != nil {
|
|
fmt.Println("delete vethPair error", err)
|
|
}
|
|
}(vethPair)
|
|
|
|
err = netns.Set(newNs)
|
|
if err != nil {
|
|
fmt.Println("set guest ns error", err)
|
|
return 1
|
|
}
|
|
|
|
firstIpTapNetwork := net.IPv4(172, 16, 0, 1)
|
|
tapNetwork := net.IPNet{
|
|
IP: firstIpTapNetwork,
|
|
Mask: net.CIDRMask(30, 32),
|
|
}
|
|
|
|
tap, err := netlink.CreateTap(tapNetwork, vethPair.Guest.Link.Attrs().Name)
|
|
if err != nil {
|
|
fmt.Println("create tap in guest ns error", err)
|
|
return 1
|
|
}
|
|
defer func(tap *netlink.Tap) {
|
|
err := tap.DeleteTap()
|
|
if err != nil {
|
|
fmt.Println("delete tap error", err)
|
|
}
|
|
}(tap)
|
|
|
|
// Do something with the network namespace
|
|
interfaces, _ := net.Interfaces()
|
|
log.Debugf("Interfaces: %v\n", interfaces)
|
|
|
|
ctx := context.Background()
|
|
cancel, cancelFunc := context.WithCancel(ctx)
|
|
defer cancelFunc()
|
|
|
|
cpuCount := int64(4)
|
|
memorySize := int64(1024)
|
|
isSmt := true
|
|
socketPath := "/tmp/firecracker.socket"
|
|
|
|
cfg := firecracker.Config{
|
|
SocketPath: socketPath,
|
|
KernelImagePath: "./out/vmlinux",
|
|
LogPath: "./out/firecracker.log",
|
|
LogLevel: "Debug",
|
|
KernelArgs: "console=ttyS0 reboot=k panic=1 pci=off",
|
|
Drives: []models.Drive{
|
|
{
|
|
DriveID: firecracker.String("rootfs"),
|
|
PathOnHost: firecracker.String("./out/rootfs.ext4"),
|
|
IsReadOnly: firecracker.Bool(false),
|
|
IsRootDevice: firecracker.Bool(true),
|
|
},
|
|
},
|
|
NetworkInterfaces: firecracker.NetworkInterfaces{
|
|
firecracker.NetworkInterface{
|
|
StaticConfiguration: &firecracker.StaticNetworkConfiguration{
|
|
MacAddress: "06:00:AC:10:00:02",
|
|
HostDevName: tap.Link.Attrs().Name,
|
|
},
|
|
},
|
|
},
|
|
MachineCfg: models.MachineConfiguration{
|
|
VcpuCount: &cpuCount,
|
|
MemSizeMib: &memorySize,
|
|
Smt: &isSmt,
|
|
TrackDirtyPages: true,
|
|
},
|
|
}
|
|
|
|
firecrackerOpts := []firecracker.Opt{
|
|
firecracker.WithProcessRunner(
|
|
firecracker.VMCommandBuilder{}.
|
|
WithBin("firecracker").
|
|
WithSocketPath(socketPath).
|
|
Build(ctx),
|
|
),
|
|
firecracker.WithLogger(logrus.NewEntry(log)),
|
|
}
|
|
|
|
vm, err := firecracker.NewMachine(cancel, cfg, firecrackerOpts...)
|
|
if err != nil {
|
|
log.Errorln("create vm error", err)
|
|
return 1
|
|
}
|
|
defer os.Remove(cfg.SocketPath)
|
|
|
|
defer vm.StopVMM()
|
|
|
|
if err := vm.Start(ctx); err != nil {
|
|
log.Errorln("start vm error", err)
|
|
return 1
|
|
}
|
|
|
|
if err := vm.Wait(ctx); err != nil {
|
|
log.Errorln("wait vm error", err)
|
|
return 1
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
func main() {
|
|
// Lock the OS Thread, so we don't accidentally switch namespaces
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
|
|
os.Exit(setupEnv())
|
|
}
|