Merge pull request #85170 from flokli/networking-virtual

nixos/networking: fix setting MAC Address and MTU in networkd, fix tests
This commit is contained in:
Michele Guerini Rocco 2020-04-14 14:20:49 +02:00 committed by GitHub
commit 86d71ddbed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 51 deletions

View File

@ -237,6 +237,38 @@ let
''; '';
}; };
createNetworkLink = i:
let
deviceDependency = if (config.boot.isContainer || i.name == "lo")
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 = deviceDependency;
after = [ "network-pre.target" ] ++ deviceDependency;
path = [ pkgs.iproute ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script =
''
echo "Configuring link..."
'' + optionalString (i.macAddress != null) ''
echo "setting MAC address to ${i.macAddress}..."
ip link set "${i.name}" address "${i.macAddress}"
'' + optionalString (i.mtu != null) ''
echo "setting MTU to ${toString i.mtu}..."
ip link set "${i.name}" mtu "${toString i.mtu}"
'' + ''
echo -n "bringing up interface... "
ip link set "${i.name}" up && echo "done" || (echo "failed"; exit 1)
'';
};
createTunDevice = i: nameValuePair "${i.name}-netdev" createTunDevice = i: nameValuePair "${i.name}-netdev"
{ description = "Virtual Network Interface ${i.name}"; { description = "Virtual Network Interface ${i.name}";
bindsTo = [ "dev-net-tun.device" ]; bindsTo = [ "dev-net-tun.device" ];
@ -508,6 +540,7 @@ let
}); });
in listToAttrs ( in listToAttrs (
map createNetworkLink interfaces ++
map configureAddrs interfaces ++ map configureAddrs interfaces ++
map createTunDevice (filter (i: i.virtual) interfaces)) map createTunDevice (filter (i: i.virtual) interfaces))
// mapAttrs' createBridgeDevice cfg.bridges // mapAttrs' createBridgeDevice cfg.bridges

View File

