mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Use hostos.KernelVersion everywhere, and have it return semver strings
PiperOrigin-RevId: 460872657
This commit is contained in:
committed by
gVisor bot
parent
63bb6e7e69
commit
2ceb6bb1f8
@@ -22,14 +22,14 @@ import (
|
||||
)
|
||||
|
||||
func TestEnable(t *testing.T) {
|
||||
major, minor, err := hostos.KernelVersion()
|
||||
version, err := hostos.KernelVersion()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to parse kernel version: %v", err)
|
||||
}
|
||||
// Skip running test when running on Linux kernel < 5.14 because core tagging
|
||||
// is not available.
|
||||
if major < 5 && minor < 14 {
|
||||
t.Skipf("Running on Linux kernel: %d.%d < 5.14. Core tagging not available. Skipping test.", major, minor)
|
||||
if version.LessThan(5, 14) {
|
||||
t.Skipf("Running on Linux kernel: %s < 5.14. Core tagging not available. Skipping test.", version)
|
||||
return
|
||||
}
|
||||
if err := Enable(); err != nil {
|
||||
|
||||
@@ -17,38 +17,40 @@
|
||||
|
||||
package cpuid
|
||||
|
||||
func archSkipFeature(feature Feature, major, minor int) bool {
|
||||
import "gvisor.dev/gvisor/pkg/hostos"
|
||||
|
||||
func archSkipFeature(feature Feature, version hostos.Version) bool {
|
||||
switch {
|
||||
// Block 0.
|
||||
case feature == X86FeatureSDBG && (major < 4 || major == 4 && minor < 3):
|
||||
case feature == X86FeatureSDBG && version.AtLeast(4, 3):
|
||||
// SDBG only exposed in
|
||||
// b1c599b8ff80ea79b9f8277a3f9f36a7b0cfedce (4.3).
|
||||
return true
|
||||
// Block 2.
|
||||
case feature == X86FeatureRDT && (major < 4 || major == 4 && minor < 10):
|
||||
case feature == X86FeatureRDT && version.AtLeast(4, 10):
|
||||
// RDT only exposed in
|
||||
// 4ab1586488cb56ed8728e54c4157cc38646874d9 (4.10).
|
||||
return true
|
||||
// Block 3.
|
||||
case feature == X86FeatureAVX512VBMI && (major < 4 || major == 4 && minor < 10):
|
||||
case feature == X86FeatureAVX512VBMI && version.AtLeast(4, 10):
|
||||
// AVX512VBMI only exposed in
|
||||
// a8d9df5a509a232a959e4ef2e281f7ecd77810d6 (4.10).
|
||||
return true
|
||||
case feature == X86FeatureUMIP && (major < 4 || major == 4 && minor < 15):
|
||||
case feature == X86FeatureUMIP && version.AtLeast(4, 15):
|
||||
// UMIP only exposed in
|
||||
// 3522c2a6a4f341058b8291326a945e2a2d2aaf55 (4.15).
|
||||
return true
|
||||
case feature == X86FeaturePKU && (major < 4 || major == 4 && minor < 9):
|
||||
case feature == X86FeaturePKU && version.AtLeast(4, 9):
|
||||
// PKU only exposed in
|
||||
// dfb4a70f20c5b3880da56ee4c9484bdb4e8f1e65 (4.9).
|
||||
return true
|
||||
// Block 4.
|
||||
case feature == X86FeatureXSAVES && (major < 4 || major == 4 && minor < 8):
|
||||
case feature == X86FeatureXSAVES && version.AtLeast(4, 8):
|
||||
// XSAVES only exposed in
|
||||
// b8be15d588060a03569ac85dc4a0247460988f5b (4.8).
|
||||
return true
|
||||
// Block 5.
|
||||
case feature == X86FeaturePERFCTR_LLC && (major < 4 || major == 4 && minor < 14):
|
||||
case feature == X86FeaturePERFCTR_LLC && version.AtLeast(4, 14):
|
||||
// PERFCTR_LLC renamed in
|
||||
// 910448bbed066ab1082b510eef1ae61bb792d854 (4.14).
|
||||
return true
|
||||
|
||||
@@ -17,6 +17,6 @@
|
||||
|
||||
package cpuid
|
||||
|
||||
func archSkipFeature(feature Feature, major, minor int) bool {
|
||||
func archSkipFeature(feature Feature, version hostos.Version) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
// analog in the actual CPUID feature set.
|
||||
func TestHostFeatureFlags(t *testing.T) {
|
||||
// Extract the kernel version.
|
||||
major, minor, err := hostos.KernelVersion()
|
||||
version, err := hostos.KernelVersion()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to parse kernel version: %v", err)
|
||||
}
|
||||
@@ -54,7 +54,7 @@ func TestHostFeatureFlags(t *testing.T) {
|
||||
for feature, info := range allFeatures {
|
||||
// Special cases not consistently visible. We don't mind if
|
||||
// they are exposed in earlier versions.
|
||||
if archSkipFeature(feature, major, minor) {
|
||||
if archSkipFeature(feature, version) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -6,5 +6,8 @@ go_library(
|
||||
name = "hostos",
|
||||
srcs = ["hostos.go"],
|
||||
visibility = ["//:sandbox"],
|
||||
deps = ["@org_golang_x_sys//unix:go_default_library"],
|
||||
deps = [
|
||||
"@org_golang_x_mod//semver:go_default_library",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
+56
-26
@@ -17,41 +17,71 @@ package hostos
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/mod/semver"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// KernelVersion returns the major and minor release version of the kernel using uname().
|
||||
func KernelVersion() (int, int, error) {
|
||||
var u unix.Utsname
|
||||
if err := unix.Uname(&u); err != nil {
|
||||
return 0, 0, err
|
||||
// Version represents a semantic version of the form "%d.%d[.%d]".
|
||||
type Version struct {
|
||||
version string
|
||||
}
|
||||
|
||||
// AtLeast returns whether vr is at least version major.minor.
|
||||
func (vr Version) AtLeast(major, minor int) bool {
|
||||
return semver.Compare(vr.version, fmt.Sprintf("v%d.%d", major, minor)) >= 0
|
||||
}
|
||||
|
||||
// LessThan returns whether vr is less than version major.minor.
|
||||
func (vr Version) LessThan(major, minor int) bool {
|
||||
return !vr.AtLeast(major, minor)
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (vr Version) String() string {
|
||||
if vr.version == "" {
|
||||
return "unknown"
|
||||
}
|
||||
// Omit the "v" prefix required by semver.
|
||||
return vr.version[1:]
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
for _, b := range u.Release {
|
||||
if b == 0 {
|
||||
break
|
||||
// These values are effectively local to KernelVersion, but kept here so as to
|
||||
// work with sync.Once.
|
||||
var (
|
||||
semVersion Version
|
||||
unameErr error
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
// KernelVersion returns the version of the kernel using uname().
|
||||
func KernelVersion() (Version, error) {
|
||||
once.Do(func() {
|
||||
var utsname unix.Utsname
|
||||
if err := unix.Uname(&utsname); err != nil {
|
||||
unameErr = err
|
||||
return
|
||||
}
|
||||
sb.WriteByte(byte(b))
|
||||
}
|
||||
|
||||
s := strings.Split(sb.String(), ".")
|
||||
if len(s) < 2 {
|
||||
return 0, 0, fmt.Errorf("kernel release missing major and minor component: %s", sb.String())
|
||||
}
|
||||
var sb strings.Builder
|
||||
for _, b := range utsname.Release {
|
||||
if b == 0 {
|
||||
break
|
||||
}
|
||||
sb.WriteByte(byte(b))
|
||||
}
|
||||
|
||||
major, err := strconv.Atoi(s[0])
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("error parsing major version %q in %q: %w", s[0], sb.String(), err)
|
||||
}
|
||||
|
||||
minor, err := strconv.Atoi(s[1])
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("error parsing minor version %q in %q: %w", s[1], sb.String(), err)
|
||||
}
|
||||
versionRegexp := regexp.MustCompile(`[0-9]+\.[0-9]+(\.[0-9]+)?`)
|
||||
version := "v" + string(versionRegexp.Find([]byte(sb.String())))
|
||||
if !semver.IsValid(version) {
|
||||
unameErr = fmt.Errorf("invalid version found in release %q", sb.String())
|
||||
return
|
||||
}
|
||||
semVersion.version = version
|
||||
})
|
||||
|
||||
return major, minor, nil
|
||||
return semVersion, unameErr
|
||||
}
|
||||
|
||||
+1
-1
@@ -40,6 +40,7 @@ go_library(
|
||||
"//pkg/fd",
|
||||
"//pkg/flipcall",
|
||||
"//pkg/fspath",
|
||||
"//pkg/hostos",
|
||||
"//pkg/log",
|
||||
"//pkg/memutil",
|
||||
"//pkg/rand",
|
||||
@@ -119,7 +120,6 @@ go_library(
|
||||
"//runsc/specutils/seccomp",
|
||||
"@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
"@org_golang_x_mod//semver:go_default_library",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
+5
-10
@@ -17,12 +17,11 @@ package boot
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/mod/semver"
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/hostos"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/ethernet"
|
||||
@@ -197,16 +196,12 @@ func (n *Network) CreateLinksAndRoutes(args *CreateLinksAndRoutesArgs, _ *struct
|
||||
}
|
||||
|
||||
// Choose a dispatch mode.
|
||||
// Get the Linux kernel version. Uname will return something like
|
||||
// "5.17.7-1distro-amd64", from which we'd want "5.17.7".
|
||||
var uname unix.Utsname
|
||||
if err := unix.Uname(&uname); err != nil {
|
||||
dispatchMode := fdbased.RecvMMsg
|
||||
version, err := hostos.KernelVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
re := regexp.MustCompile(`[0-9]+\.[0-9]+(\.[0-9]+)?`)
|
||||
version := "v" + string(re.Find(uname.Release[:]))
|
||||
dispatchMode := fdbased.RecvMMsg
|
||||
if semver.IsValid(version) && semver.Compare(version, "v5.6") >= 0 {
|
||||
if version.AtLeast(5, 6) {
|
||||
dispatchMode = fdbased.PacketMMap
|
||||
} else {
|
||||
log.Infof("Host kernel version < 5.6, falling back to RecvMMsg dispatch")
|
||||
|
||||
Reference in New Issue
Block a user