nixos: add uplink option to children

Add an option to genode.core.children and genode.init.children
for specifying a Nic driver for the exclusive use of the child
for which it is added. This mechanism is to support the nic_router
but it is reusable for arbitrary children.
This commit is contained in:
Ehmry - 2021-03-12 18:50:40 +01:00
parent de98f23758
commit a91dda99d8
5 changed files with 116 additions and 169 deletions

View File

@ -4,7 +4,8 @@ with lib;
let let
localPackages = pkgs.buildPackages; localPackages = pkgs.buildPackages;
children' = config.lib.children.freeze config.genode.core.children; children' = config.lib.children.freeze
(config.genode.core.children // config.genode.core.supportChildren);
coreErisCaps = with builtins; coreErisCaps = with builtins;
let pkgNames = [ "rtc_drv" ]; let pkgNames = [ "rtc_drv" ];
@ -26,9 +27,12 @@ let
net = [ ]; net = [ ];
}.${config.genode.boot.storeBackend}; }.${config.genode.boot.storeBackend};
coreInputs = with builtins; coreInputs =
# TODO: get rid of this?
with builtins;
concatMap (getAttr "extraInputs") concatMap (getAttr "extraInputs")
(attrValues config.genode.core.children); ((attrValues config.genode.core.children)
++ (attrValues config.genode.core.supportChildren));
mergeManifests = inputs: mergeManifests = inputs:
with builtins; with builtins;
@ -150,6 +154,14 @@ in {
''; '';
}; };
supportChildren = config.lib.types.children { extraOptions = { }; } // {
internal = true;
description = ''
Children added to support other children, such as drivers.
Do not manually add children here.
'';
};
}; };
boot = { boot = {

View File

@ -70,7 +70,7 @@ with lib;
, Init.ServiceRoute.parent "IO_PORT" , Init.ServiceRoute.parent "IO_PORT"
] ]
, config = Init.Config::{ , config = Init.Config::{
, policies = [ ${toString policies} ] , policies = [ ${toString policies} ] : List Init.Config.Policy.Type
} }
} }
''; '';

View File

