Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Meta issue about kernel features dependencies #41103

Closed
teto opened this issue May 26, 2018 · 8 comments
Closed

Meta issue about kernel features dependencies #41103

teto opened this issue May 26, 2018 · 8 comments
Labels
6.topic: kernel The Linux kernel

Comments

@teto
Copy link
Member

teto commented May 26, 2018

Issue description

I develop on a custom kernel so I like to keep its configuration tight to speed up compilation time.

I've recently been dealing with packages that wouldn't work without specific kernel features.

I would like to add to packages a field kernelFeatures or requiredLinuxFeatures.

mininet = stdenv.mkDerivation {
name="mininet";
...
requiredLinuxFeatures = [ "NETNS"  ]
}

When this package is added to configuration.nix it should check that the kernel config has "NETNS" enabled. I don't believe it's possible to enable it automatically yet since we don't know the dependencies between the different kernel features (setting CONFIG_NETNS should enable CONFIG_NET but we can't do that yet).
Checking is easier though since one can grep the config and look for NETNS value.

Hopefully someone can build the kernel dependency into the structured linux config #12158

Examples:

  • usage of perf probe with modules may require COMPRESS off
@teto teto changed the title add the possibility to require or hint at kernel compilation flags add the possibility to require or hint at kernel features May 26, 2018
@symphorien
Copy link
Member

Does system.requiredKernelConfig fit your requirements ?

system.requiredKernelConfig = mkOption {
default = [];
example = literalExample ''
with config.lib.kernelConfig; [
(isYes "MODULES")
(isEnabled "FB_CON_DECOR")
(isEnabled "BLK_DEV_INITRD")
]
'';
internal = true;
type = types.listOf types.attrs;
description = ''
This option allows modules to specify the kernel config options that
must be set (or unset) for the module to work. Please use the
lib.kernelConfig functions to build list elements.
'';
};
};

@coretemp
Copy link
Contributor

@symphorien Your system wouldn't work outside of NixOS for example.

He wants to have it as part of the responsibility of the packager, not as part of the person who creates a module. I agree that the packager is the best person to specify required kernel modules.

There should also be flags to ignore this feature.

@teto
Copy link
Member Author

teto commented May 28, 2018

It is as @coretemp says. Basically I want the kernel config to depend on programs requirement rather than having to specify

For instance, if I add the openvswitch program to my system, I would expect my kernel to be rebuilt with CONFIG_OPENVSWITCH without any manual intervention. Or maybe easier as a first step have nixos-rebuild error out so that I can add it to my config.

As nixpkgs is crossplatform, I am not sure what the best API would be but the idea fits with nixos mindset imo.

@teto
Copy link
Member Author

teto commented May 28, 2018

Interestingly enough, at least for services/programs one can use boot.kernelPatches to achieve this it seems:
https://github.com/NixOS/nixpkgs/blob/release-18.03/nixos/modules/misc/crashdump.nix

@teto
Copy link
Member Author

teto commented May 28, 2018

I've started playing with the idea and it makes things easier but the kernel configuration system in nix is too brittle to use this to build the kernel config automatically,

  kernelExtraConfig = ''
          # ideally we should just have to switch OPENVSWITCH on and let nix enable the dependencies
          OPENVSWITCH y

         # but I do it manually & imperfectly.
          NF_INET y
          NF_CONNTRACK y

          NF_NAT y
          NF_NAT_IPV4 y
  '';

I wanted to do nixos/modules/virtualisation/openvswitch.nix

    boot.kernelPatches = [ {
        name = "openvswitch";
        patch = null;
        extraConfig = pkgs.openvswitch.kernelExtraConfig;
        } ];

but that caused some problems so I still manually specify the kernel config, just a bit better via
mykernel = super.linux_latest.override { extraConfig=pkgs.openvswitch.kernelExtraConfig; }.

With the current system we might have several contradicting values for CONFIG_OPENVSWITCH, it seems like the current generate-config.pl will just use the last value. It may be good to display a warning if $requiredAnswers{$1} is already defined in $requiredAnswers{$1} = !(defined $2); :

open ANSWERS, "<$ENV{KERNEL_CONFIG}" or die "Could not open answer file";
while (<ANSWERS>) {
    chomp;
    s/#.*//;
    if (/^\s*([A-Za-z0-9_]+)(\?)?\s+(\S+)\s*$/) {
        $answers{$1} = $3;
        $requiredAnswers{$1} = !(defined $2);
    } elsif (!/^\s*$/) {
        die "invalid config line: $_";
    }
}
close ANSWERS;

