summary refs log tree commit diff
path: root/nixos/modules/tasks
diff options
context:
space:
mode:
authorThomas Strobel <ts468@cam.ac.uk>2015-09-22 15:49:17 +0200
committerThomas Strobel <ts468@cam.ac.uk>2015-09-25 11:55:27 +0200
commit59bc47c9ede58f3cdfdfea18297375627ac99c6c (patch)
treec8f05bfa2bdc5d93e8345fef2dba0b10e69325e1 /nixos/modules/tasks
parent000a2108ba10df725065004e1f3d2fb793078f71 (diff)
downloadnixlib-59bc47c9ede58f3cdfdfea18297375627ac99c6c.tar
nixlib-59bc47c9ede58f3cdfdfea18297375627ac99c6c.tar.gz
nixlib-59bc47c9ede58f3cdfdfea18297375627ac99c6c.tar.bz2
nixlib-59bc47c9ede58f3cdfdfea18297375627ac99c6c.tar.lz
nixlib-59bc47c9ede58f3cdfdfea18297375627ac99c6c.tar.xz
nixlib-59bc47c9ede58f3cdfdfea18297375627ac99c6c.tar.zst
nixlib-59bc47c9ede58f3cdfdfea18297375627ac99c6c.zip
nixos networking: add vswitch option
Add a configuration option for Open vSwitch that is
similar to the option for the Linux kernel ethernet
bridge.
Diffstat (limited to 'nixos/modules/tasks')
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix40
-rw-r--r--nixos/modules/tasks/network-interfaces-systemd.nix3
-rw-r--r--nixos/modules/tasks/network-interfaces.nix80
3 files changed, 122 insertions, 1 deletions
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index 328d94cbb05c..d8b1592c36bb 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -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
diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix
index 8223c5a4941e..301ee43fd0e5 100644
--- a/nixos/modules/tasks/network-interfaces-systemd.nix
+++ b/nixos/modules/tasks/network-interfaces-systemd.nix
@@ -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.";
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index 9931c977e8f0..7af3160e2d42 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -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; };
+
   };
 
 }