@ -23,193 +23,97 @@ with lib;
}; };
config = { config =
# TODO: create drivers in both the first and second level inits
{
assertions = with builtins; assertions = with builtins;
let let
addrCheck = name: interface: { addrCheck = name: interface: {
assertion = lessThan (length interface.ipv4.addresses) 2; assertion = lessThan (length interface.ipv4.addresses) 2;
message = "Genode interfaces do not support multihoming."; message = "Genode interfaces do not support multihoming.";
};
routeCheck = name: interface: {
assertion = lessThan (length interface.ipv4.routes) 2;
message = "Genode interfaces do not support multiple routes.";
};
policyCheck = name: interface:
let
clientList = filter (x: x != null) (lib.mapAttrsToList
(childName: value:
if any (nic: nic == name) value.routeToNics then
childName
else
null) config.genode.init.children);
in {
assertion = clientList == [ ] || length clientList == 1;
message = "Multiple routes to Nic ${name}, ${clientList}";
}; };
in lib.lists.concatMap routeCheck = name: interface: {
(f: lib.mapAttrsToList f config.networking.interfaces) [ assertion = lessThan (length interface.ipv4.routes) 2;
addrCheck message = "Genode interfaces do not support multiple routes.";
routeCheck };
policyCheck policyCheck = name: interface:
]; let
clientList = filter (x: x != null) (lib.mapAttrsToList
(childName: value:
if any (nic: nic == name) value.routeToNics then
childName
else
null) config.genode.core.children);
in {
assertion = clientList == [ ] || length clientList == 1;
message = "Multiple routes to Nic ${name}, ${clientList}";
};
in lib.lists.concatMap
(f: lib.mapAttrsToList f config.networking.interfaces) [
addrCheck
routeCheck
policyCheck
];
hardware.genode.platform.policies = lib.lists.imap0 (i: name: hardware.genode.platform.policies = let
builtins.toFile (name + ".platform-policy.dhall") '' mkPolicy = { name, platformPolicy }:
let Genode = env:DHALL_GENODE pkgs.writeText "${name}.policy.dhall" ''${platformPolicy} "${name}"'';
in Genode.Init.Config.Policy::{ childPolicies = builtins.concatLists (lib.attrsets.mapAttrsToList
, service = "Platform" (child: childAttrs:
, label = Genode.Init.LabelSelector.prefix "${name}.driver" lib.attrsets.mapAttrsToList (uplink: uplinkAttrs:
, content = mkPolicy {
[ Genode.Prelude.XML.leaf name = "${child}-${uplink}.driver";
{ name = "pci" inherit (uplinkAttrs) platformPolicy;
, attributes = toMap { }) childAttrs.uplinks) config.genode.core.children);
, class = "ETHERNET"
, index = "${toString i}"
}
}
]
}
'') (builtins.attrNames config.networking.interfaces);
genode.core.children = mapAttrs' (name: interface: in childPolicies;
let name' = name + ".driver";
in { genode.core.supportChildren = let
name = name';
value = { mkUplinkDriver = { policyPrefix, driver, verbose }: {
package = with pkgs.genodePackages; package = with pkgs.genodePackages;
{ {
ipxe = ipxe_nic_drv; ipxe = ipxe_nic_drv;
virtio = virtio_nic_drv; virtio = virtio_nic_drv;
}.${interface.genode.driver}; }.${driver};
configFile = let configFile = pkgs.writeText "driver.dhall" ''
policy = lib.mapAttrsToList (childName: value:
if any (nic: nic == name) value.routeToNics then ''
Init.Config.Policy::{
, service = "Nic"
, label = Init.LabelSelector.prefix "nixos -> ${childName}"
}
'' else
"") config.genode.init.children;
in pkgs.writeText "${name'}.dhall" ''
let Genode = env:DHALL_GENODE let Genode = env:DHALL_GENODE
let Init = Genode.Init let Init = Genode.Init
in λ(binary : Text) -> Init.Child.flat in λ(binary : Text)
Init.Child.Attributes::{ Init.Child.flat
, binary
, resources = Init.Resources::{ caps = 128, ram = Genode.units.MiB 4 }
, routes = [ Init.ServiceRoute.parent "IO_MEM" ]
, config = Init.Config::{
, attributes = toMap { verbose = "true" }
, policies = [ ${
toString policy
} ] : List Init.Config.Policy.Type
}
}
'';
};
}) config.networking.interfaces;
genode.init.children = let
sockets = mapAttrs' (name: interface:
let
name' = name + ".sockets";
vfsPlugin = lib.getEris "lib" (with pkgs.genodePackages;
{
lwip = vfs_lwip;
lxip = vfs_lxip;
}.${interface.genode.stack});
in {
name = name';
value = if interface.genode.stack == null then
null
else {
package = pkgs.genodePackages.vfs;
extraErisInputs = [ vfsPlugin ];
routeToNics = [ name ];
configFile = let
ram = {
lwip = 16;
lxip = 32;
}.${interface.genode.stack};
settings = with builtins;
[
{
name = "label";
value = name;
}
{
name = "load";
value = vfsPlugin.cap;
}
] ++ lib.optionals (interface.ipv4.addresses != [ ])
(let addr = head interface.ipv4.addresses;
in [
{
name = "ip_addr";
value = addr.address;
}
{
name = "netmask";
value = if addr.prefixLength == 24 then
"255.255.255.0"
else
throw "missing prefix to netmask conversion";
}
]) ++ lib.optional (interface.ipv4.routes != [ ])
(let route = head interface.ipv4.routes;
in {
name = "gateway";
value = route.address;
}) ++ lib.optional (interface.useDHCP != null) {
name = "dhcp";
value = if interface.useDHCP then "true" else "false";
};
settingsMap = builtins.concatStringsSep ", " (map
({ name, value }:
''{ mapKey = "${name}", mapValue = "${value}" }'') settings);
in pkgs.writeText "${name'}.dhall" ''
let Genode = env:DHALL_GENODE
let Init = Genode.Init
in λ(binary : Text) -> Init.Child.flat
Init.Child.Attributes::{ Init.Child.Attributes::{
, binary , binary
, provides = [ "File_system" ] , resources = Init.Resources::{ caps = 128, ram = Genode.units.MiB 4 }
, resources = Init.Resources::{ , routes = [ Init.ServiceRoute.parent "IO_MEM" ]
, caps = 128
, ram = Genode.units.MiB ${toString ram}
}
, config = Init.Config::{ , config = Init.Config::{
, attributes = toMap { verbose = "${
if verbose then "yes" else "no"
}" }
, policies = , policies =
[ Init.Config.Policy::{ [ Init.Config.Policy::{
, service = "File_system" , service = "Nic"
, label = Init.LabelSelector.suffix "${name'}" , label = Init.LabelSelector.prefix "${policyPrefix}"
, attributes = toMap { root = "/", writeable="yes" }
} }
] ]
, content =
let VFS = Genode.VFS
in [ VFS.vfs
[ VFS.leafAttrs
"plugin"
([ ${settingsMap} ] : Genode.Prelude.Map.Type Text Text)
]
]
} }
} }
''; '';
}; };
}) config.networking.interfaces;
in lib.filterAttrs (n: v: v != null) sockets; otherDrivers = builtins.concatLists (lib.attrsets.mapAttrsToList
(child: childAttrs:
}; lib.attrsets.mapAttrsToList (uplink: uplinkAttrs: {
name = "${child}-${uplink}.driver";
value = mkUplinkDriver {
policyPrefix = "${child} -> ${uplink}";
inherit (uplinkAttrs) driver verbose;
};
}) childAttrs.uplinks) config.genode.core.children);
in builtins.listToAttrs otherDrivers;
};
} }

View File

@ -61,6 +61,8 @@
example = literalExample "pkg.genodePackages.init"; example = literalExample "pkg.genodePackages.init";
}; };
uplinks = import ./uplinks-option.nix { inherit lib; };
} // extraOptions; } // extraOptions;
}); });
}; };

View File

@ -0,0 +1,29 @@
{ lib }:
with lib;
mkOption {
default = { };
type = with types;
attrsOf (submodule {
options = {
driver = mkOption { type = types.enum [ "ipxe" "virtio" ]; };
platformPolicy = mkOption {
type = types.path;
default = builtins.toFile "driver.policy.dhall" ''
let Genode = env:DHALL_GENODE
in λ(driverName : Text)
Genode.Init.Config.Policy::{
, service = "Platform"
, label = Genode.Init.LabelSelector.prefix driverName
, content =
[ Genode.Prelude.XML.leaf
{ name = "pci", attributes = toMap { class = "ETHERNET" } }
]
}
'';
};
verbose = lib.mkEnableOption "verbose driver logging";
};
});
}