Also I alternate between building builtin modules (to use with qemu -kernel , this way I don't have to build the initramfs) and typical kernels. But the current system seems to

my $answer = "";
# Build everything as a module if possible.
$answer = "m" if $autoModules && $alts =~ /\/m/ && !($preferBuiltin && $alts =~ /Y/);
# `OPENVSWITCH m` in extraConfig will override the $preferBuiltin
$answer = $answers{$name} if defined $answers{$name};

so one should write in extraConfig sthg akin to "OPENVSWITCH ${if preferBuiltin then "y" else "m"}", there is an opportunity for an alias there.

@teto
Copy link
Member Author

teto commented Jan 28, 2019

Not sure where to post this trick, I just want to write down some experience I've had into merging 2 configs.
I usually run tests on kernels in VMs but from times to times, it's more practical to run them in the host (when custom userspace components are involved for instance).

It turns out that I've had some problems with merging the config from my (development) test kernel and the one from my host. I've tried concating nix's extraConfig. Turns out kernel config is a complex beast and even with the adequate preferBuiltin and autoModules options of buildLinux, I still reached a non valid configuration. I had some success running make menuconfig, looking at the "selected by" entry and force values for these options. Yet myu kernel was still missing some drivers to make it run on my host. I thus decided to stop trying to merge configs via nix and discovered the scripts/kconfig/merge_config.sh script which allows to merge fragments via:
KCONFIG_CONFIG=out.config scripts/kconfig/merge_config.sh main.config fragment.config

I tried to merge the 2 full configs (from my VM with the experimental settings and the other being my host config with the correct drivers enabled). At first I got surprised that the merge was removing the drivers I desperately wanted but the output explains a bit the results. Comments such as # CONFIG_TULIP_MWI is not set are interpreted as CONFIG_TULIP_MWI disabled hence it was disabled during the merge. As I wanted the union of configs rather than their intersection,
I edited the command with vim :g/is not set$/d to keep only items I wanted.

I mention this because with the lack of automated dependency resolution, it can be hard to build the desired .config file and I believe scripts/kconfig/merge_config.sh could prove to be a helpful (interactive) way to fix/help build new kernel configs.

@teto
Copy link
Member Author

teto commented Feb 13, 2019

Now that structured kernel config is available upstream, we can decide on an API. Some random thoughts:

Current mechanisms are just checks but I propose to add an option that proactively enforces kernel options.
(A drawback is that custom kernel configurations invalidate the cache, well it's already the case for me).

    system.requiredKernelConfig = with config.lib.kernelConfig; [
      (isYes "SERIAL_8250_CONSOLE")
      (isYes "SERIAL_8250")
    ];

system.requiredKernelConfig is used in

  • minimal-kernel.nix:
    (map (builtins.getAttr "configLine") config.system.requiredKernelConfig))

  • and in nixos/modules/system/boot/kernel.nix|

    # nixpkgs kernels are assumed to have all required features
    assertions = if config.boot.kernelPackages.kernel ? features then [] else
      let cfg = config.boot.kernelPackages.kernel.config; in map (attrs:
        { assertion = attrs.assertion cfg; inherit (attrs) message; }
      ) config.system.requiredKernelConfig;

I would like to update these configs with structured kernel configs (see a bit later on how to use it).

I would like packages to be able to communicate their configuration/needs, for instance installing openvswitch should turn on CONFIG_OPENVSWITCH. This should be done independently of the nixos modules as some packages can be installed without modules/overriden etc. Like mininet requires the kernel to support namespaces. meta.kernel.requiredConfig = [ NET_NS ] etc.
Now I wonder how to pass on those dependencies to the kernel configuration. Should the kernel depend on all packages and check for their config requirements ?

At this point, it should be ok to add a boot.kernel.structuredConfig setting. (already exists: system.requiredKernelConfig).

teto added a commit to teto/home that referenced this issue Mar 1, 2019
@teto teto added the 6.topic: kernel The Linux kernel label Apr 24, 2019
@teto teto changed the title add the possibility to require or hint at kernel features Meta issue about kernel features dependencies Aug 21, 2019
@teto
Copy link
Member Author

teto commented Sep 18, 2019

closed in favor of #69014

@teto teto closed this as completed Sep 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: kernel The Linux kernel
Projects
None yet
Development

No branches or pull requests

3 participants