diff options
-rw-r--r-- | nixos/modules/tasks/network-interfaces-scripted.nix | 33 | ||||
-rw-r--r-- | nixos/modules/tasks/network-interfaces.nix | 13 | ||||
-rw-r--r-- | nixos/release.nix | 1 | ||||
-rw-r--r-- | nixos/tests/containers-physical_interfaces.nix | 66 |
4 files changed, 101 insertions, 12 deletions
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix index 6a8f20bab5b62..4bbb5a3a16692 100644 --- a/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixos/modules/tasks/network-interfaces-scripted.nix @@ -46,6 +46,23 @@ in systemd.services = let + deviceDependency = dev: + if (config.boot.isContainer == false) + then + # Trust udev when not in the container + [ (subsystemDevice dev) ] + else + # When in the container, check whether the interface is built from other definitions + if (hasAttr dev cfg.bridges) || + (hasAttr dev cfg.bonds) || + (hasAttr dev cfg.macvlans) || + (hasAttr dev cfg.sits) || + (hasAttr dev cfg.vlans) || + (hasAttr dev cfg.vswitches) || + (hasAttr dev cfg.wlanInterfaces) + then [ "${dev}-netdev.service" ] + else []; + networkLocalCommands = { after = [ "network-setup.service" ]; bindsTo = [ "network-setup.service" ]; @@ -120,8 +137,8 @@ in # order before network-setup because the routes that are configured # there may need ip addresses configured before = [ "network-setup.service" ]; - bindsTo = [ (subsystemDevice i.name) ]; - after = [ (subsystemDevice i.name) "network-pre.target" ]; + bindsTo = deviceDependency i.name; + after = [ "network-pre.target" ] ++ (deviceDependency i.name); serviceConfig.Type = "oneshot"; serviceConfig.RemainAfterExit = true; path = [ pkgs.iproute ]; @@ -179,7 +196,7 @@ in createBridgeDevice = n: v: nameValuePair "${n}-netdev" (let - deps = map subsystemDevice v.interfaces; + deps = if config.boot.isContainer then [] else map subsystemDevice v.interfaces; in { description = "Bridge Interface ${n}"; wantedBy = [ "network-setup.service" (subsystemDevice n) ]; @@ -220,7 +237,7 @@ in createVswitchDevice = n: v: nameValuePair "${n}-netdev" (let - deps = map subsystemDevice v.interfaces; + deps = if config.boot.isContainer then [] else map subsystemDevice v.interfaces; ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules; in { description = "Open vSwitch Interface ${n}"; @@ -253,7 +270,7 @@ in createBondDevice = n: v: nameValuePair "${n}-netdev" (let - deps = map subsystemDevice v.interfaces; + deps = if config.boot.isContainer then [] else map subsystemDevice v.interfaces; in { description = "Bond Interface ${n}"; wantedBy = [ "network-setup.service" (subsystemDevice n) ]; @@ -291,7 +308,7 @@ in createMacvlanDevice = n: v: nameValuePair "${n}-netdev" (let - deps = [ (subsystemDevice v.interface) ]; + deps = deviceDependency v.interface; in { description = "Vlan Interface ${n}"; wantedBy = [ "network-setup.service" (subsystemDevice n) ]; @@ -316,7 +333,7 @@ in createSitDevice = n: v: nameValuePair "${n}-netdev" (let - deps = optional (v.dev != null) (subsystemDevice v.dev); + deps = optional (v.dev != null) (deviceDependency v.dev); in { description = "6-to-4 Tunnel Interface ${n}"; wantedBy = [ "network-setup.service" (subsystemDevice n) ]; @@ -344,7 +361,7 @@ in createVlanDevice = n: v: nameValuePair "${n}-netdev" (let - deps = [ (subsystemDevice v.interface) ]; + deps = deviceDependency v.interface; in { description = "Vlan Interface ${n}"; wantedBy = [ "network-setup.service" (subsystemDevice n) ]; diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index cac7e6b02eba2..aae4dc5fdadfa 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -310,9 +310,9 @@ in generate a random 32-bit ID using the following commands: <literal>cksum /etc/machine-id | while read c rest; do printf "%x" $c; done</literal> - + (this derives it from the machine-id that systemd generates) or - + <literal>head -c4 /dev/urandom | od -A none -t x4</literal> ''; }; @@ -972,12 +972,17 @@ in ''; }; } // (listToAttrs (flip map interfaces (i: + let + deviceDependency = if config.boot.isContainer + then [] + else [ (subsystemDevice i.name) ]; + in nameValuePair "network-link-${i.name}" { description = "Link configuration of ${i.name}"; wantedBy = [ "network-interfaces.target" ]; before = [ "network-interfaces.target" ]; - bindsTo = [ (subsystemDevice i.name) ]; - after = [ (subsystemDevice i.name) "network-pre.target" ]; + bindsTo = deviceDependency; + after = [ "network-pre.target" ] ++ deviceDependency; path = [ pkgs.iproute ]; serviceConfig = { Type = "oneshot"; diff --git a/nixos/release.nix b/nixos/release.nix index bff17da607f30..10c624afebc7d 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -227,6 +227,7 @@ in rec { tests.containers-bridge = callTest tests/containers-bridge.nix {}; tests.containers-imperative = callTest tests/containers-imperative.nix {}; tests.containers-extra_veth = callTest tests/containers-extra_veth.nix {}; + tests.containers-physical_interfaces = callTest tests/containers-physical_interfaces.nix {}; tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; }); tests.dnscrypt-proxy = callTest tests/dnscrypt-proxy.nix { system = "x86_64-linux"; }; tests.ecryptfs = callTest tests/ecryptfs.nix {}; diff --git a/nixos/tests/containers-physical_interfaces.nix b/nixos/tests/containers-physical_interfaces.nix new file mode 100644 index 0000000000000..4a53f8c824f5b --- /dev/null +++ b/nixos/tests/containers-physical_interfaces.nix @@ -0,0 +1,66 @@ + +import ./make-test.nix ({ pkgs, ...} : { + name = "containers-physical_interfaces"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ kampfschlaefer ]; + }; + + nodes = { + server = { config, pkgs, ... }: + { + virtualisation.memorySize = 256; + virtualisation.vlans = [ 1 ]; + + containers.server = { + privateNetwork = true; + interfaces = [ "eth1" ]; + + config = { + networking.interfaces.eth1 = { + ip4 = [ { address = "10.10.0.1"; prefixLength = 24; } ]; + }; + networking.firewall.enable = false; + }; + }; + }; + client = { config, pkgs, ... }: { + virtualisation.memorySize = 256; + virtualisation.vlans = [ 1 ]; + + containers.client = { + privateNetwork = true; + interfaces = [ "eth1" ]; + + config = { + networking.bridges.br0.interfaces = [ "eth1" ]; + networking.interfaces.br0 = { + ip4 = [ { address = "10.10.0.2"; prefixLength = 24; } ]; + }; + networking.firewall.enable = false; + }; + }; + }; + }; + + testScript = '' + startAll; + + $server->waitForUnit("default.target"); + $server->execute("ip link >&2"); + + $server->succeed("ip link show dev eth1 >&2"); + + $server->succeed("nixos-container start server"); + $server->waitForUnit("container\@server"); + $server->succeed("systemctl -M server list-dependencies network-addresses-eth1.service >&2"); + + $server->succeed("nixos-container run server -- ip a show dev eth1 >&2"); + + $client->waitForUnit("default.target"); + $client->succeed("nixos-container start client"); + $client->waitForUnit("container\@client"); + $client->succeed("systemctl -M client list-dependencies network-addresses-br0.service >&2"); + $client->succeed("systemctl -M client status -n 30 -l network-addresses-br0.service"); + $client->succeed("nixos-container run client -- ping -w 10 -c 1 -n 10.10.0.1"); + ''; +}) |