Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
virtcontainers: add support for loading kernel modules
Browse files Browse the repository at this point in the history
The list of kernel modules can be passed to the runtime through the
configuration file or using OCI annotations. In both cases, a list paramentes
can be specified for each module.

fixes #1925

Signed-off-by: Julio Montes <julio.montes@intel.com>
  • Loading branch information
Julio Montes committed Aug 1, 2019
1 parent 74157c8 commit 6b174a7
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 39 deletions.
8 changes: 8 additions & 0 deletions cli/config/configuration-fc.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ path = "@SHIMPATH@"
#trace_mode = "dynamic"
#trace_type = "isolated"

# Comma separated list of kernel modules and their parameters.
# These modules will be loaded in the guest kernel using modprobe(8).
# The following example can be used to load two kernel modules with parameters
# - kernel_modules=["e1000e InterruptThrottleRate=3000,3000,3000 EEE=1", "i915 enable_ppgtt=0"]
# The first word is considered as the module name and the rest as its parameters.
#
kernel_modules=[]

[netmon]
# If enabled, the network monitoring process gets started when the
# sandbox is created. This allows for the detection of some additional
Expand Down
8 changes: 8 additions & 0 deletions cli/config/configuration-nemu.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,14 @@ path = "@SHIMPATH@"
#trace_mode = "dynamic"
#trace_type = "isolated"

# Comma separated list of kernel modules and their parameters.
# These modules will be loaded in the guest kernel using modprobe(8).
# The following example can be used to load two kernel modules with parameters
# - kernel_modules=["e1000e InterruptThrottleRate=3000,3000,3000 EEE=1", "i915 enable_ppgtt=0"]
# The first word is considered as the module name and the rest as its parameters.
#
kernel_modules=[]

[netmon]
# If enabled, the network monitoring process gets started when the
# sandbox is created. This allows for the detection of some additional
Expand Down
9 changes: 9 additions & 0 deletions cli/config/configuration-qemu.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,15 @@ path = "@SHIMPATH@"
#trace_mode = "dynamic"
#trace_type = "isolated"

# Comma separated list of kernel modules and their parameters.
# These modules will be loaded in the guest kernel using modprobe(8).
# The following example can be used to load two kernel modules with parameters
# - kernel_modules=["e1000e InterruptThrottleRate=3000,3000,3000 EEE=1", "i915 enable_ppgtt=0"]
# The first word is considered as the module name and the rest as its parameters.
#
kernel_modules=[]


[netmon]
# If enabled, the network monitoring process gets started when the
# sandbox is created. This allows for the detection of some additional
Expand Down
31 changes: 19 additions & 12 deletions pkg/katautils/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,11 @@ type shim struct {
}

type agent struct {
Debug bool `toml:"enable_debug"`
Tracing bool `toml:"enable_tracing"`
TraceMode string `toml:"trace_mode"`
TraceType string `toml:"trace_type"`
Debug bool `toml:"enable_debug"`
Tracing bool `toml:"enable_tracing"`
TraceMode string `toml:"trace_mode"`
TraceType string `toml:"trace_type"`
KernelModules []string `toml:"kernel_modules"`
}

