|
10 | 10 | hasSits = cfg.sits != { }; |
11 | 11 | hasBonds = cfg.bonds != { }; |
12 | 12 |
|
13 | | - addrOpts = v: |
14 | | - assert v == 4 || v == 6; |
15 | | - { |
16 | | - address = mkOption { |
17 | | - type = types.str; |
18 | | - description = '' |
19 | | - IPv${toString v} address of the interface. Leave empty to configure the |
20 | | - interface using DHCP. |
21 | | - ''; |
22 | | - }; |
23 | | - |
24 | | - prefixLength = mkOption { |
25 | | - type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128)); |
26 | | - description = '' |
27 | | - Subnet mask of the interface, specified as the number of |
28 | | - bits in the prefix (<literal>${if v == 4 then "24" else "64"}</literal>). |
29 | | - ''; |
30 | | - }; |
31 | | - }; |
32 | | - |
33 | 13 | interfaceOpts = { name, ... }: { |
34 | 14 |
|
35 | 15 | options = { |
|
40 | 20 | description = "Name of the interface."; |
41 | 21 | }; |
42 | 22 |
|
43 | | - ip4 = mkOption { |
44 | | - default = [ ]; |
45 | | - example = [ |
46 | | - { address = "10.0.0.1"; prefixLength = 16; } |
47 | | - { address = "192.168.1.1"; prefixLength = 24; } |
48 | | - ]; |
49 | | - type = types.listOf types.optionSet; |
50 | | - options = addrOpts 4; |
51 | | - description = '' |
52 | | - List of IPv4 addresses that will be statically assigned to the interface. |
53 | | - ''; |
54 | | - }; |
55 | | - |
56 | | - ip6 = mkOption { |
57 | | - default = [ ]; |
58 | | - example = [ |
59 | | - { address = "fdfd:b3f0:482::1"; prefixLength = 48; } |
60 | | - { address = "2001:1470:fffd:2098::e006"; prefixLength = 64; } |
61 | | - ]; |
62 | | - type = types.listOf types.optionSet; |
63 | | - options = addrOpts 6; |
64 | | - description = '' |
65 | | - List of IPv6 addresses that will be statically assigned to the interface. |
66 | | - ''; |
67 | | - }; |
68 | | - |
69 | 23 | ipAddress = mkOption { |
70 | 24 | default = null; |
71 | 25 | example = "10.0.0.1"; |
72 | | - type = types.nullOr types.str; |
| 26 | + type = types.nullOr (types.str); |
73 | 27 | description = '' |
74 | 28 | IP address of the interface. Leave empty to configure the |
75 | 29 | interface using DHCP. |
|
87 | 41 | }; |
88 | 42 |
|
89 | 43 | subnetMask = mkOption { |
90 | | - default = null; |
| 44 | + default = ""; |
| 45 | + example = "255.255.255.0"; |
| 46 | + type = types.str; |
91 | 47 | description = '' |
92 | | - Defunct, supply the prefix length instead. |
| 48 | + Subnet mask of the interface, specified as a bitmask. |
| 49 | + This is deprecated; use <option>prefixLength</option> |
| 50 | + instead. |
93 | 51 | ''; |
94 | 52 | }; |
95 | 53 |
|
96 | 54 | ipv6Address = mkOption { |
97 | 55 | default = null; |
98 | 56 | example = "2001:1470:fffd:2098::e006"; |
99 | | - type = types.nullOr types.str; |
| 57 | + type = types.nullOr types.string; |
100 | 58 | description = '' |
101 | 59 | IPv6 address of the interface. Leave empty to configure the |
102 | 60 | interface using NDP. |
|
266 | 224 | networking.interfaces = mkOption { |
267 | 225 | default = {}; |
268 | 226 | example = |
269 | | - { eth0.ip4 = [ { |
270 | | - address = "131.211.84.78"; |
271 | | - prefixLength = 25; |
272 | | - } ]; |
| 227 | + { eth0 = { |
| 228 | + ipAddress = "131.211.84.78"; |
| 229 | + subnetMask = "255.255.255.128"; |
| 230 | + }; |
273 | 231 | }; |
274 | 232 | description = '' |
275 | 233 | The configuration for each network interface. If |
|
480 | 438 |
|
481 | 439 | config = { |
482 | 440 |
|
483 | | - assertions = |
484 | | - flip map interfaces (i: { |
485 | | - assertion = i.subnetMask == null; |
486 | | - message = "The networking.interfaces.${i.name}.subnetMask option is defunct. Use prefixLength instead."; |
487 | | - }); |
488 | | - |
489 | 441 | boot.kernelModules = [ ] |
490 | 442 | ++ optional cfg.enableIPv6 "ipv6" |
491 | 443 | ++ optional hasVirtuals "tun" |
|
582 | 534 | # network device, so it only gets started after the interface |
583 | 535 | # has appeared, and it's stopped when the interface |
584 | 536 | # disappears. |
585 | | - configureInterface = i: |
586 | | - let |
587 | | - ips = i.ip4 ++ optionals cfg.enableIPv6 i.ip6 |
588 | | - ++ optional (i.ipAddress != null) { |
589 | | - ipAddress = i.ipAddress; |
590 | | - prefixLength = i.prefixLength; |
591 | | - } ++ optional (cfg.enableIPv6 && i.ipv6Address != null) { |
592 | | - ipAddress = i.ipv6Address; |
593 | | - prefixLength = i.ipv6PrefixLength; |
594 | | - }; |
| 537 | + configureInterface = i: nameValuePair "${i.name}-cfg" |
| 538 | + (let mask = |
| 539 | + if i.prefixLength != null then toString i.prefixLength else |
| 540 | + if i.subnetMask != "" then i.subnetMask else "32"; |
| 541 | + staticIPv6 = cfg.enableIPv6 && i.ipv6Address != null; |
595 | 542 | in |
596 | | - nameValuePair "${i.name}-cfg" |
597 | 543 | { description = "Configuration of ${i.name}"; |
598 | 544 | wantedBy = [ "network-interfaces.target" ]; |
599 | 545 | bindsTo = [ "sys-subsystem-net-devices-${i.name}.device" ]; |
|
616 | 562 | echo "setting MTU to ${toString i.mtu}..." |
617 | 563 | ip link set "${i.name}" mtu "${toString i.mtu}" |
618 | 564 | '' |
619 | | - |
620 | | - # Ip Setup |
621 | | - + |
| 565 | + + optionalString (i.ipAddress != null) |
622 | 566 | '' |
623 | | - curIps=$(ip -o a show dev "${i.name}" | awk '{print $4}') |
624 | | - # Only do an add if it's necessary. This is |
| 567 | + cur=$(ip -4 -o a show dev "${i.name}" | awk '{print $4}') |
| 568 | + # Only do a flush/add if it's necessary. This is |
625 | 569 | # useful when the Nix store is accessed via this |
626 | 570 | # interface (e.g. in a QEMU VM test). |
| 571 | + if [ "$cur" != "${i.ipAddress}/${mask}" ]; then |
| 572 | + echo "configuring interface..." |
| 573 | + ip -4 addr flush dev "${i.name}" |
| 574 | + ip -4 addr add "${i.ipAddress}/${mask}" dev "${i.name}" |
| 575 | + restart_network_setup=true |
| 576 | + else |
| 577 | + echo "skipping configuring interface" |
| 578 | + fi |
627 | 579 | '' |
628 | | - + flip concatMapStrings (ips) (ip: |
629 | | - let |
630 | | - address = "${ip.address}/${toString ip.prefixLength}"; |
631 | | - in |
| 580 | + + optionalString (staticIPv6) |
632 | 581 | '' |
633 | | - echo "checking ip ${address}..." |
634 | | - if ! echo "$curIps" | grep "${address}" >/dev/null 2>&1; then |
635 | | - if out=$(ip addr add "${address}" dev "${i.name}" 2>&1); then |
636 | | - echo "added ip ${address}..." |
637 | | - restart_network_setup=true |
638 | | - elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then |
639 | | - echo "failed to add ${address}" |
640 | | - exit 1 |
641 | | - fi |
| 582 | + # Only do a flush/add if it's necessary. This is |
| 583 | + # useful when the Nix store is accessed via this |
| 584 | + # interface (e.g. in a QEMU VM test). |
| 585 | + if ! ip -6 -o a show dev "${i.name}" | grep "${i.ipv6Address}/${toString i.ipv6prefixLength}"; then |
| 586 | + echo "configuring interface..." |
| 587 | + ip -6 addr flush dev "${i.name}" |
| 588 | + ip -6 addr add "${i.ipv6Address}/${toString i.ipv6prefixLength}" dev "${i.name}" |
| 589 | + restart_network_setup=true |
| 590 | + else |
| 591 | + echo "skipping configuring interface" |
642 | 592 | fi |
643 | | - '') |
644 | | - + optionalString (ips != [ ]) |
| 593 | + '' |
| 594 | + + optionalString (i.ipAddress != null || staticIPv6) |
645 | 595 | '' |
646 | 596 | if [ restart_network_setup = true ]; then |
647 | 597 | # Ensure that the default gateway remains set. |
|
658 | 608 | '' |
659 | 609 | echo 1 > /proc/sys/net/ipv6/conf/${i.name}/proxy_ndp |
660 | 610 | ''; |
661 | | - preStop = |
662 | | - '' |
663 | | - echo "releasing configured ip's..." |
664 | | - '' |
665 | | - + flip concatMapStrings (ips) (ip: |
666 | | - let |
667 | | - address = "${ip.address}/${toString ip.prefixLength}"; |
668 | | - in |
669 | | - '' |
670 | | - echo -n "Deleting ${address}..." |
671 | | - ip addr del "${address}" dev "${i.name}" >/dev/null 2>&1 || echo -n " Failed" |
672 | | - echo "" |
673 | | - ''); |
674 | | - }; |
| 611 | + }); |
675 | 612 |
|
676 | 613 | createTunDevice = i: nameValuePair "${i.name}" |
677 | 614 | { description = "Virtual Network Interface ${i.name}"; |
|
0 commit comments