nixos networking: add vswitch option
Add a configuration option for Open vSwitch that is similar to the option for the Linux kernel ethernet bridge.
This commit is contained in:
parent
000a2108ba
commit
59bc47c9ed
4 changed files with 123 additions and 1 deletions
|
@ -18,6 +18,7 @@ let
|
|||
map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ip4 != [ ] || i.ipAddress != null) interfaces)
|
||||
++ mapAttrsToList (i: _: i) config.networking.sits
|
||||
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
|
||||
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.vswitches))
|
||||
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bonds))
|
||||
++ config.networking.dhcpcd.denyInterfaces;
|
||||
|
||||
|
|
|
@ -220,6 +220,45 @@ in
|
|||
'';
|
||||
});
|
||||
|
||||
createVswitchDevice = n: v: nameValuePair "${n}-netdev"
|
||||
(let
|
||||
managedInterfaces = filter (x: hasAttr x cfg.interfaces) v.interfaces;
|
||||
managedInterfaceServices = concatMap (i: [ "network-addresses-${i}.service" "network-link-${i}.service" ]) managedInterfaces;
|
||||
virtualInterfaces = filter (x: (hasAttr x cfg.interfaces) && cfg.interfaces.${x}.virtual) v.interfaces;
|
||||
virtualInterfaceServices = concatMap (i: [ "${i}-netdev.service" ]) virtualInterfaces;
|
||||
deps = map subsystemDevice v.interfaces;
|
||||
ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
|
||||
in
|
||||
{ description = "Open vSwitch Interface ${n}";
|
||||
wantedBy = [ "network.target" "vswitchd.service" (subsystemDevice n) ];
|
||||
requires = optionals v.bindInterfaces (deps ++ managedInterfaceServices ++ virtualInterfaceServices);
|
||||
requiredBy = optionals v.bindInterfaces (managedInterfaceServices ++ virtualInterfaceServices);
|
||||
bindsTo = deps ++ [ "vswitchd.service" ];
|
||||
partOf = [ "vswitchd.service" ];
|
||||
after = [ "network-pre.target" "vswitchd.service" ] ++ deps ++ managedInterfaceServices ++ virtualInterfaceServices;
|
||||
before = [ "network-interfaces.target" (subsystemDevice n) ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [ pkgs.iproute config.virtualisation.vswitch.package ];
|
||||
script = ''
|
||||
echo "Removing old Open vSwitch ${n}..."
|
||||
ovs-vsctl --if-exists del-br ${n}
|
||||
|
||||
echo "Adding Open vSwitch ${n}..."
|
||||
ovs-vsctl -- add-br ${n} ${concatMapStrings (i: " -- add-port ${n} ${i}") v.interfaces} \
|
||||
${concatMapStrings (x: " -- set-controller ${n} " + x) v.controllers} \
|
||||
${concatMapStrings (x: " -- " + x) (splitString "\n" v.extraOvsctlCmds)}
|
||||
|
||||
echo "Adding OpenFlow rules for Open vSwitch ${n}..."
|
||||
ovs-ofctl add-flows ${n} ${ofRules}
|
||||
'';
|
||||
postStop = ''
|
||||
ip link set ${n} down || true
|
||||
ovs-ofctl del-flows ${n} || true
|
||||
ovs-vsctl --if-exists del-br ${n}
|
||||
'';
|
||||
});
|
||||
|
||||
createBondDevice = n: v: nameValuePair "${n}-netdev"
|
||||
(let
|
||||
deps = map subsystemDevice v.interfaces;
|
||||
|
@ -335,6 +374,7 @@ in
|
|||
map configureAddrs interfaces ++
|
||||
map createTunDevice (filter (i: i.virtual) interfaces))
|
||||
// mapAttrs' createBridgeDevice cfg.bridges
|
||||
// mapAttrs' createVswitchDevice cfg.vswitches
|
||||
// mapAttrs' createBondDevice cfg.bonds
|
||||
// mapAttrs' createMacvlanDevice cfg.macvlans
|
||||
// mapAttrs' createSitDevice cfg.sits
|
||||
|
|
|
@ -35,6 +35,9 @@ in
|
|||
assertions = [ {
|
||||
assertion = cfg.defaultGatewayWindowSize == null;
|
||||
message = "networking.defaultGatewayWindowSize is not supported by networkd.";
|
||||
} {
|
||||
assertion = cfg.vswitches == {};
|
||||
message = "networking.vswichtes are not supported by networkd.";
|
||||
} ] ++ flip mapAttrsToList cfg.bridges (n: { rstp, ... }: {
|
||||
assertion = !rstp;
|
||||
message = "networking.bridges.${n}.rstp is not supported by networkd.";
|
||||
|
|
|
@ -12,7 +12,8 @@ let
|
|||
hasBonds = cfg.bonds != { };
|
||||
|
||||
slaves = concatMap (i: i.interfaces) (attrValues cfg.bonds)
|
||||
++ concatMap (i: i.interfaces) (attrValues cfg.bridges);
|
||||
++ concatMap (i: i.interfaces) (attrValues cfg.bridges)
|
||||
++ concatMap (i: i.interfaces) (attrValues cfg.vswitches);
|
||||
|
||||
slaveIfs = map (i: cfg.interfaces.${i}) (filter (i: cfg.interfaces ? ${i}) slaves);
|
||||
|
||||
|
@ -371,6 +372,81 @@ in
|
|||
options = [ interfaceOpts ];
|
||||
};
|
||||
|
||||
networking.vswitches = mkOption {
|
||||
default = { };
|
||||
example =
|
||||
{ vs0.interfaces = [ "eth0" "eth1" ];
|
||||
vs1.interfaces = [ "eth2" "wlan0" ];
|
||||
};
|
||||
description =
|
||||
''
|
||||
This option allows you to define Open vSwitches that connect
|
||||
physical networks together. The value of this option is an
|
||||
attribute set. Each attribute specifies a vswitch, with the
|
||||
attribute name specifying the name of the vswitch's network
|
||||
interface.
|
||||
'';
|
||||
|
||||
type = types.attrsOf types.optionSet;
|
||||
|
||||
options = {
|
||||
|
||||
interfaces = mkOption {
|
||||
example = [ "eth0" "eth1" ];
|
||||
type = types.listOf types.str;
|
||||
description =
|
||||
"The physical network interfaces connected by the vSwitch.";
|
||||
};
|
||||
|
||||
bindInterfaces = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If true, then the interfaces of the vSwitch are brought 'up' and especially
|
||||
also 'down' together with the vSwitch. That requires that every interfaces
|
||||
is configured as a systemd network services.
|
||||
'';
|
||||
};
|
||||
|
||||
controllers = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "ptcp:6653:[::1]" ];
|
||||
description = ''
|
||||
Specify the controller targets. For the allowed options see <literal>man 8 ovs-vsctl</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
openFlowRules = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = ''
|
||||
actions=normal
|
||||
'';
|
||||
description = ''
|
||||
OpenFlow rules to insert into the Open vSwitch. All <literal>openFlowRules</literal> are
|
||||
loaded with <literal>ovs-ofctl</literal> within one atomic operation.
|
||||
'';
|
||||
};
|
||||
|
||||
extraOvsctlCmds = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = ''
|
||||
set-fail-mode <switch_name> secure
|
||||
set Bridge <switch_name> stp_enable=true
|
||||
'';
|
||||
description = ''
|
||||
Commands to manipulate the Open vSwitch database. Every line executed with <literal>ovs-vsctl</literal>.
|
||||
All commands are bundled together with the operations for adding the interfaces
|
||||
into one atomic operation.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
networking.bridges = mkOption {
|
||||
default = { };
|
||||
example =
|
||||
|
@ -766,6 +842,8 @@ in
|
|||
|
||||
services.mstpd = mkIf needsMstpd { enable = true; };
|
||||
|
||||
virtualisation.vswitch = mkIf (cfg.vswitches != { }) { enable = true; };
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue