sigil/nixos-modules/hardware/nic.nix
Emery Hemingway 8379dccf12 Refer to program and library ROMs by store path
Retrieve ROMs in the common case by full store path. This reduces
the need for route policies for driving relative requests into
absolute package paths.

Making library requests by absolute path required libraries to be
stored in the core image as such, and it follows that program
binaries should be handled in the same way. This makes requests
to core and to a file-system store more consistent, and makes
dependency detection more robust.
2021-02-16 15:46:14 +01:00

219 lines
7.2 KiB
Nix

{ config, pkgs, lib, ... }:
with lib;
{
options = {
networking.interfaces = lib.mkOption {
type = with types;
attrsOf (submodule ({ ... }: {
options.genode = {
driver = mkOption { type = types.enum [ "ipxe" "virtio" ]; };
stack = mkOption {
type = with types; nullOr (enum [ "lwip" "lxip" ]);
default = "lwip";
};
};
}));
};
};
config = {
assertions = with builtins;
let
addrCheck = name: interface: {
assertion = lessThan (length interface.ipv4.addresses) 2;
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 =
trace clientList (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:
builtins.toFile (name + ".platform-policy.dhall") ''
let Genode = env:DHALL_GENODE
in Genode.Init.Config.Policy::{
, service = "Platform"
, label = Genode.Init.LabelSelector.prefix "${name}.driver"
, content =
[ Genode.Prelude.XML.leaf
{ name = "pci"
, attributes = toMap {
, class = "ETHERNET"
, index = "${toString i}"
}
}
]
}
'') (builtins.attrNames config.networking.interfaces);
genode.core.children = mapAttrs' (name: interface:
let name' = name + ".driver";
in {
name = name';
value = let
binary = with pkgs.genodePackages;
{
ipxe = ipxe_nic_drv;
virtio = virtio_nic_drv;
}.${interface.genode.driver};
in {
inputs = [ binary ];
configFile = let
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 Init = Genode.Init
in Init.Child.flat
Init.Child.Attributes::{
, binary = "${binary}/bin/${binary.pname}"
, provides = [ "Nic" ]
, 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 = with pkgs.genodePackages;
{
lwip = vfs_lwip;
lxip = vfs_lxip;
}.${interface.genode.stack};
in {
name = name';
value = if interface.genode.stack == null then
null
else {
inputs = [ vfsPlugin ];
routeToNics = [ name ];
configFile = let
ram = {
lwip = 16;
lxip = 32;
}.${interface.genode.stack};
settings = with builtins;
[
{
name = "label";
value = name;
}
{
name = "load";
value = "${vfsPlugin}/lib/${vfsPlugin.pname}.lib.so";
}
] ++ 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 Init.Child.flat
Init.Child.Attributes::{
, binary = "${pkgs.genodePackages.vfs}/bin/vfs"
, provides = [ "File_system" ]
, resources = Init.Resources::{
, caps = 128
, ram = Genode.units.MiB ${toString ram}
}
, config = Init.Config::{
, policies =
[ Init.Config.Policy::{
, service = "File_system"
, label = Init.LabelSelector.suffix "${name'}"
, 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;
};
}