@ -94,7 +94,12 @@ in
address = forEach (interfaceIps i) address = forEach (interfaceIps i)
(ip: "${ip.address}/${toString ip.prefixLength}"); (ip: "${ip.address}/${toString ip.prefixLength}");
networkConfig.IPv6PrivacyExtensions = "kernel"; networkConfig.IPv6PrivacyExtensions = "kernel";
} ]; linkConfig = optionalAttrs (i.macAddress != null) {
MACAddress = i.macAddress;
} // optionalAttrs (i.mtu != null) {
MTUBytes = toString i.mtu;
};
}];
}))) })))
(mkMerge (flip mapAttrsToList cfg.bridges (name: bridge: { (mkMerge (flip mapAttrsToList cfg.bridges (name: bridge: {
netdevs."40-${name}" = { netdevs."40-${name}" = {

View File

@ -1031,6 +1031,11 @@ in
message = '' message = ''
Temporary addresses are only needed when IPv6 is enabled. Temporary addresses are only needed when IPv6 is enabled.
''; '';
})) ++ (forEach interfaces (i: {
assertion = (i.virtual && i.virtualType == "tun") -> i.macAddress == null;
message = ''
Setting a MAC Address for tun device ${i.name} isn't supported.
'';
})) ++ [ })) ++ [
{ {
assertion = cfg.hostId == null || (stringLength cfg.hostId == 8 && isHexString cfg.hostId); assertion = cfg.hostId == null || (stringLength cfg.hostId == 8 && isHexString cfg.hostId);
@ -1140,38 +1145,7 @@ in
${cfg.localCommands} ${cfg.localCommands}
''; '';
}; };
} // (listToAttrs (forEach interfaces (i: };
let
deviceDependency = if (config.boot.isContainer || i.name == "lo")
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 = deviceDependency;
after = [ "network-pre.target" ] ++ deviceDependency;
path = [ pkgs.iproute ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script =
''
echo "Configuring link..."
'' + optionalString (i.macAddress != null) ''
echo "setting MAC address to ${i.macAddress}..."
ip link set "${i.name}" address "${i.macAddress}"
'' + optionalString (i.mtu != null) ''
echo "setting MTU to ${toString i.mtu}..."
ip link set "${i.name}" mtu "${toString i.mtu}"
'' + ''
echo -n "bringing up interface... "
ip link set "${i.name}" up && echo "done" || (echo "failed"; exit 1)
'';
})));
services.mstpd = mkIf needsMstpd { enable = true; }; services.mstpd = mkIf needsMstpd { enable = true; };
virtualisation.vswitch = mkIf (cfg.vswitches != { }) { enable = true; }; virtualisation.vswitch = mkIf (cfg.vswitches != { }) { enable = true; };

View File

@ -200,6 +200,7 @@ let
useDHCP = false; useDHCP = false;
interfaces.eth1 = { interfaces.eth1 = {
ipv4.addresses = mkOverride 0 [ ]; ipv4.addresses = mkOverride 0 [ ];
mtu = 1343;
useDHCP = true; useDHCP = true;
}; };
interfaces.eth2.ipv4.addresses = mkOverride 0 [ ]; interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
@ -216,6 +217,9 @@ let
with subtest("Wait until we have an ip address on each interface"): with subtest("Wait until we have an ip address on each interface"):
client.wait_until_succeeds("ip addr show dev eth1 | grep -q '192.168.1'") client.wait_until_succeeds("ip addr show dev eth1 | grep -q '192.168.1'")
with subtest("ensure MTU is set"):
assert "mtu 1343" in client.succeed("ip link show dev eth1")
with subtest("Test vlan 1"): with subtest("Test vlan 1"):
client.wait_until_succeeds("ping -c 1 192.168.1.1") client.wait_until_succeeds("ping -c 1 192.168.1.1")
client.wait_until_succeeds("ping -c 1 192.168.1.2") client.wait_until_succeeds("ping -c 1 192.168.1.2")
@ -455,11 +459,14 @@ let
ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ]; ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ];
ipv6.addresses = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ]; ipv6.addresses = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ];
virtual = true; virtual = true;
mtu = 1342;
macAddress = "02:de:ad:be:ef:01";
}; };
networking.interfaces.tun0 = { networking.interfaces.tun0 = {
ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ]; ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
virtual = true; virtual = true;
mtu = 1343;
}; };
}; };
@ -471,7 +478,7 @@ let
with subtest("Wait for networking to come up"): with subtest("Wait for networking to come up"):
machine.start() machine.start()
machine.wait_for_unit("network-online.target") machine.wait_for_unit("network.target")
with subtest("Test interfaces set up"): with subtest("Test interfaces set up"):
list = machine.succeed("ip tuntap list | sort").strip() list = machine.succeed("ip tuntap list | sort").strip()
@ -486,7 +493,12 @@ let
""".format( """.format(
list, targetList list, targetList
) )
with subtest("Test MTU and MAC Address are configured"):
assert "mtu 1342" in machine.succeed("ip link show dev tap0")
assert "mtu 1343" in machine.succeed("ip link show dev tun0")
assert "02:de:ad:be:ef:01" in machine.succeed("ip link show dev tap0")
'' # network-addresses-* only exist in scripted networking
+ optionalString (!networkd) ''
with subtest("Test interfaces clean up"): with subtest("Test interfaces clean up"):
machine.succeed("systemctl stop network-addresses-tap0") machine.succeed("systemctl stop network-addresses-tap0")
machine.sleep(10) machine.sleep(10)
@ -602,17 +614,17 @@ let
}; };
testScript = '' testScript = ''
targetIPv4Table = """ targetIPv4Table = [
10.0.0.0/16 proto static scope link mtu 1500 "10.0.0.0/16 proto static scope link mtu 1500",
192.168.1.0/24 proto kernel scope link src 192.168.1.2 "192.168.1.0/24 proto kernel scope link src 192.168.1.2",
192.168.2.0/24 via 192.168.1.1 proto static "192.168.2.0/24 via 192.168.1.1 proto static",
""".strip() ]
targetIPv6Table = """ targetIPv6Table = [
2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium "2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium",
2001:1470:fffd:2098::/64 via fdfd:b3f0::1 proto static metric 1024 pref medium "2001:1470:fffd:2098::/64 via fdfd:b3f0::1 proto static metric 1024 pref medium",
fdfd:b3f0::/48 proto static metric 1024 pref medium "fdfd:b3f0::/48 proto static metric 1024 pref medium",
""".strip() ]
machine.start() machine.start()
machine.wait_for_unit("network.target") machine.wait_for_unit("network.target")
@ -620,9 +632,9 @@ let
with subtest("test routing tables"): with subtest("test routing tables"):
ipv4Table = machine.succeed("ip -4 route list dev eth0 | head -n3").strip() ipv4Table = machine.succeed("ip -4 route list dev eth0 | head -n3").strip()
ipv6Table = machine.succeed("ip -6 route list dev eth0 | head -n3").strip() ipv6Table = machine.succeed("ip -6 route list dev eth0 | head -n3").strip()
assert ( assert [
ipv4Table == targetIPv4Table l.strip() for l in ipv4Table.splitlines()
), """ ] == targetIPv4Table, """
The IPv4 routing table does not match the expected one: The IPv4 routing table does not match the expected one:
Result: Result:
{} {}
@ -631,9 +643,9 @@ let
""".format( """.format(
ipv4Table, targetIPv4Table ipv4Table, targetIPv4Table
) )
assert ( assert [
ipv6Table == targetIPv6Table l.strip() for l in ipv6Table.splitlines()
), """ ] == targetIPv6Table, """
The IPv6 routing table does not match the expected one: The IPv6 routing table does not match the expected one:
Result: Result:
{} {}