nixos: Add VM TAP FD, use real WAN (via macvtap) and fix deps
This commit is contained in:
		| @@ -128,6 +128,10 @@ | ||||
|                 Name = "base"; | ||||
|                 Kind = "bridge"; | ||||
|               }; | ||||
|               "30-base-dummy".netdevConfig = { | ||||
|                 Name = "base0"; | ||||
|                 Kind = "dummy"; | ||||
|               }; | ||||
|  | ||||
|               "25-vms".netdevConfig = { | ||||
|                 Name = "vms"; | ||||
| @@ -141,6 +145,10 @@ | ||||
|  | ||||
|             networks = { | ||||
|               "80-base" = networkdAssignment "base" assignments.internal; | ||||
|               "80-base-dummy" = { | ||||
|                 matchConfig.Name = "base0"; | ||||
|                 networkConfig.Bridge = "base"; | ||||
|               }; | ||||
|               "80-base-ext" = { | ||||
|                 matchConfig.Name = "base-ext"; | ||||
|                 networkConfig.Bridge = "base"; | ||||
|   | ||||
| @@ -39,6 +39,40 @@ | ||||
|     }; | ||||
|   in | ||||
|   { | ||||
|     systemd = { | ||||
|       network = { | ||||
|         links = { | ||||
|           "10-wan10g" = { | ||||
|             matchConfig.Path = "pci-0000:2d:00.0"; | ||||
|             linkConfig.Name = "wan10g"; | ||||
|           }; | ||||
|         }; | ||||
|         netdevs = { | ||||
|           "25-vm-wan10g" = { | ||||
|             netdevConfig = { | ||||
|               Name = "vm-wan10g"; | ||||
|               Kind = "macvtap"; | ||||
|             }; | ||||
|             # TODO: Upstream this missing section | ||||
|             extraConfig = '' | ||||
|               [MACVTAP] | ||||
|               Mode=passthru | ||||
|             ''; | ||||
|           }; | ||||
|         }; | ||||
|         networks = { | ||||
|           "75-wan10g" = { | ||||
|             matchConfig.Name = "wan10g"; | ||||
|             networkConfig.MACVTAP = "vm-wan10g"; | ||||
|           }; | ||||
|           "75-vm-wan10g" = { | ||||
|             matchConfig.Name = "vm-wan10g"; | ||||
|             linkConfig.RequiredForOnline = "carrier"; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
|     my = { | ||||
|       vms = { | ||||
|         instances = { | ||||
| @@ -50,12 +84,21 @@ | ||||
|               threads = 2; | ||||
|             }; | ||||
|             memory = 3072; | ||||
|             networks.base = { | ||||
|               waitOnline = "no-carrier"; | ||||
|               mac = "52:54:00:15:1a:53"; | ||||
|             networks = { | ||||
|               wan = { | ||||
|                 ifname = "vm-wan10g"; | ||||
|                 bridge = null; | ||||
|                 tapFD = 100; | ||||
|                 # Real hardware MAC | ||||
|                 mac = "00:02:c9:56:24:6e"; | ||||
|               }; | ||||
|               base = { | ||||
|                 waitOnline = "carrier"; | ||||
|                 mac = "52:54:00:15:1a:53"; | ||||
|               }; | ||||
|             }; | ||||
|             drives = [ ] ++ (optionals (!config.my.build.isDevVM) [ | ||||
|               (vmLVM "estuary" "esp") | ||||
|               (mkMerge [ (vmLVM "estuary" "esp") { frontendOpts.bootindex = 0; } ]) | ||||
|               (vmLVM "estuary" "nix") | ||||
|               (vmLVM "estuary" "persist") | ||||
|             ]); | ||||
|   | ||||
| @@ -69,10 +69,11 @@ let | ||||
|  | ||||
|   netOpts = with lib.types; { name, iName, ... }: { | ||||
|     options = { | ||||
|       ifname = mkOpt' str "vm-${iName}" "TAP device to create "; | ||||
|       ifname = mkOpt' str "vm-${iName}" "TAP device to create / use."; | ||||
|       bridge = mkOpt' (nullOr str) name "Network bridge to connect to (null to not attach to bridge)."; | ||||
|       waitOnline = mkOpt' (either bool str) true | ||||
|         "Whether to wait for networkd to consider the bridge online. Pass a string to set the OPERSTATE will wait for."; | ||||
|         "Whether to wait for networkd to consider the bridge / existing TAP device online. Pass a string to set the OPERSTATE will wait for."; | ||||
|       tapFD = mkOpt' (nullOr ints.unsigned) null "FD to use to pass existing TAP device."; | ||||
|  | ||||
|       model = mkOpt' str "virtio-net" "Device type for network interface."; | ||||
|       mac = mkOpt' str null "Guest MAC address."; | ||||
| @@ -171,7 +172,10 @@ let | ||||
|       ]) ++ | ||||
|       (optional i.spice.enable "spice unix=on,addr=/run/vms/${n}/spice.sock,disable-ticketing=on") ++ | ||||
|       (flatten (mapAttrsToList (nn: c: [ | ||||
|         "netdev tap,id=${nn},ifname=${c.ifname},script=no,downscript=no" | ||||
|         ("netdev tap,id=${nn}," + ( | ||||
|           if (c.tapFD != null) | ||||
|             then "fd=${toString c.tapFD} ${toString c.tapFD}<>/dev/tap$(cat /sys/class/net/${c.ifname}/ifindex)" | ||||
|             else "ifname=${c.ifname},script=no,downscript=no")) | ||||
|         ("device ${c.model},netdev=${nn},mac=${c.mac}" + (extraQEMUOpts c.extraOptions)) | ||||
|       ]) i.networks)) ++ | ||||
|       (flatten (map (d: [ | ||||
| @@ -244,16 +248,22 @@ in | ||||
|               }; | ||||
|             }) | ||||
|             (filterAttrs (_: net: net.bridge != null) i.networks); | ||||
|         services."vm@${n}" = { | ||||
|           description = "Virtual machine '${n}'"; | ||||
|           requires = | ||||
|         services."vm@${n}" = | ||||
|         let | ||||
|           dependencies = | ||||
|             map | ||||
|               (net: | ||||
|               let | ||||
|                 arg = if net.waitOnline == true then net.bridge else "${net.bridge}:${net.waitOnline}"; | ||||
|                 ifname = if net.bridge != null then net.bridge else net.ifname; | ||||
|                 arg = if net.waitOnline == true then ifname else "${ifname}:${net.waitOnline}"; | ||||
|               in | ||||
|               "systemd-networkd-wait-online@${arg}.service") | ||||
|               (filter (net: net.bridge != null && net.waitOnline != false) (attrValues i.networks)); | ||||
|               (filter (net: (net.bridge != null || net.tapFD != null) && net.waitOnline != false) (attrValues i.networks)); | ||||
|         in | ||||
|         { | ||||
|           description = "Virtual machine '${n}'"; | ||||
|           requires = dependencies; | ||||
|           after = dependencies; | ||||
|           serviceConfig = { | ||||
|             ExecStop = mkIf i.cleanShutdown.enabled "${doCleanShutdown} /run/vms/${n}/monitor-qmp.sock"; | ||||
|             TimeoutStopSec = mkIf i.cleanShutdown.enabled i.cleanShutdown.timeout; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user