Skip to content

Commit

Permalink
move kernel version check to its own pkg (#373)
Browse files Browse the repository at this point in the history
Signed-off-by: Mohamed Mahmoud <[email protected]>
  • Loading branch information
msherif1234 authored Jul 24, 2024
1 parent 0709e78 commit 7acdf8d
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 79 deletions.
4 changes: 2 additions & 2 deletions pkg/ebpf/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"time"

"github.com/netobserv/netobserv-ebpf-agent/pkg/ifaces"
"github.com/netobserv/netobserv-ebpf-agent/pkg/kernel"
"github.com/netobserv/netobserv-ebpf-agent/pkg/metrics"
"github.com/netobserv/netobserv-ebpf-agent/pkg/utils"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/btf"
Expand Down Expand Up @@ -133,7 +133,7 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) {
return nil, fmt.Errorf("rewriting BPF constants definition: %w", err)
}

oldKernel := utils.IsKernelOlderThan("5.14.0")
oldKernel := kernel.IsKernelOlderThan("5.14.0")
if oldKernel {
log.Infof("kernel older than 5.14.0 detected: not all hooks are supported")
}
Expand Down
80 changes: 80 additions & 0 deletions pkg/kernel/kernel_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package kernel

import (
"fmt"
"regexp"
"strconv"
"strings"
"syscall"

"github.com/sirupsen/logrus"
)

var (
versionRegex = regexp.MustCompile(`^(\d+)\.(\d+).(\d+).*$`)
kernelVersion uint32
log = logrus.WithField("component", "kernel")
)

func init() {
var err error
kernelVersion, err = currentKernelVersion()
if err != nil {
log.Errorf("failed to get current kernel version: %v", err)
}
}

func IsKernelOlderThan(version string) bool {
refVersion, err := kernelVersionFromReleaseString(version)
if err != nil {
log.Warnf("failed to get kernel version from release string: %v", err)
return false
}
return kernelVersion != 0 && kernelVersion < refVersion
}

// kernelVersionFromReleaseString converts a release string with format
// 4.4.2[-1] to a kernel version number in LINUX_VERSION_CODE format.
// That is, for kernel "a.b.c", the version number will be (a<<16 + b<<8 + c)
func kernelVersionFromReleaseString(releaseString string) (uint32, error) {
versionParts := versionRegex.FindStringSubmatch(releaseString)
if len(versionParts) != 4 {
return 0, fmt.Errorf("got invalid release version %q (expected format '4.3.2-1')", releaseString)
}
major, err := strconv.Atoi(versionParts[1])
if err != nil {
return 0, err
}

minor, err := strconv.Atoi(versionParts[2])
if err != nil {
return 0, err
}

patch, err := strconv.Atoi(versionParts[3])
if err != nil {
return 0, err
}
out := major*256*256 + minor*256 + patch
return uint32(out), nil
}

func currentKernelVersion() (uint32, error) {
var buf syscall.Utsname
if err := syscall.Uname(&buf); err != nil {
return 0, err
}
releaseString := strings.Trim(utsnameStr(buf.Release[:]), "\x00")
return kernelVersionFromReleaseString(releaseString)
}

func utsnameStr[T int8 | uint8](in []T) string {
out := make([]byte, len(in))
for i := 0; i < len(in); i++ {
if in[i] == 0 {
break
}
out = append(out, byte(in[i]))
}
return string(out)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package utils
package kernel

import (
"testing"
Expand Down
76 changes: 0 additions & 76 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,8 @@ package utils
import (
"fmt"
"net"
"regexp"
"strconv"
"strings"
"syscall"

"github.com/sirupsen/logrus"
)

var (
kernelVersion uint32
log = logrus.WithField("component", "utils")
)

func init() {
var err error
kernelVersion, err = currentKernelVersion()
if err != nil {
log.Errorf("failed to get current kernel version: %v", err)
}
}

// GetSocket returns socket string in the correct format based on address family
func GetSocket(hostIP string, hostPort int) string {
socket := fmt.Sprintf("%s:%d", hostIP, hostPort)
Expand All @@ -33,60 +14,3 @@ func GetSocket(hostIP string, hostPort int) string {
}
return socket
}

func IsKernelOlderThan(version string) bool {
refVersion, err := kernelVersionFromReleaseString(version)
if err != nil {
log.Warnf("failed to get kernel version from release string: %v", err)
return false
}
return kernelVersion != 0 && kernelVersion < refVersion
}

var versionRegex = regexp.MustCompile(`^(\d+)\.(\d+).(\d+).*$`)

// kernelVersionFromReleaseString converts a release string with format
// 4.4.2[-1] to a kernel version number in LINUX_VERSION_CODE format.
// That is, for kernel "a.b.c", the version number will be (a<<16 + b<<8 + c)
func kernelVersionFromReleaseString(releaseString string) (uint32, error) {
versionParts := versionRegex.FindStringSubmatch(releaseString)
if len(versionParts) != 4 {
return 0, fmt.Errorf("got invalid release version %q (expected format '4.3.2-1')", releaseString)
}
major, err := strconv.Atoi(versionParts[1])
if err != nil {
return 0, err
}

minor, err := strconv.Atoi(versionParts[2])
if err != nil {
return 0, err
}

patch, err := strconv.Atoi(versionParts[3])
if err != nil {
return 0, err
}
out := major*256*256 + minor*256 + patch
return uint32(out), nil
}

func currentKernelVersion() (uint32, error) {
var buf syscall.Utsname
if err := syscall.Uname(&buf); err != nil {
return 0, err
}
releaseString := strings.Trim(utsnameStr(buf.Release[:]), "\x00")
return kernelVersionFromReleaseString(releaseString)
}

func utsnameStr[T int8 | uint8](in []T) string {
out := make([]byte, len(in))
for i := 0; i < len(in); i++ {
if in[i] == 0 {
break
}
out = append(out, byte(in[i]))
}
return string(out)
}

0 comments on commit 7acdf8d

Please sign in to comment.