Merge pull request #1432 from wkennington/bond
network-interfaces: Add the ability to create bond devices
This commit is contained in:
commit
66d930b355
@ -11,6 +11,7 @@ let
|
|||||||
ignoredInterfaces =
|
ignoredInterfaces =
|
||||||
map (i: i.name) (filter (i: i.ipAddress != null) (attrValues config.networking.interfaces))
|
map (i: i.name) (filter (i: i.ipAddress != null) (attrValues config.networking.interfaces))
|
||||||
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
|
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
|
||||||
|
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bonds))
|
||||||
++ config.networking.dhcpcd.denyInterfaces;
|
++ config.networking.dhcpcd.denyInterfaces;
|
||||||
|
|
||||||
# Config file adapted from the one that ships with dhcpcd.
|
# Config file adapted from the one that ships with dhcpcd.
|
||||||
|
@ -7,6 +7,7 @@ let
|
|||||||
cfg = config.networking;
|
cfg = config.networking;
|
||||||
interfaces = attrValues cfg.interfaces;
|
interfaces = attrValues cfg.interfaces;
|
||||||
hasVirtuals = any (i: i.virtual) interfaces;
|
hasVirtuals = any (i: i.virtual) interfaces;
|
||||||
|
hasBonds = cfg.bonds != { };
|
||||||
|
|
||||||
interfaceOpts = { name, ... }: {
|
interfaceOpts = { name, ... }: {
|
||||||
|
|
||||||
@ -228,6 +229,60 @@ in
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
networking.bonds = mkOption {
|
||||||
|
default = { };
|
||||||
|
example = {
|
||||||
|
bond0 = {
|
||||||
|
interfaces = [ "eth0" "wlan0" ];
|
||||||
|
miimon = 100;
|
||||||
|
mode = "active-backup";
|
||||||
|
};
|
||||||
|
fatpipe.interfaces = [ "enp4s0f0" "enp4s0f1" "enp5s0f0" "enp5s0f1" ];
|
||||||
|
};
|
||||||
|
description = ''
|
||||||
|
This option allows you to define bond devices that aggregate multiple,
|
||||||
|
underlying networking interfaces together. The value of this option is
|
||||||
|
an attribute set. Each attribute specifies a bond, with the attribute
|
||||||
|
name specifying the name of the bond's network interface
|
||||||
|
'';
|
||||||
|
|
||||||
|
type = types.attrsOf types.optionSet;
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
interfaces = mkOption {
|
||||||
|
example = [ "enp4s0f0" "enp4s0f1" "wlan0" ];
|
||||||
|
type = types.listOf types.string;
|
||||||
|
description = "The interfaces to bond together";
|
||||||
|
};
|
||||||
|
|
||||||
|
miimon = mkOption {
|
||||||
|
default = null;
|
||||||
|
example = 100;
|
||||||
|
type = types.nullOr types.int;
|
||||||
|
description = ''
|
||||||
|
Miimon is the number of millisecond in between each round of polling
|
||||||
|
by the device driver for failed links. By default polling is not
|
||||||
|
enabled and the driver is trusted to properly detect and handle
|
||||||
|
failure scenarios.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mode = mkOption {
|
||||||
|
default = null;
|
||||||
|
example = "active-backup";
|
||||||
|
type = types.nullOr types.string;
|
||||||
|
description = ''
|
||||||
|
The mode which the bond will be running. The default mode for
|
||||||
|
the bonding driver is balance-rr, optimizing for throughput.
|
||||||
|
More information about valid modes can be found at
|
||||||
|
https://www.kernel.org/doc/Documentation/networking/bonding.txt
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
networking.vlans = mkOption {
|
networking.vlans = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
example = {
|
example = {
|
||||||
@ -284,7 +339,15 @@ in
|
|||||||
|
|
||||||
config = {
|
config = {
|
||||||
|
|
||||||
boot.kernelModules = optional cfg.enableIPv6 "ipv6" ++ optional hasVirtuals "tun";
|
boot.kernelModules = [ ]
|
||||||
|
++ optional cfg.enableIPv6 "ipv6"
|
||||||
|
++ optional hasVirtuals "tun"
|
||||||
|
++ optional hasBonds "bonding";
|
||||||
|
|
||||||
|
boot.extraModprobeConfig =
|
||||||
|
# This setting is intentional as it prevents default bond devices
|
||||||
|
# from being created.
|
||||||
|
optionalString hasBonds "options bonding max_bonds=0";
|
||||||
|
|
||||||
environment.systemPackages =
|
environment.systemPackages =
|
||||||
[ pkgs.host
|
[ pkgs.host
|
||||||
@ -450,6 +513,9 @@ in
|
|||||||
path = [ pkgs.bridge_utils pkgs.iproute ];
|
path = [ pkgs.bridge_utils pkgs.iproute ];
|
||||||
script =
|
script =
|
||||||
''
|
''
|
||||||
|
# Remove Dead Interfaces
|
||||||
|
ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
|
||||||
|
|
||||||
brctl addbr "${n}"
|
brctl addbr "${n}"
|
||||||
|
|
||||||
# Set bridge's hello time to 0 to avoid startup delays.
|
# Set bridge's hello time to 0 to avoid startup delays.
|
||||||
@ -474,12 +540,50 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
createBondDevice = n: v:
|
||||||
|
let
|
||||||
|
deps = map (i: "sys-subsystem-net-devices-${i}.device") v.interfaces;
|
||||||
|
in
|
||||||
|
{ description = "Bond Interface ${n}";
|
||||||
|
wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ];
|
||||||
|
bindsTo = deps;
|
||||||
|
after = deps;
|
||||||
|
serviceConfig.Type = "oneshot";
|
||||||
|
serviceConfig.RemainAfterExit = true;
|
||||||
|
path = [ pkgs.ifenslave pkgs.iproute ];
|
||||||
|
script = ''
|
||||||
|
# Remove Dead Interfaces
|
||||||
|
ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
|
||||||
|
|
||||||
|
ip link add "${n}" type bond
|
||||||
|
|
||||||
|
# !!! There must be a better way to wait for the interface
|
||||||
|
while [ ! -d /sys/class/net/${n} ]; do sleep 0.1; done;
|
||||||
|
|
||||||
|
# Set the miimon and mode options
|
||||||
|
${optionalString (v.miimon != null)
|
||||||
|
"echo ${toString v.miimon} > /sys/class/net/${n}/bonding/miimon"}
|
||||||
|
${optionalString (v.mode != null)
|
||||||
|
"echo \"${v.mode}\" > /sys/class/net/${n}/bonding/mode"}
|
||||||
|
|
||||||
|
# Bring up the bridge and enslave the specified interfaces
|
||||||
|
ip link set "${n}" up
|
||||||
|
${flip concatMapStrings v.interfaces (i: ''
|
||||||
|
ifenslave "${n}" "${i}"
|
||||||
|
'')}
|
||||||
|
'';
|
||||||
|
postStop = ''
|
||||||
|
ip link set "${n}" down
|
||||||
|
ifenslave -d "${n}"
|
||||||
|
ip link delete "${n}"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
createVlanDevice = n: v:
|
createVlanDevice = n: v:
|
||||||
let
|
let
|
||||||
deps = [ "sys-subsystem-net-devices-${v.interface}.device" ];
|
deps = [ "sys-subsystem-net-devices-${v.interface}.device" ];
|
||||||
in
|
in
|
||||||
{
|
{ description = "Vlan Interface ${n}";
|
||||||
description = "Vlan Interface ${n}";
|
|
||||||
wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ];
|
wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ];
|
||||||
bindsTo = deps;
|
bindsTo = deps;
|
||||||
after = deps;
|
after = deps;
|
||||||
@ -487,6 +591,8 @@ in
|
|||||||
serviceConfig.RemainAfterExit = true;
|
serviceConfig.RemainAfterExit = true;
|
||||||
path = [ pkgs.iproute ];
|
path = [ pkgs.iproute ];
|
||||||
script = ''
|
script = ''
|
||||||
|
# Remove Dead Interfaces
|
||||||
|
ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
|
||||||
ip link add link "${v.interface}" "${n}" type vlan id "${toString v.id}"
|
ip link add link "${v.interface}" "${n}" type vlan id "${toString v.id}"
|
||||||
ip link set "${n}" up
|
ip link set "${n}" up
|
||||||
'';
|
'';
|
||||||
@ -499,6 +605,7 @@ in
|
|||||||
map configureInterface interfaces ++
|
map configureInterface interfaces ++
|
||||||
map createTunDevice (filter (i: i.virtual) interfaces))
|
map createTunDevice (filter (i: i.virtual) interfaces))
|
||||||
// mapAttrs createBridgeDevice cfg.bridges
|
// mapAttrs createBridgeDevice cfg.bridges
|
||||||
|
// mapAttrs createBondDevice cfg.bonds
|
||||||
// mapAttrs createVlanDevice cfg.vlans
|
// mapAttrs createVlanDevice cfg.vlans
|
||||||
// { "network-setup" = networkSetup; };
|
// { "network-setup" = networkSetup; };
|
||||||
|
|
||||||
|
26
pkgs/os-specific/linux/ifenslave/default.nix
Normal file
26
pkgs/os-specific/linux/ifenslave/default.nix
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{ stdenv, fetchurl }:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
name = "ifenslave-${version}";
|
||||||
|
version = "1.1.0";
|
||||||
|
|
||||||
|
src = fetchurl {
|
||||||
|
url = "mirror://debian/pool/main/i/ifenslave-2.6/ifenslave-2.6_${version}.orig.tar.gz";
|
||||||
|
sha256 = "0h9hrmy19zdksl7ys250r158b943ihbgkb95n8p4k8l0vqsby5vr";
|
||||||
|
};
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
gcc -o ifenslave ifenslave.c
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp -a ifenslave $out/bin
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Utility for enslaving networking interfaces under a bond";
|
||||||
|
license = stdenv.lib.licenses.gpl2;
|
||||||
|
platforms = stdenv.lib.platforms.linux;
|
||||||
|
};
|
||||||
|
}
|
@ -8221,6 +8221,8 @@ let
|
|||||||
|
|
||||||
id3v2 = callPackage ../applications/audio/id3v2 { };
|
id3v2 = callPackage ../applications/audio/id3v2 { };
|
||||||
|
|
||||||
|
ifenslave = callPackage ../os-specific/linux/ifenslave { };
|
||||||
|
|
||||||
ii = callPackage ../applications/networking/irc/ii { };
|
ii = callPackage ../applications/networking/irc/ii { };
|
||||||
|
|
||||||
ike = callPackage ../applications/ike { };
|
ike = callPackage ../applications/ike { };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user