diff options
Diffstat (limited to 'nixpkgs/nixos/modules/system/boot/networkd.nix')
-rw-r--r-- | nixpkgs/nixos/modules/system/boot/networkd.nix | 1423 |
1 files changed, 1376 insertions, 47 deletions
diff --git a/nixpkgs/nixos/modules/system/boot/networkd.nix b/nixpkgs/nixos/modules/system/boot/networkd.nix index 337d238f910d..d88f88f9fdaf 100644 --- a/nixpkgs/nixos/modules/system/boot/networkd.nix +++ b/nixpkgs/nixos/modules/system/boot/networkd.nix @@ -6,8 +6,6 @@ with lib; let - cfg = config.systemd.network; - check = { global = { @@ -27,9 +25,11 @@ let sectionDHCPv4 = checkUnitConfig "DHCPv4" [ (assertOnlyFields [ + "ClientIdentifier" "DUIDType" "DUIDRawData" ]) + (assertValueOneOf "ClientIdentifier" ["mac" "duid" "duid-only"]) ]; sectionDHCPv6 = checkUnitConfig "DHCPv6" [ @@ -72,6 +72,9 @@ let "CombinedChannels" "RxBufferSize" "TxBufferSize" + "ReceiveQueues" + "TransmitQueues" + "TransmitQueueLength" ]) (assertValueOneOf "MACAddressPolicy" ["persistent" "random" "none"]) (assertMacAddress "MACAddress") @@ -98,6 +101,9 @@ let (assertRange "CombinedChannels" 1 4294967295) (assertInt "RxBufferSize") (assertInt "TxBufferSize") + (assertRange "ReceiveQueues" 1 4096) + (assertRange "TransmitQueues" 1 4096) + (assertRange "TransmitQueueLength" 1 4294967294) ]; }; @@ -303,6 +309,48 @@ let sectionTap = checkUnitConfig "Tap" tunChecks; + sectionL2TP = checkUnitConfig "L2TP" [ + (assertOnlyFields [ + "TunnelId" + "PeerTunnelId" + "Remote" + "Local" + "EncapsulationType" + "UDPSourcePort" + "UDPDestinationPort" + "UDPChecksum" + "UDP6ZeroChecksumTx" + "UDP6ZeroChecksumRx" + ]) + (assertInt "TunnelId") + (assertRange "TunnelId" 1 4294967295) + (assertInt "PeerTunnelId") + (assertRange "PeerTunnelId" 1 4294967295) + (assertValueOneOf "EncapsulationType" [ "ip" "udp" ]) + (assertPort "UDPSourcePort") + (assertPort "UDPDestinationPort") + (assertValueOneOf "UDPChecksum" boolValues) + (assertValueOneOf "UDP6ZeroChecksumTx" boolValues) + (assertValueOneOf "UDP6ZeroChecksumRx" boolValues) + ]; + + sectionL2TPSession = checkUnitConfig "L2TPSession" [ + (assertOnlyFields [ + "Name" + "SessionId" + "PeerSessionId" + "Layer2SpecificHeader" + ]) + (assertHasField "Name") + (assertHasField "SessionId") + (assertInt "SessionId") + (assertRange "SessionId" 1 4294967295) + (assertHasField "PeerSessionId") + (assertInt "PeerSessionId") + (assertRange "PeerSessionId" 1 4294967295) + (assertValueOneOf "Layer2SpecificHeader" [ "none" "default" ]) + ]; + # NOTE The PrivateKey directive is missing on purpose here, please # do not add it to this list. The nix store is world-readable let's # refrain ourselves from providing a footgun. @@ -451,6 +499,7 @@ let "Multicast" "AllMulticast" "Unmanaged" + "Group" "RequiredForOnline" "RequiredFamilyForOnline" "ActivationPolicy" @@ -463,6 +512,8 @@ let (assertValueOneOf "AllMulticast" boolValues) (assertValueOneOf "Promiscuous" boolValues) (assertValueOneOf "Unmanaged" boolValues) + (assertInt "Group") + (assertRange "Group" 0 2147483647) (assertValueOneOf "RequiredForOnline" (boolValues ++ [ "missing" "off" @@ -498,7 +549,6 @@ let "LinkLocalAddressing" "IPv4LLRoute" "DefaultRouteOnDevice" - "IPv6Token" "LLMNR" "MulticastDNS" "DNSOverTLS" @@ -523,7 +573,7 @@ let "IPv6ProxyNDP" "IPv6ProxyNDPAddress" "IPv6SendRA" - "DHCPv6PrefixDelegation" + "DHCPPrefixDelegation" "IPv6MTUBytes" "Bridge" "Bond" @@ -566,12 +616,11 @@ let (assertValueOneOf "IPv4ProxyARP" boolValues) (assertValueOneOf "IPv6ProxyNDP" boolValues) (assertValueOneOf "IPv6SendRA" boolValues) - (assertValueOneOf "DHCPv6PrefixDelegation" boolValues) + (assertValueOneOf "DHCPPrefixDelegation" boolValues) (assertByteFormat "IPv6MTUBytes") (assertValueOneOf "ActiveSlave" boolValues) (assertValueOneOf "PrimarySlave" boolValues) (assertValueOneOf "ConfigureWithoutCarrier" boolValues) - (assertValueOneOf "IgnoreCarrierLoss" boolValues) (assertValueOneOf "KeepConfiguration" (boolValues ++ ["static" "dhcp-on-stop" "dhcp"])) ]; @@ -583,6 +632,7 @@ let "Label" "PreferredLifetime" "Scope" + "RouteMetric" "HomeAddress" "DuplicateAddressDetection" "ManageTemporaryAddress" @@ -591,6 +641,7 @@ let ]) (assertHasField "Address") (assertValueOneOf "PreferredLifetime" ["forever" "infinity" "0" 0]) + (assertInt "RouteMetric") (assertValueOneOf "HomeAddress" boolValues) (assertValueOneOf "DuplicateAddressDetection" ["ipv4" "ipv6" "both" "none"]) (assertValueOneOf "ManageTemporaryAddress" boolValues) @@ -616,6 +667,7 @@ let "User" "SuppressPrefixLength" "Type" + "SuppressInterfaceGroup" ]) (assertInt "TypeOfService") (assertRange "TypeOfService" 0 255) @@ -629,6 +681,7 @@ let (assertInt "SuppressPrefixLength") (assertRange "SuppressPrefixLength" 0 128) (assertValueOneOf "Type" ["blackhole" "unreachable" "prohibit"]) + (assertRange "SuppressInterfaceGroup" 0 2147483647) ]; sectionRoute = checkUnitConfig "Route" [ @@ -708,6 +761,9 @@ let "BlackList" "RequestOptions" "SendOption" + "FallbackLeaseLifetimeSec" + "Label" + "Use6RD" ]) (assertValueOneOf "UseDNS" boolValues) (assertValueOneOf "RoutesToDNS" boolValues) @@ -730,6 +786,8 @@ let (assertPort "ListenPort") (assertValueOneOf "SendRelease" boolValues) (assertValueOneOf "SendDecline" boolValues) + (assertValueOneOf "FallbackLeaseLifetimeSec" ["forever" "infinity"]) + (assertValueOneOf "Use6RD" boolValues) ]; sectionDHCPv6 = checkUnitConfig "DHCPv6" [ @@ -742,7 +800,6 @@ let "MUDURL" "RequestOptions" "SendVendorOption" - "ForceDHCPv6PDOtherInformation" "PrefixDelegationHint" "WithoutRA" "SendOption" @@ -751,27 +808,33 @@ let "DUIDType" "DUIDRawData" "IAID" + "UseDelegatedPrefix" ]) (assertValueOneOf "UseAddress" boolValues) (assertValueOneOf "UseDNS" boolValues) (assertValueOneOf "UseNTP" boolValues) (assertInt "RouteMetric") (assertValueOneOf "RapidCommit" boolValues) - (assertValueOneOf "ForceDHCPv6PDOtherInformation" boolValues) - (assertValueOneOf "WithoutRA" ["solicit" "information-request"]) + (assertValueOneOf "WithoutRA" ["no" "solicit" "information-request"]) (assertRange "SendOption" 1 65536) (assertInt "IAID") + (assertValueOneOf "UseDelegatedPrefix" boolValues) ]; - sectionDHCPv6PrefixDelegation = checkUnitConfig "DHCPv6PrefixDelegation" [ + sectionDHCPPrefixDelegation = checkUnitConfig "DHCPPrefixDelegation" [ (assertOnlyFields [ + "UplinkInterface" "SubnetId" "Announce" "Assign" "Token" + "ManageTemporaryAddress" + "RouteMetric" ]) (assertValueOneOf "Announce" boolValues) (assertValueOneOf "Assign" boolValues) + (assertValueOneOf "ManageTemporaryAddress" boolValues) + (assertRange "RouteMetric" 0 4294967295) ]; sectionIPv6AcceptRA = checkUnitConfig "IPv6AcceptRA" [ @@ -789,6 +852,10 @@ let "RouteAllowList" "DHCPv6Client" "RouteMetric" + "UseMTU" + "UseGateway" + "UseRoutePrefix" + "Token" ]) (assertValueOneOf "UseDNS" boolValues) (assertValueOneOf "UseDomains" (boolValues ++ ["route"])) @@ -796,14 +863,19 @@ let (assertValueOneOf "UseAutonomousPrefix" boolValues) (assertValueOneOf "UseOnLinkPrefix" boolValues) (assertValueOneOf "DHCPv6Client" (boolValues ++ ["always"])) + (assertValueOneOf "UseMTU" boolValues) + (assertValueOneOf "UseGateway" boolValues) + (assertValueOneOf "UseRoutePrefix" boolValues) ]; sectionDHCPServer = checkUnitConfig "DHCPServer" [ (assertOnlyFields [ + "ServerAddress" "PoolOffset" "PoolSize" "DefaultLeaseTimeSec" "MaxLeaseTimeSec" + "UplinkInterface" "EmitDNS" "DNS" "EmitNTP" @@ -817,10 +889,15 @@ let "EmitLPR" "LPR" "EmitRouter" + "Router" "EmitTimezone" "Timezone" "SendOption" "SendVendorOption" + "BindToInterface" + "RelayTarget" + "RelayAgentCircuitId" + "RelayAgentRemoteId" ]) (assertInt "PoolOffset") (assertMinimum "PoolOffset" 0) @@ -834,6 +911,7 @@ let (assertValueOneOf "EmitLPR" boolValues) (assertValueOneOf "EmitRouter" boolValues) (assertValueOneOf "EmitTimezone" boolValues) + (assertValueOneOf "BindToInterface" boolValues) ]; sectionIPv6SendRA = checkUnitConfig "IPv6SendRA" [ @@ -842,6 +920,7 @@ let "OtherInformation" "RouterLifetimeSec" "RouterPreference" + "UplinkInterface" "EmitDNS" "DNS" "EmitDomains" @@ -862,11 +941,21 @@ let "Prefix" "PreferredLifetimeSec" "ValidLifetimeSec" + "Token" ]) (assertValueOneOf "AddressAutoconfiguration" boolValues) (assertValueOneOf "OnLink" boolValues) ]; + sectionIPv6RoutePrefix = checkUnitConfig "IPv6RoutePrefix" [ + (assertOnlyFields [ + "Route" + "LifetimeSec" + ]) + (assertHasField "Route") + (assertInt "LifetimeSec") + ]; + sectionDHCPServerStaticLease = checkUnitConfig "DHCPServerStaticLease" [ (assertOnlyFields [ "MACAddress" @@ -877,6 +966,470 @@ let (assertMacAddress "MACAddress") ]; + sectionBridge = checkUnitConfig "Bridge" [ + (assertOnlyFields [ + "UnicastFlood" + "MulticastFlood" + "MulticastToUnicast" + "NeighborSuppression" + "Learning" + "Hairpin" + "Isolated" + "UseBPDU" + "FastLeave" + "AllowPortToBeRoot" + "ProxyARP" + "ProxyARPWiFi" + "MulticastRouter" + "Cost" + "Priority" + ]) + (assertValueOneOf "UnicastFlood" boolValues) + (assertValueOneOf "MulticastFlood" boolValues) + (assertValueOneOf "MulticastToUnicast" boolValues) + (assertValueOneOf "NeighborSuppression" boolValues) + (assertValueOneOf "Learning" boolValues) + (assertValueOneOf "Hairpin" boolValues) + (assertValueOneOf "Isolated" boolValues) + (assertValueOneOf "UseBPDU" boolValues) + (assertValueOneOf "FastLeave" boolValues) + (assertValueOneOf "AllowPortToBeRoot" boolValues) + (assertValueOneOf "ProxyARP" boolValues) + (assertValueOneOf "ProxyARPWiFi" boolValues) + (assertValueOneOf "MulticastRouter" [ "no" "query" "permanent" "temporary" ]) + (assertInt "Cost") + (assertRange "Cost" 1 65535) + (assertInt "Priority") + (assertRange "Priority" 0 63) + ]; + + sectionBridgeFDB = checkUnitConfig "BridgeFDB" [ + (assertOnlyFields [ + "MACAddress" + "Destination" + "VLANId" + "VNI" + "AssociatedWith" + "OutgoingInterface" + ]) + (assertHasField "MACAddress") + (assertInt "VLANId") + (assertRange "VLANId" 0 4094) + (assertInt "VNI") + (assertRange "VNI" 1 16777215) + (assertValueOneOf "AssociatedWith" [ "use" "self" "master" "router" ]) + ]; + + sectionBridgeMDB = checkUnitConfig "BridgeMDB" [ + (assertOnlyFields [ + "MulticastGroupAddress" + "VLANId" + ]) + (assertHasField "MulticastGroupAddress") + (assertInt "VLANId") + (assertRange "VLANId" 0 4094) + ]; + + sectionLLDP = checkUnitConfig "LLDP" [ + (assertOnlyFields [ + "MUDURL" + ]) + ]; + + sectionCAN = checkUnitConfig "CAN" [ + (assertOnlyFields [ + "BitRate" + "SamplePoint" + "TimeQuantaNSec" + "PropagationSegment" + "PhaseBufferSegment1" + "PhaseBufferSegment2" + "SyncJumpWidth" + "DataBitRate" + "DataSamplePoint" + "DataTimeQuantaNSec" + "DataPropagationSegment" + "DataPhaseBufferSegment1" + "DataPhaseBufferSegment2" + "DataSyncJumpWidth" + "FDMode" + "FDNonISO" + "RestartSec" + "Termination" + "TripleSampling" + "BusErrorReporting" + "ListenOnly" + "Loopback" + "OneShot" + "PresumeAck" + "ClassicDataLengthCode" + ]) + (assertInt "TimeQuantaNSec" ) + (assertRange "TimeQuantaNSec" 0 4294967295 ) + (assertInt "PropagationSegment" ) + (assertRange "PropagationSegment" 0 4294967295 ) + (assertInt "PhaseBufferSegment1" ) + (assertRange "PhaseBufferSegment1" 0 4294967295 ) + (assertInt "PhaseBufferSegment2" ) + (assertRange "PhaseBufferSegment2" 0 4294967295 ) + (assertInt "SyncJumpWidth" ) + (assertRange "SyncJumpWidth" 0 4294967295 ) + (assertInt "DataTimeQuantaNSec" ) + (assertRange "DataTimeQuantaNSec" 0 4294967295 ) + (assertInt "DataPropagationSegment" ) + (assertRange "DataPropagationSegment" 0 4294967295 ) + (assertInt "DataPhaseBufferSegment1" ) + (assertRange "DataPhaseBufferSegment1" 0 4294967295 ) + (assertInt "DataPhaseBufferSegment2" ) + (assertRange "DataPhaseBufferSegment2" 0 4294967295 ) + (assertInt "DataSyncJumpWidth" ) + (assertRange "DataSyncJumpWidth" 0 4294967295 ) + (assertValueOneOf "FDMode" boolValues) + (assertValueOneOf "FDNonISO" boolValues) + (assertValueOneOf "TripleSampling" boolValues) + (assertValueOneOf "BusErrorReporting" boolValues) + (assertValueOneOf "ListenOnly" boolValues) + (assertValueOneOf "Loopback" boolValues) + (assertValueOneOf "OneShot" boolValues) + (assertValueOneOf "PresumeAck" boolValues) + (assertValueOneOf "ClassicDataLengthCode" boolValues) + ]; + + sectionIPoIB = checkUnitConfig "IPoIB" [ + (assertOnlyFields [ + "Mode" + "IgnoreUserspaceMulticastGroup" + ]) + (assertValueOneOf "Mode" [ "datagram" "connected" ]) + (assertValueOneOf "IgnoreUserspaceMulticastGroup" boolValues) + ]; + + sectionQDisc = checkUnitConfig "QDisc" [ + (assertOnlyFields [ + "Parent" + "Handle" + ]) + (assertValueOneOf "Parent" [ "clsact" "ingress" ]) + ]; + + sectionNetworkEmulator = checkUnitConfig "NetworkEmulator" [ + (assertOnlyFields [ + "Parent" + "Handle" + "DelaySec" + "DelayJitterSec" + "PacketLimit" + "LossRate" + "DuplicateRate" + ]) + (assertInt "PacketLimit") + (assertRange "PacketLimit" 0 4294967294) + ]; + + sectionTokenBucketFilter = checkUnitConfig "TokenBucketFilter" [ + (assertOnlyFields [ + "Parent" + "Handle" + "LatencySec" + "LimitBytes" + "BurstBytes" + "Rate" + "MPUBytes" + "PeakRate" + "MTUBytes" + ]) + ]; + + sectionPIE = checkUnitConfig "PIE" [ + (assertOnlyFields [ + "Parent" + "Handle" + "PacketLimit" + ]) + (assertInt "PacketLimit") + (assertRange "PacketLimit" 1 4294967294) + ]; + + sectionFlowQueuePIE = checkUnitConfig "FlowQueuePIE" [ + (assertOnlyFields [ + "Parent" + "Handle" + "PacketLimit" + ]) + (assertInt "PacketLimit") + (assertRange "PacketLimit" 1 4294967294) + ]; + + sectionStochasticFairBlue = checkUnitConfig "StochasticFairBlue" [ + (assertOnlyFields [ + "Parent" + "Handle" + "PacketLimit" + ]) + (assertInt "PacketLimit") + (assertRange "PacketLimit" 1 4294967294) + ]; + + sectionStochasticFairnessQueueing = checkUnitConfig "StochasticFairnessQueueing" [ + (assertOnlyFields [ + "Parent" + "Handle" + "PerturbPeriodSec" + ]) + (assertInt "PerturbPeriodSec") + ]; + + sectionBFIFO = checkUnitConfig "BFIFO" [ + (assertOnlyFields [ + "Parent" + "Handle" + "LimitBytes" + ]) + ]; + + sectionPFIFO = checkUnitConfig "PFIFO" [ + (assertOnlyFields [ + "Parent" + "Handle" + "PacketLimit" + ]) + (assertInt "PacketLimit") + (assertRange "PacketLimit" 0 4294967294) + ]; + + sectionPFIFOHeadDrop = checkUnitConfig "PFIFOHeadDrop" [ + (assertOnlyFields [ + "Parent" + "Handle" + "PacketLimit" + ]) + (assertInt "PacketLimit") + (assertRange "PacketLimit" 0 4294967294) + ]; + + sectionPFIFOFast = checkUnitConfig "PFIFOFast" [ + (assertOnlyFields [ + "Parent" + "Handle" + ]) + ]; + + sectionCAKE = checkUnitConfig "CAKE" [ + (assertOnlyFields [ + "Parent" + "Handle" + "Bandwidth" + "AutoRateIngress" + "OverheadBytes" + "MPUBytes" + "CompensationMode" + "UseRawPacketSize" + "FlowIsolationMode" + "NAT" + "PriorityQueueingPreset" + "FirewallMark" + "Wash" + "SplitGSO" + ]) + (assertValueOneOf "AutoRateIngress" boolValues) + (assertInt "OverheadBytes") + (assertRange "OverheadBytes" (-64) 256) + (assertInt "MPUBytes") + (assertRange "MPUBytes" 1 256) + (assertValueOneOf "CompensationMode" [ "none" "atm" "ptm" ]) + (assertValueOneOf "UseRawPacketSize" boolValues) + (assertValueOneOf "FlowIsolationMode" + [ + "none" + "src-host" + "dst-host" + "hosts" + "flows" + "dual-src-host" + "dual-dst-host" + "triple" + ]) + (assertValueOneOf "NAT" boolValues) + (assertValueOneOf "PriorityQueueingPreset" + [ + "besteffort" + "precedence" + "diffserv8" + "diffserv4" + "diffserv3" + ]) + (assertInt "FirewallMark") + (assertRange "FirewallMark" 1 4294967295) + (assertValueOneOf "Wash" boolValues) + (assertValueOneOf "SplitGSO" boolValues) + ]; + + sectionControlledDelay = checkUnitConfig "ControlledDelay" [ + (assertOnlyFields [ + "Parent" + "Handle" + "PacketLimit" + "TargetSec" + "IntervalSec" + "ECN" + "CEThresholdSec" + ]) + (assertValueOneOf "ECN" boolValues) + ]; + + sectionDeficitRoundRobinScheduler = checkUnitConfig "DeficitRoundRobinScheduler" [ + (assertOnlyFields [ + "Parent" + "Handle" + ]) + ]; + + sectionDeficitRoundRobinSchedulerClass = checkUnitConfig "DeficitRoundRobinSchedulerClass" [ + (assertOnlyFields [ + "Parent" + "Handle" + "QuantumBytes" + ]) + ]; + + sectionEnhancedTransmissionSelection = checkUnitConfig "EnhancedTransmissionSelection" [ + (assertOnlyFields [ + "Parent" + "Handle" + "Bands" + "StrictBands" + "QuantumBytes" + "PriorityMap" + ]) + (assertInt "Bands") + (assertRange "Bands" 1 16) + (assertInt "StrictBands") + (assertRange "StrictBands" 1 16) + ]; + + sectionGenericRandomEarlyDetection = checkUnitConfig "GenericRandomEarlyDetection" [ + (assertOnlyFields [ + "Parent" + "Handle" + "VirtualQueues" + "DefaultVirtualQueue" + "GenericRIO" + ]) + (assertInt "VirtualQueues") + (assertRange "VirtualQueues" 1 16) + (assertInt "DefaultVirtualQueue") + (assertRange "DefaultVirtualQueue" 1 16) + (assertValueOneOf "GenericRIO" boolValues) + ]; + + sectionFairQueueingControlledDelay = checkUnitConfig "FairQueueingControlledDelay" [ + (assertOnlyFields [ + "Parent" + "Handle" + "PacketLimit" + "MemoryLimitBytes" + "Flows" + "TargetSec" + "IntervalSec" + "QuantumBytes" + "ECN" + "CEThresholdSec" + ]) + (assertInt "PacketLimit") + (assertInt "Flows") + (assertValueOneOf "ECN" boolValues) + ]; + + sectionFairQueueing = checkUnitConfig "FairQueueing" [ + (assertOnlyFields [ + "Parent" + "Handle" + "PacketLimit" + "FlowLimit" + "QuantumBytes" + "InitualQuantumBytes" + "MaximumRate" + "Buckets" + "OrphanMask" + "Pacing" + "CEThresholdSec" + ]) + (assertInt "PacketLimit") + (assertInt "FlowLimit") + (assertInt "OrphanMask") + (assertValueOneOf "Pacing" boolValues) + ]; + + sectionTrivialLinkEqualizer = checkUnitConfig "TrivialLinkEqualizer" [ + (assertOnlyFields [ + "Parent" + "Handle" + "Id" + ]) + ]; + + sectionHierarchyTokenBucket = checkUnitConfig "HierarchyTokenBucket" [ + (assertOnlyFields [ + "Parent" + "Handle" + "DefaultClass" + "RateToQuantum" + ]) + (assertInt "RateToQuantum") + ]; + + sectionHierarchyTokenBucketClass = checkUnitConfig "HierarchyTokenBucketClass" [ + (assertOnlyFields [ + "Parent" + "ClassId" + "Priority" + "QuantumBytes" + "MTUBytes" + "OverheadBytes" + "Rate" + "CeilRate" + "BufferBytes" + "CeilBufferBytes" + ]) + ]; + + sectionHeavyHitterFilter = checkUnitConfig "HeavyHitterFilter" [ + (assertOnlyFields [ + "Parent" + "Handle" + "PacketLimit" + ]) + (assertInt "PacketLimit") + (assertRange "PacketLimit" 0 4294967294) + ]; + + sectionQuickFairQueueing = checkUnitConfig "QuickFairQueueing" [ + (assertOnlyFields [ + "Parent" + "Handle" + ]) + ]; + + sectionQuickFairQueueingClass = checkUnitConfig "QuickFairQueueingClass" [ + (assertOnlyFields [ + "Parent" + "ClassId" + "Weight" + "MaxPacketBytes" + ]) + (assertInt "Weight") + (assertRange "Weight" 1 1023) + ]; + + sectionBridgeVLAN = checkUnitConfig "BridgeVLAN" [ + (assertOnlyFields [ + "VLAN" + "EgressUntagged" + "PVID" + ]) + (assertInt "PVID") + (assertRange "PVID" 0 4094) + ]; }; }; @@ -887,6 +1440,8 @@ let type = types.bool; description = lib.mdDoc '' Whether to manage network configuration using {command}`systemd-network`. + + This also enables {option}`systemd.networkd.enable`. ''; }; @@ -969,6 +1524,21 @@ let }; + + l2tpSessionOptions = { + options = { + l2tpSessionConfig = mkOption { + default = {}; + type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionL2TPSession; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[L2TPSession]` section of the unit. See + {manpage}`systemd.netdev(5)` for details. + ''; + }; + }; + }; + wireguardPeerOptions = { options = { wireguardPeerConfig = mkOption { @@ -1082,6 +1652,38 @@ let ''; }; + l2tpConfig = mkOption { + default = {}; + example = { + TunnelId = 10; + PeerTunnelId = 12; + Local = "static"; + Remote = "192.168.30.101"; + EncapsulationType = "ip"; + }; + type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionL2TP; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[L2TP]` section of the unit. See + {manpage}`systemd.netdev(5)` for details. + ''; + }; + + l2tpSessions = mkOption { + default = []; + example = [ { l2tpSessionConfig={ + SessionId = 25; + PeerSessionId = 26; + Name = "l2tp-sess"; + };}]; + type = with types; listOf (submodule l2tpSessionOptions); + description = lib.mdDoc '' + Each item in this array specifies an option in the + `[L2TPSession]` section of the unit. See + {manpage}`systemd.netdev(5)` for details. + ''; + }; + wireguardConfig = mkOption { default = {}; example = { @@ -1230,6 +1832,21 @@ let }; }; + ipv6RoutePrefixOptions = { + options = { + ipv6RoutePrefixConfig = mkOption { + default = {}; + example = { Route = "fd00::/64"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6RoutePrefix; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[IPv6RoutePrefix]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + }; + }; + dhcpServerStaticLeaseOptions = { options = { dhcpServerStaticLeaseConfig = mkOption { @@ -1248,6 +1865,51 @@ let }; }; + bridgeFDBOptions = { + options = { + bridgeFDBConfig = mkOption { + default = {}; + example = { MACAddress = "65:43:4a:5b:d8:5f"; Destination = "192.168.1.42"; VNI = 20; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeFDB; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[BridgeFDB]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + }; + }; + + bridgeMDBOptions = { + options = { + bridgeMDBConfig = mkOption { + default = {}; + example = { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeMDB; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[BridgeMDB]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + }; + }; + + bridgeVLANOptions = { + options = { + bridgeMDBConfig = mkOption { + default = {}; + example = { VLAN = 20; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeVLAN; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[BridgeVLAN]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + }; + }; + networkOptions = commonNetworkOptions // { linkConfig = mkOption { @@ -1302,12 +1964,17 @@ let }; dhcpV6PrefixDelegationConfig = mkOption { + visible = false; + apply = _: throw "The option `systemd.network.networks.<name>.dhcpV6PrefixDelegationConfig` has been renamed to `systemd.network.networks.<name>.dhcpPrefixDelegationConfig`."; + }; + + dhcpPrefixDelegationConfig = mkOption { default = {}; example = { SubnetId = "auto"; Announce = true; }; - type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPv6PrefixDelegation; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPPrefixDelegation; description = lib.mdDoc '' Each attribute in this set specifies an option in the - `[DHCPv6PrefixDelegation]` section of the unit. See + `[DHCPPrefixDelegation]` section of the unit. See {manpage}`systemd.network(5)` for details. ''; }; @@ -1372,6 +2039,376 @@ let ''; }; + ipv6RoutePrefixes = mkOption { + default = []; + example = [ { ipv6RoutePrefixConfig = { Route = "fd00::/64"; LifetimeSec = 3600; }; } ]; + type = with types; listOf (submodule ipv6RoutePrefixOptions); + description = lib.mdDoc '' + A list of ipv6RoutePrefix sections to be added to the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + bridgeConfig = mkOption { + default = {}; + example = { MulticastFlood = false; Cost = 20; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridge; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[Bridge]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + bridgeFDBs = mkOption { + default = []; + example = [ { bridgeFDBConfig = { MACAddress = "90:e2:ba:43:fc:71"; Destination = "192.168.100.4"; VNI = 3600; }; } ]; + type = with types; listOf (submodule bridgeFDBOptions); + description = lib.mdDoc '' + A list of BridgeFDB sections to be added to the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + bridgeMDBs = mkOption { + default = []; + example = [ { bridgeMDBConfig = { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; } ; } ]; + type = with types; listOf (submodule bridgeMDBOptions); + description = lib.mdDoc '' + A list of BridgeMDB sections to be added to the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + lldpConfig = mkOption { + default = {}; + example = { MUDURL = "https://things.example.org/product_abc123/v5"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionLLDP; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[LLDP]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + canConfig = mkOption { + default = {}; + example = { }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionCAN; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[CAN]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + ipoIBConfig = mkOption { + default = {}; + example = { }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPoIB; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[IPoIB]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + qdiscConfig = mkOption { + default = {}; + example = { Parent = "ingress"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionQDisc; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[QDisc]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + networkEmulatorConfig = mkOption { + default = {}; + example = { Parent = "ingress"; DelaySec = "20msec"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionNetworkEmulator; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[NetworkEmulator]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + tokenBucketFilterConfig = mkOption { + default = {}; + example = { Parent = "ingress"; Rate = "100k"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionTokenBucketFilter; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[TokenBucketFilter]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + pieConfig = mkOption { + default = {}; + example = { Parent = "ingress"; PacketLimit = "3847"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionPIE; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[PIE]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + flowQueuePIEConfig = mkOption { + default = {}; + example = { Parent = "ingress"; PacketLimit = "3847"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionFlowQueuePIE; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[FlowQueuePIE]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + stochasticFairBlueConfig = mkOption { + default = {}; + example = { Parent = "ingress"; PacketLimit = "3847"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionStochasticFairBlue; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[StochasticFairBlue]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + stochasticFairnessQueueingConfig = mkOption { + default = {}; + example = { Parent = "ingress"; PerturbPeriodSec = "30"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionStochasticFairnessQueueing; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[StochasticFairnessQueueing]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + bfifoConfig = mkOption { + default = {}; + example = { Parent = "ingress"; LimitBytes = "20K"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionBFIFO; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[BFIFO]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + pfifoConfig = mkOption { + default = {}; + example = { Parent = "ingress"; PacketLimit = "300"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionPFIFO; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[PFIFO]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + pfifoHeadDropConfig = mkOption { + default = {}; + example = { Parent = "ingress"; PacketLimit = "300"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionPFIFOHeadDrop; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[PFIFOHeadDrop]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + pfifoFastConfig = mkOption { + default = {}; + example = { Parent = "ingress"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionPFIFOFast; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[PFIFOFast]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + cakeConfig = mkOption { + default = {}; + example = { Bandwidth = "40M"; OverheadBytes = 8; CompensationMode = "ptm"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionCAKE; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[CAKE]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + controlledDelayConfig = mkOption { + default = {}; + example = { Parent = "ingress"; TargetSec = "20msec"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionControlledDelay; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[ControlledDelay]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + deficitRoundRobinSchedulerConfig = mkOption { + default = {}; + example = { Parent = "root"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionDeficitRoundRobinScheduler; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[DeficitRoundRobinScheduler]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + deficitRoundRobinSchedulerClassConfig = mkOption { + default = {}; + example = { Parent = "root"; QuantumBytes = "300k"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionDeficitRoundRobinSchedulerClass; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[DeficitRoundRobinSchedulerClass]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + enhancedTransmissionSelectionConfig = mkOption { + default = {}; + example = { Parent = "root"; QuantumBytes = "300k"; Bands = 3; PriorityMap = "100 200 300"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionEnhancedTransmissionSelection; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[EnhancedTransmissionSelection]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + genericRandomEarlyDetectionConfig = mkOption { + default = {}; + example = { Parent = "root"; VirtualQueues = 5; DefaultVirtualQueue = 3; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionGenericRandomEarlyDetection; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[GenericRandomEarlyDetection]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + fairQueueingControlledDelayConfig = mkOption { + default = {}; + example = { Parent = "root"; Flows = 5; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionFairQueueingControlledDelay; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[FairQueueingControlledDelay]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + fairQueueingConfig = mkOption { + default = {}; + example = { Parent = "root"; FlowLimit = 5; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionFairQueueing; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[FairQueueing]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + trivialLinkEqualizerConfig = mkOption { + default = {}; + example = { Parent = "root"; Id = 0; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionTrivialLinkEqualizer; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[TrivialLinkEqualizer]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + hierarchyTokenBucketConfig = mkOption { + default = {}; + example = { Parent = "root"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionHierarchyTokenBucket; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[HierarchyTokenBucket]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + hierarchyTokenBucketClassConfig = mkOption { + default = {}; + example = { Parent = "root"; Rate = "10M"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionHierarchyTokenBucketClass; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[HierarchyTokenBucketClass]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + heavyHitterFilterConfig = mkOption { + default = {}; + example = { Parent = "root"; PacketLimit = 10000; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionHeavyHitterFilter; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[HeavyHitterFilter]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + quickFairQueueingConfig = mkOption { + default = {}; + example = { Parent = "root"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionQuickFairQueueing; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[QuickFairQueueing]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + quickFairQueueingConfigClass = mkOption { + default = {}; + example = { Parent = "root"; Weight = 133; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionQuickFairQueueingClass; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[QuickFairQueueingClass]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + bridgeVLANConfig = mkOption { + default = {}; + example = { VLAN = "10-20"; }; + type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeVLAN; + description = lib.mdDoc '' + Each attribute in this set specifies an option in the + `[BridgeVLAN]` section of the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + + bridgeVLANs = mkOption { + default = []; + example = [ { bridgeVLANConfig = { VLAN = "10-20"; }; } ]; + type = with types; listOf (submodule bridgeVLANOptions); + description = lib.mdDoc '' + A list of BridgeVLAN sections to be added to the unit. See + {manpage}`systemd.network(5)` for details. + ''; + }; + name = mkOption { type = types.nullOr types.str; default = null; @@ -1632,6 +2669,14 @@ let [Tap] ${attrsToSection def.tapConfig} '' + + optionalString (def.l2tpConfig != { }) '' + [L2TP] + ${attrsToSection def.l2tpConfig} + '' + + flip concatMapStrings def.l2tpSessions (x: '' + [L2TPSession] + ${attrsToSection x.l2tpSessionConfig} + '') + optionalString (def.wireguardConfig != { }) '' [WireGuard] ${attrsToSection def.wireguardConfig} @@ -1743,9 +2788,9 @@ let [DHCPv6] ${attrsToSection def.dhcpV6Config} '' - + optionalString (def.dhcpV6PrefixDelegationConfig != { }) '' - [DHCPv6PrefixDelegation] - ${attrsToSection def.dhcpV6PrefixDelegationConfig} + + optionalString (def.dhcpPrefixDelegationConfig != { }) '' + [DHCPPrefixDelegation] + ${attrsToSection def.dhcpPrefixDelegationConfig} '' + optionalString (def.ipv6AcceptRAConfig != { }) '' [IPv6AcceptRA] @@ -1763,23 +2808,153 @@ let [IPv6Prefix] ${attrsToSection x.ipv6PrefixConfig} '') + + flip concatMapStrings def.ipv6RoutePrefixes (x: '' + [IPv6RoutePrefix] + ${attrsToSection x.ipv6RoutePrefixConfig} + '') + flip concatMapStrings def.dhcpServerStaticLeases (x: '' [DHCPServerStaticLease] ${attrsToSection x.dhcpServerStaticLeaseConfig} '') + + optionalString (def.bridgeConfig != { }) '' + [Bridge] + ${attrsToSection def.bridgeConfig} + '' + + flip concatMapStrings def.bridgeFDBs (x: '' + [BridgeFDB] + ${attrsToSection x.bridgeFDBConfig} + '') + + flip concatMapStrings def.bridgeMDBs (x: '' + [BridgeMDB] + ${attrsToSection x.bridgeMDBConfig} + '') + + optionalString (def.lldpConfig != { }) '' + [LLDP] + ${attrsToSection def.lldpConfig} + '' + + optionalString (def.canConfig != { }) '' + [CAN] + ${attrsToSection def.canConfig} + '' + + optionalString (def.ipoIBConfig != { }) '' + [IPoIB] + ${attrsToSection def.ipoIBConfig} + '' + + optionalString (def.qdiscConfig != { }) '' + [QDisc] + ${attrsToSection def.qdiscConfig} + '' + + optionalString (def.networkEmulatorConfig != { }) '' + [NetworkEmulator] + ${attrsToSection def.networkEmulatorConfig} + '' + + optionalString (def.tokenBucketFilterConfig != { }) '' + [TokenBucketFilter] + ${attrsToSection def.tokenBucketFilterConfig} + '' + + optionalString (def.pieConfig != { }) '' + [PIE] + ${attrsToSection def.pieConfig} + '' + + optionalString (def.flowQueuePIEConfig != { }) '' + [FlowQueuePIE] + ${attrsToSection def.flowQueuePIEConfig} + '' + + optionalString (def.stochasticFairBlueConfig != { }) '' + [StochasticFairBlue] + ${attrsToSection def.stochasticFairBlueConfig} + '' + + optionalString (def.stochasticFairnessQueueingConfig != { }) '' + [StochasticFairnessQueueing] + ${attrsToSection def.stochasticFairnessQueueingConfig} + '' + + optionalString (def.bfifoConfig != { }) '' + [BFIFO] + ${attrsToSection def.bfifoConfig} + '' + + optionalString (def.pfifoConfig != { }) '' + [PFIFO] + ${attrsToSection def.pfifoConfig} + '' + + optionalString (def.pfifoHeadDropConfig != { }) '' + [PFIFOHeadDrop] + ${attrsToSection def.pfifoHeadDropConfig} + '' + + optionalString (def.pfifoFastConfig != { }) '' + [PFIFOFast] + ${attrsToSection def.pfifoFastConfig} + '' + + optionalString (def.cakeConfig != { }) '' + [CAKE] + ${attrsToSection def.cakeConfig} + '' + + optionalString (def.controlledDelayConfig != { }) '' + [ControlledDelay] + ${attrsToSection def.controlledDelayConfig} + '' + + optionalString (def.deficitRoundRobinSchedulerConfig != { }) '' + [DeficitRoundRobinScheduler] + ${attrsToSection def.deficitRoundRobinSchedulerConfig} + '' + + optionalString (def.deficitRoundRobinSchedulerClassConfig != { }) '' + [DeficitRoundRobinSchedulerClass] + ${attrsToSection def.deficitRoundRobinSchedulerClassConfig} + '' + + optionalString (def.enhancedTransmissionSelectionConfig != { }) '' + [EnhancedTransmissionSelection] + ${attrsToSection def.enhancedTransmissionSelectionConfig} + '' + + optionalString (def.genericRandomEarlyDetectionConfig != { }) '' + [GenericRandomEarlyDetection] + ${attrsToSection def.genericRandomEarlyDetectionConfig} + '' + + optionalString (def.fairQueueingControlledDelayConfig != { }) '' + [FairQueueingControlledDelay] + ${attrsToSection def.fairQueueingControlledDelayConfig} + '' + + optionalString (def.fairQueueingConfig != { }) '' + [FairQueueing] + ${attrsToSection def.fairQueueingConfig} + '' + + optionalString (def.trivialLinkEqualizerConfig != { }) '' + [TrivialLinkEqualizer] + ${attrsToSection def.trivialLinkEqualizerConfig} + '' + + optionalString (def.hierarchyTokenBucketConfig != { }) '' + [HierarchyTokenBucket] + ${attrsToSection def.hierarchyTokenBucketConfig} + '' + + optionalString (def.hierarchyTokenBucketClassConfig != { }) '' + [HierarchyTokenBucketClass] + ${attrsToSection def.hierarchyTokenBucketClassConfig} + '' + + optionalString (def.heavyHitterFilterConfig != { }) '' + [HeavyHitterFilter] + ${attrsToSection def.heavyHitterFilterConfig} + '' + + optionalString (def.quickFairQueueingConfig != { }) '' + [QuickFairQueueing] + ${attrsToSection def.quickFairQueueingConfig} + '' + + optionalString (def.quickFairQueueingConfigClass != { }) '' + [QuickFairQueueingClass] + ${attrsToSection def.quickFairQueueingConfigClass} + '' + + flip concatMapStrings def.bridgeVLANs (x: '' + [BridgeVLAN] + ${attrsToSection x.bridgeVLANConfig} + '') + def.extraConfig; }; - unitFiles = listToAttrs (map (name: { - name = "systemd/network/${name}"; + mkUnitFiles = prefix: cfg: listToAttrs (map (name: { + name = "${prefix}systemd/network/${name}"; value.source = "${cfg.units.${name}.unit}/${name}"; }) (attrNames cfg.units)); -in -{ - options = { + commonOptions = visible: { - systemd.network.enable = mkOption { + enable = mkOption { default = false; type = types.bool; description = lib.mdDoc '' @@ -1787,32 +2962,36 @@ in ''; }; - systemd.network.links = mkOption { + links = mkOption { default = {}; + inherit visible; type = with types; attrsOf (submodule [ { options = linkOptions; } ]); description = lib.mdDoc "Definition of systemd network links."; }; - systemd.network.netdevs = mkOption { + netdevs = mkOption { default = {}; + inherit visible; type = with types; attrsOf (submodule [ { options = netdevOptions; } ]); description = lib.mdDoc "Definition of systemd network devices."; }; - systemd.network.networks = mkOption { + networks = mkOption { default = {}; + inherit visible; type = with types; attrsOf (submodule [ { options = networkOptions; } networkConfig ]); description = lib.mdDoc "Definition of systemd networks."; }; - systemd.network.config = mkOption { + config = mkOption { default = {}; + inherit visible; type = with types; submodule [ { options = networkdOptions; } networkdConfig ]; description = lib.mdDoc "Definition of global systemd network config."; }; - systemd.network.units = mkOption { - description = "Definition of networkd units."; + units = mkOption { + description = lib.mdDoc "Definition of networkd units."; default = {}; internal = true; type = with types; attrsOf (submodule ( @@ -1824,7 +3003,21 @@ in })); }; - systemd.network.wait-online = { + wait-online = { + enable = mkOption { + type = types.bool; + default = true; + example = false; + description = lib.mdDoc '' + Whether to enable the systemd-networkd-wait-online service. + + systemd-networkd-wait-online can timeout and fail if there are no network interfaces + available for it to manage. When systemd-networkd is enabled but a different service is + responsible for managing the system's internet connection (for example, NetworkManager or + connman are used to manage WiFi connections), this service is unnecessary and can be + disabled. + ''; + }; anyInterface = mkOption { description = lib.mdDoc '' Whether to consider the network online when any interface is online, as opposed to all of them. @@ -1857,7 +3050,7 @@ in Extra command-line arguments to pass to systemd-networkd-wait-online. These also affect per-interface `systemd-network-wait-online@` services. - See [{manpage}`systemd-networkd-wait-online.service(8)`](https://www.freedesktop.org/software/systemd/man/systemd-networkd-wait-online.service.html) for all available options. + See {manpage}`systemd-networkd-wait-online.service(8)` for all available options. ''; type = with types; listOf str; default = []; @@ -1866,12 +3059,11 @@ in }; - config = mkMerge [ + commonConfig = config: let cfg = config.systemd.network; in mkMerge [ # .link units are honored by udev, no matter if systemd-networkd is enabled or not. { systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links; - environment.etc = unitFiles; systemd.network.wait-online.extraArgs = [ "--timeout=${toString cfg.wait-online.timeout}" ] @@ -1881,14 +3073,6 @@ in (mkIf config.systemd.network.enable { - users.users.systemd-network.group = "systemd-network"; - - systemd.additionalUpstreamSystemUnits = [ - "systemd-networkd-wait-online.service" - "systemd-networkd.service" - "systemd-networkd.socket" - ]; - systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks; @@ -1897,15 +3081,8 @@ in # networkd. systemd.sockets.systemd-networkd.wantedBy = [ "sockets.target" ]; - systemd.services.systemd-networkd = { - wantedBy = [ "multi-user.target" ]; - aliases = [ "dbus-org.freedesktop.network1.service" ]; - restartTriggers = map (x: x.source) (attrValues unitFiles) ++ [ - config.environment.etc."systemd/networkd.conf".source - ]; - }; - systemd.services.systemd-networkd-wait-online = { + inherit (cfg.wait-online) enable; wantedBy = [ "network-online.target" ]; serviceConfig.ExecStart = [ "" @@ -1925,8 +3102,37 @@ in }; }; + }) + ]; + + stage2Config = let + cfg = config.systemd.network; + unitFiles = mkUnitFiles "" cfg; + in mkMerge [ + (commonConfig config) + + { environment.etc = unitFiles; } + + (mkIf config.systemd.network.enable { + + users.users.systemd-network.group = "systemd-network"; + + systemd.additionalUpstreamSystemUnits = [ + "systemd-networkd-wait-online.service" + "systemd-networkd.service" + "systemd-networkd.socket" + ]; + environment.etc."systemd/networkd.conf" = renderConfig cfg.config; + systemd.services.systemd-networkd = { + wantedBy = [ "multi-user.target" ]; + restartTriggers = map (x: x.source) (attrValues unitFiles) ++ [ + config.environment.etc."systemd/networkd.conf".source + ]; + aliases = [ "dbus-org.freedesktop.network1.service" ]; + }; + networking.iproute2 = mkIf (cfg.config.addRouteTablesToIPRoute2 && cfg.config.routeTables != { }) { enable = mkDefault true; rttablesExtraConfig = '' @@ -1937,6 +3143,129 @@ in }; services.resolved.enable = mkDefault true; + + }) + ]; + + stage1Config = let + cfg = config.boot.initrd.systemd.network; + in mkMerge [ + (commonConfig config.boot.initrd) + + { + systemd.network.enable = mkDefault config.boot.initrd.network.enable; + systemd.contents = mkUnitFiles "/etc/" cfg; + + # Networkd link files are used early by udev to set up interfaces early. + # This must be done in stage 1 to avoid race conditions between udev and + # network daemons. + systemd.network.units = lib.filterAttrs (n: _: hasSuffix ".link" n) config.systemd.network.units; + systemd.storePaths = ["${config.boot.initrd.systemd.package}/lib/systemd/network/99-default.link"]; + } + + (mkIf cfg.enable { + + systemd.package = pkgs.systemdStage1Network; + + # For networkctl + systemd.dbus.enable = mkDefault true; + + systemd.additionalUpstreamUnits = [ + "systemd-networkd-wait-online.service" + "systemd-networkd.service" + "systemd-networkd.socket" + "systemd-network-generator.service" + "network-online.target" + "network-pre.target" + "network.target" + "nss-lookup.target" + "nss-user-lookup.target" + "remote-fs-pre.target" + "remote-fs.target" + ]; + systemd.users.systemd-network = {}; + systemd.groups.systemd-network = {}; + + systemd.contents."/etc/systemd/networkd.conf" = renderConfig cfg.config; + + systemd.services.systemd-networkd = { + wantedBy = [ "initrd.target" ]; + # These before and conflicts lines can be removed when this PR makes it into a release: + # https://github.com/systemd/systemd/pull/27791 + before = ["initrd-switch-root.target"]; + conflicts = ["initrd-switch-root.target"]; + }; + systemd.sockets.systemd-networkd = { + wantedBy = [ "initrd.target" ]; + before = ["initrd-switch-root.target"]; + conflicts = ["initrd-switch-root.target"]; + }; + + systemd.services.systemd-network-generator.wantedBy = [ "sysinit.target" ]; + + systemd.storePaths = [ + "${config.boot.initrd.systemd.package}/lib/systemd/systemd-networkd" + "${config.boot.initrd.systemd.package}/lib/systemd/systemd-networkd-wait-online" + "${config.boot.initrd.systemd.package}/lib/systemd/systemd-network-generator" + ]; + kernelModules = [ "af_packet" ]; + + systemd.services.nixos-flush-networkd = mkIf config.boot.initrd.network.flushBeforeStage2 { + description = "Flush Network Configuration"; + wantedBy = ["initrd.target"]; + after = ["systemd-networkd.service" "dbus.socket" "dbus.service"]; + before = ["shutdown.target" "initrd-switch-root.target"]; + conflicts = ["shutdown.target" "initrd-switch-root.target"]; + unitConfig.DefaultDependencies = false; + serviceConfig = { + # This service does nothing when starting, but brings down + # interfaces when switching root. This is the easiest way to + # ensure proper ordering while stopping. See systemd.unit(5) + # section on Before= and After=. The important part is that + # we are stopped before units we need, like dbus.service, + # and that we are stopped before starting units like + # initrd-switch-root.target + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "/bin/true"; + }; + # systemd-networkd doesn't bring down interfaces on its own + # when it exits (see: systemd-networkd(8)), so we have to do + # it ourselves. The networkctl command doesn't have a way to + # bring all interfaces down, so we have to iterate over the + # list and filter out unmanaged interfaces to bring them down + # individually. + preStop = '' + networkctl list --full --no-legend | while read _idx link _type _operational setup _; do + [ "$setup" = unmanaged ] && continue + networkctl down "$link" + done + ''; + }; + + }) + ]; + +in + +{ + options = { + systemd.network = commonOptions true; + boot.initrd.systemd.network = commonOptions "shallow"; + }; + + config = mkMerge [ + stage2Config + (mkIf config.boot.initrd.systemd.enable { + assertions = [{ + assertion = config.boot.initrd.network.udhcpc.extraArgs == []; + message = '' + boot.initrd.network.udhcpc.extraArgs is not supported when + boot.initrd.systemd.enable is enabled + ''; + }]; + + boot.initrd = stage1Config; }) ]; } |