type netmon struct {
Expand Down Expand Up @@ -452,6 +453,10 @@ func (a agent) traceType() string {
return a.TraceType
}

func (a agent) kernelModules() []string {
return a.KernelModules
}

func (n netmon) enable() bool {
return n.Enable
}
Expand Down Expand Up @@ -788,9 +793,10 @@ func updateRuntimeConfigAgent(configPath string, tomlConf tomlConfig, config *oc

config.AgentType = vc.KataContainersAgent
config.AgentConfig = vc.KataAgentConfig{
LongLiveConn: true,
UseVSock: config.HypervisorConfig.UseVSock,
Debug: agentConfig.Debug,
LongLiveConn: true,
UseVSock: config.HypervisorConfig.UseVSock,
Debug: agentConfig.Debug,
KernelModules: agentConfig.KernelModules,
}

return nil
Expand All @@ -801,11 +807,12 @@ func updateRuntimeConfigAgent(configPath string, tomlConf tomlConfig, config *oc
case kataAgentTableType:
config.AgentType = vc.KataContainersAgent
config.AgentConfig = vc.KataAgentConfig{
UseVSock: config.HypervisorConfig.UseVSock,
Debug: agent.debug(),
Trace: agent.trace(),
TraceMode: agent.traceMode(),
TraceType: agent.traceType(),
UseVSock: config.HypervisorConfig.UseVSock,
Debug: agent.debug(),
Trace: agent.trace(),
TraceMode: agent.traceMode(),
TraceType: agent.traceType(),
KernelModules: agent.kernelModules(),
}
default:
return fmt.Errorf("%s agent type is not supported", k)
Expand Down
89 changes: 62 additions & 27 deletions virtcontainers/kata_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,13 @@ const (
// KataAgentConfig is a structure storing information needed
// to reach the Kata Containers agent.
type KataAgentConfig struct {
LongLiveConn bool
UseVSock bool
Debug bool
Trace bool
TraceMode string
TraceType string
LongLiveConn bool
UseVSock bool
Debug bool
Trace bool
TraceMode string
TraceType string
KernelModules []string
}

type kataVSOCK struct {
Expand Down Expand Up @@ -138,6 +139,7 @@ type kataAgent struct {
proxyBuiltIn bool
dynamicTracing bool
dead bool
kmodules []string

vmSocket interface{}
ctx context.Context
Expand Down Expand Up @@ -270,6 +272,7 @@ func (k *kataAgent) init(ctx context.Context, sandbox *Sandbox, config interface

disableVMShutdown = k.handleTraceSettings(c)
k.keepConn = c.LongLiveConn
k.kmodules = c.KernelModules
default:
return false, vcTypes.ErrInvalidConfigType
}
Expand Down Expand Up @@ -743,6 +746,58 @@ func (k *kataAgent) startSandbox(sandbox *Sandbox) error {
return err
}

storages := setupStorages(sandbox)

kmodules := setupKernelModules(k.kmodules)

req := &grpc.CreateSandboxRequest{
Hostname: hostname,
Storages: storages,
SandboxPidns: sandbox.sharePidNs,
SandboxId: sandbox.id,
GuestHookPath: sandbox.config.HypervisorConfig.GuestHookPath,
KernelModules: kmodules,
}

_, err = k.sendReq(req)
if err != nil {
return err
}

if k.dynamicTracing {
_, err = k.sendReq(&grpc.StartTracingRequest{})
if err != nil {
return err
}
}

return nil
}

func setupKernelModules(kmodules []string) []*grpc.KernelModule {
modules := []*grpc.KernelModule{}

for _, m := range kmodules {
l := strings.Fields(m)
if len(l) == 0 {
continue
}

module := &grpc.KernelModule{Name: l[0]}
modules = append(modules, module)
if len(l) == 1 {
continue
}

for _, p := range l[1:] {
module.Parameters = append(module.Parameters, p)
}
}

return modules
}

func setupStorages(sandbox *Sandbox) []*grpc.Storage {
storages := []*grpc.Storage{}
caps := sandbox.hypervisor.capabilities()

Expand Down Expand Up @@ -793,27 +848,7 @@ func (k *kataAgent) startSandbox(sandbox *Sandbox) error {
storages = append(storages, shmStorage)
}

req := &grpc.CreateSandboxRequest{
Hostname: hostname,
Storages: storages,
SandboxPidns: sandbox.sharePidNs,
SandboxId: sandbox.id,
GuestHookPath: sandbox.config.HypervisorConfig.GuestHookPath,
}

_, err = k.sendReq(req)
if err != nil {
return err
}

if k.dynamicTracing {
_, err = k.sendReq(&grpc.StartTracingRequest{})
if err != nil {
return err
}
}

return nil
return storages
}

func (k *kataAgent) stopSandbox(sandbox *Sandbox) error {
Expand Down
13 changes: 13 additions & 0 deletions virtcontainers/pkg/annotations/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ const (

// ContainerTypeKey is the annotation key to fetch container type.
ContainerTypeKey = vcAnnotationsPrefix + "pkg.oci.container_type"

// KernelModules is the annotation key for passing the list of kernel
// modules and their parameters that will be loaded in the guest kernel.
// Semicolon separated list of kernel modules and their parameters.
// These modules will be loaded in the guest kernel using modprobe(8).
// The following example can be used to load two kernel modules with parameters
///
// annotations:
// com.github.containers.virtcontainers.KernelModules: "e1000e InterruptThrottleRate=3000,3000,3000 EEE=1; i915 enable_ppgtt=0"
//
// The first word is considered as the module name and the rest as its parameters.
//
KernelModules = vcAnnotationsPrefix + "KernelModules"
)

const (
Expand Down
9 changes: 9 additions & 0 deletions virtcontainers/pkg/oci/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ const (
StatePaused = "paused"
)

const KernelModulesSeparator = ";"

// CompatOCIProcess is a structure inheriting from spec.Process defined
// in runtime-spec/specs-go package. The goal is to be compatible with
// both v1.0.0-rc4 and v1.0.0-rc5 since the latter introduced a change
Expand Down Expand Up @@ -451,6 +453,13 @@ func addAssetAnnotations(ocispec CompatOCISpec, config *vc.SandboxConfig) {

config.Annotations[a] = value
}

if value, ok := ocispec.Annotations[vcAnnotations.KernelModules]; ok {
if c, ok := config.AgentConfig.(*vc.KataAgentConfig); ok {
modules := strings.Split(value, KernelModulesSeparator)
c.KernelModules = modules
}
}
}

// SandboxConfig converts an OCI compatible runtime configuration file
Expand Down

0 comments on commit 6b174a7

Please sign in to comment.