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

Add compatibility with compressed kernel modules #2251

Merged
merged 2 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions clab/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,9 +389,11 @@ func (c *CLab) verifyLinks(ctx context.Context) error {
}

// LoadKernelModules loads containerlab-required kernel modules.
func (c *CLab) loadKernelModules() error {
func (*CLab) loadKernelModules() error {
modules := []string{"ip_tables", "ip6_tables"}

opts := []kmod.Option{
kmod.SetInitFunc(utils.ModInitFunc),
}
for _, m := range modules {
isLoaded, err := utils.IsKernelModuleLoaded(m)
if err != nil {
Expand All @@ -406,7 +408,7 @@ func (c *CLab) loadKernelModules() error {

log.Debugf("kernel module %q is not loaded. Trying to load", m)
// trying to load the kernel modules.
km, err := kmod.New()
km, err := kmod.New(opts...)
if err != nil {
log.Warnf("Unable to init module loader: %v. Skipping...", err)

Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ require (
github.com/josharian/native v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/compress v1.17.9
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
Expand Down Expand Up @@ -275,7 +275,7 @@ require (
github.com/sylabs/sif/v2 v2.18.0 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect
github.com/ulikunitz/xz v0.5.12
github.com/vbatts/tar-split v0.11.5 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
github.com/weaveworks/libgitops v0.0.0-20200611103311-2c871bbbbf0c // indirect
Expand Down
64 changes: 64 additions & 0 deletions utils/kernel_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ package utils

import (
"bufio"
"compress/gzip"
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"

"github.com/klauspost/compress/zstd"
log "github.com/sirupsen/logrus"
"github.com/ulikunitz/xz"
"golang.org/x/sys/unix"
)

// IsKernelModuleLoaded checks if a kernel module is loaded by parsing /proc/modules file.
Expand Down Expand Up @@ -95,3 +101,61 @@ func (kv *KernelVersion) GreaterOrEqual(cmpKv *KernelVersion) bool {

return true
}

// ModInitFunc supports uncompressed files and gzip and xz compressed files.
func ModInitFunc(path, params string, _ int) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close() // skipcq: GO-S2307

switch filepath.Ext(path) {
case ".gz":
rd, err := gzip.NewReader(f)
if err != nil {
return err
}
defer rd.Close()

return initModule(rd, params)
case ".xz":
rd, err := xz.NewReader(f)
if err != nil {
return err
}

return initModule(rd, params)
case ".zst":
rd, err := zstd.NewReader(f)
if err != nil {
return err
}
defer rd.Close()

return initModule(rd, params)
}

// uncompressed file, first try finitModule then initModule
if err := finitModule(int(f.Fd()), params); err != nil {
if err == unix.ENOSYS {
return initModule(f, params)
}
}

return nil
}

// finitModule inserts a module file via syscall finit_module(2).
func finitModule(fd int, params string) error {
return unix.FinitModule(fd, params, 0)
}

// initModule inserts a module via syscall init_module(2).
func initModule(rd io.Reader, params string) error {
buf, err := io.ReadAll(rd)
if err != nil {
return err
}
return unix.InitModule(buf, params)
}
Loading