Compare commits

..

46 Commits

Author SHA1 Message Date
Evan Lezar
0db8ca9893 Fix discovery of nvidia-fs devices in non-privileged containers
The /dev/nvidia-fs* device nodes for GDS are not greated at the
driver root when running a containerized driver and are always
created in /.

This change updates the search path for these device nodes so that
non-privilged containers also have the device nodes injected.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-16 19:21:13 +02:00
Evan Lezar
8149be09ac Merge pull request #1149 from NVIDIA/dependabot/go_modules/main/github.com/urfave/cli/v2-2.27.7
Bump github.com/urfave/cli/v2 from 2.27.6 to 2.27.7
2025-06-16 16:28:29 +02:00
Evan Lezar
d935648722 Merge pull request #1140 from NVIDIA/dependabot/go_modules/main/github.com/NVIDIA/go-nvlib-0.7.3
Bump github.com/NVIDIA/go-nvlib from 0.7.2 to 0.7.3
2025-06-16 16:26:57 +02:00
dependabot[bot]
1f43b71dd8 Bump github.com/urfave/cli/v2 from 2.27.6 to 2.27.7
Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.27.6 to 2.27.7.
- [Release notes](https://github.com/urfave/cli/releases)
- [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md)
- [Commits](https://github.com/urfave/cli/compare/v2.27.6...v2.27.7)

---
updated-dependencies:
- dependency-name: github.com/urfave/cli/v2
  dependency-version: 2.27.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-16 08:56:44 +00:00
Evan Lezar
b33d475ff3 Merge pull request #1145 from elezar/remove-docker-runc
Some checks failed
CI Pipeline / code-scanning (push) Has been cancelled
CI Pipeline / variables (push) Has been cancelled
CI Pipeline / golang (push) Has been cancelled
CI Pipeline / image (push) Has been cancelled
CI Pipeline / e2e-test (push) Has been cancelled
Remove docker-run as default runtime candidate
2025-06-13 19:27:08 +02:00
Evan Lezar
6359cc9919 Remove docker-run as default runtime candidate
This change removes docker-runc as the highest priority
default candidate for the low-level runtimes supported by
the nvidia-container-runtime.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-13 17:26:19 +02:00
Evan Lezar
4f9c860a37 Merge pull request #927 from elezar/disable-device-node-creation
Disable device node creation in CDI mode
2025-06-13 16:44:18 +02:00
Evan Lezar
bab9fdf607 Merge pull request #1144 from NVIDIA/dependabot/submodules/main/third_party/libnvidia-container-710a0f1
Bump third_party/libnvidia-container from `6eda4d7` to `710a0f1`
2025-06-13 16:42:53 +02:00
Evan Lezar
cc7812470f Merge pull request #1143 from elezar/add-device-ids-to-getspec
Add device IDs to nvcdi.GetSpec API
2025-06-13 16:41:43 +02:00
Evan Lezar
bdcdcb7449 Merge pull request #1132 from elezar/make-cdi-device-extraction-consistent
Make CDI device requests consistent with other methods
2025-06-13 16:05:44 +02:00
Evan Lezar
8be03cfc41 [no-relnote] Ignore annotation devices for non-CDI modes
Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-13 15:26:48 +02:00
Evan Lezar
8650ca6533 [no-relnote] Move hookCreator initialisation for readability
Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-13 15:00:51 +02:00
Evan Lezar
1bc2a9fee3 Return annotation devices from VisibleDevices
This change includes annotation devices in CUDA.VisibleDevices
with the highest priority. This allows for the CDI device
request extraction to be consistent across all request mechanisms.

Note that this does change behaviour in the following ways:
1. Annotations are considered when resolving the runtime mode.
2. Incorrectly formed device names in annotations are no longer treated as an error.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-13 14:56:08 +02:00
Evan Lezar
dc87dcf786 Make CDI device requests consistent with other methods
Following the refactoring of device request extraction, we can
now make CDI device requests consistent with other methods.

This change moves to using image.VisibleDevices instead of
separate calls to CDIDevicesFromMounts and VisibleDevicesFromEnvVar.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-13 14:34:02 +02:00
Evan Lezar
f17d424248 Construct container info once
Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-13 14:05:51 +02:00
Evan Lezar
426186c992 Add logic to extract annotation device requests to image type
This change updates the image.CUDA type to also extract CDI
device requests. These are only relevant IF CDI prefixes are
specifically set.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-13 14:05:51 +02:00
Evan Lezar
6849ebd621 Add IsPrivileged function to CUDA container type
Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-13 14:05:51 +02:00
dependabot[bot]
4a6685d3a8 Bump third_party/libnvidia-container from 6eda4d7 to 710a0f1
Bumps [third_party/libnvidia-container](https://github.com/NVIDIA/libnvidia-container) from `6eda4d7` to `710a0f1`.
- [Release notes](https://github.com/NVIDIA/libnvidia-container/releases)
- [Commits](6eda4d76c8...710a0f1304)

---
updated-dependencies:
- dependency-name: third_party/libnvidia-container
  dependency-version: 710a0f1304dacb9de06716a4e24160698952aa81
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-13 08:14:38 +00:00
Evan Lezar
2ccf67c40f [no-relnote] Remove test output file
Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-12 16:34:08 +02:00
Evan Lezar
0134ba4250 Add device IDs to nvcdi.GetSpec API
This change allows device IDs to the specified in the GetSpec API.
This simplifies cases where CDI specs are being generated for specific
devices by ID.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-12 16:23:11 +02:00
dependabot[bot]
eab9cdf1c2 Bump github.com/NVIDIA/go-nvlib from 0.7.2 to 0.7.3
Bumps [github.com/NVIDIA/go-nvlib](https://github.com/NVIDIA/go-nvlib) from 0.7.2 to 0.7.3.
- [Release notes](https://github.com/NVIDIA/go-nvlib/releases)
- [Commits](https://github.com/NVIDIA/go-nvlib/compare/v0.7.2...v0.7.3)

---
updated-dependencies:
- dependency-name: github.com/NVIDIA/go-nvlib
  dependency-version: 0.7.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-11 12:58:33 +00:00
Evan Lezar
dba15acdcc Merge pull request #1135 from NVIDIA/dependabot/go_modules/tests/main/golang.org/x/crypto-0.39.0
Some checks failed
CI Pipeline / code-scanning (push) Has been cancelled
CI Pipeline / variables (push) Has been cancelled
CI Pipeline / golang (push) Has been cancelled
CI Pipeline / image (push) Has been cancelled
CI Pipeline / e2e-test (push) Has been cancelled
Bump golang.org/x/crypto from 0.38.0 to 0.39.0 in /tests
2025-06-11 14:57:38 +02:00
Evan Lezar
8339fb1ec3 Merge pull request #1139 from NVIDIA/dependabot/go_modules/main/github.com/NVIDIA/go-nvml-0.12.9-0
Bump github.com/NVIDIA/go-nvml from 0.12.4-1 to 0.12.9-0
2025-06-11 14:57:18 +02:00
Evan Lezar
b9d646c80d Merge pull request #1136 from NVIDIA/dependabot/docker/deployments/devel/main/golang-1.24.4
Bump golang from 1.24.3 to 1.24.4 in /deployments/devel
2025-06-11 14:53:57 +02:00
Evan Lezar
7380cff645 Merge pull request #1134 from NVIDIA/dependabot/go_modules/main/golang.org/x/mod-0.25.0
Bump golang.org/x/mod from 0.24.0 to 0.25.0
2025-06-11 14:53:34 +02:00
dependabot[bot]
f91736d832 Bump github.com/NVIDIA/go-nvml from 0.12.4-1 to 0.12.9-0
Bumps [github.com/NVIDIA/go-nvml](https://github.com/NVIDIA/go-nvml) from 0.12.4-1 to 0.12.9-0.
- [Release notes](https://github.com/NVIDIA/go-nvml/releases)
- [Commits](https://github.com/NVIDIA/go-nvml/compare/v0.12.4-1...v0.12.9-0)

---
updated-dependencies:
- dependency-name: github.com/NVIDIA/go-nvml
  dependency-version: 0.12.9-0
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-11 09:03:11 +00:00
dependabot[bot]
5ccac4da5a Bump golang from 1.24.3 to 1.24.4 in /deployments/devel
Bumps golang from 1.24.3 to 1.24.4.

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.24.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-06 09:01:57 +00:00
dependabot[bot]
1aee45be2d Bump golang.org/x/crypto from 0.38.0 to 0.39.0 in /tests
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.38.0 to 0.39.0.
- [Commits](https://github.com/golang/crypto/compare/v0.38.0...v0.39.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-06 08:43:50 +00:00
dependabot[bot]
0d4a7f1d5a Bump golang.org/x/mod from 0.24.0 to 0.25.0
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.24.0 to 0.25.0.
- [Commits](https://github.com/golang/mod/compare/v0.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-version: 0.25.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-06 08:43:41 +00:00
Evan Lezar
27f5ec83de Merge pull request #1125 from elezar/vulkan-target-cpu
Some checks failed
CI Pipeline / code-scanning (push) Has been cancelled
CI Pipeline / variables (push) Has been cancelled
CI Pipeline / golang (push) Has been cancelled
CI Pipeline / image (push) Has been cancelled
CI Pipeline / e2e-test (push) Has been cancelled
Add discovery of arch-specific vulkan ICD
2025-06-05 14:09:50 +02:00
Carlos Eduardo Arango Gutierrez
0a3146f74f Merge pull request #1076 from ArangoGutierrez/refresh_cdi
Add nvidia-cdi-refresh service
2025-06-05 13:08:57 +02:00
Carlos Eduardo Arango Gutierrez
28add0a532 Merge pull request #1123 from ArangoGutierrez/cdi_generate_env_cli
Add EnvVars option for all nvidia-ctk cdi commands
2025-06-05 13:05:46 +02:00
Evan Lezar
b55255e31f Merge pull request #1110 from ArangoGutierrez/i/1049
Refactor extracting requested devices from the container image
2025-06-05 13:00:32 +02:00
Carlos Eduardo Arango Gutierrez
dede03f322 Refactor extracting requested devices from the container image
This change consolidates the logic for determining requested devices
from the container image. The logic for this has been integrated into
the image.CUDA type so that multiple implementations are not required.

Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Co-authored-by: Evan Lezar <elezar@nvidia.com>
2025-06-05 12:38:45 +02:00
Carlos Eduardo Arango Gutierrez
ce3e2c1ed5 Add EnvVars option for all nvidia-ctk cdi commands
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
2025-06-05 11:22:35 +02:00
Carlos Eduardo Arango Gutierrez
a537d0323d Add nvidia-cdi-refresh service
Automatic regeneration of /var/run/cdi/nvidia.yaml
New units:
	•	nvidia-cdi-refresh.service – one-shot wrapper for
			nvidia-ctk cdi generate (adds sleep + required caps).
	•	nvidia-cdi-refresh.path   – fires on driver install/upgrade via
			modules.dep.bin changes.
Packaging
	•	RPM %post reloads systemd and enables the path unit on fresh
			installs.
	•	DEB postinst does the same (configure, skip on upgrade).

Result: CDI spec is always up to date

Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
2025-06-05 10:54:15 +02:00
Evan Lezar
2de997e25b Add discovery of arch-specific vulkan ICD
On some RPM-based platforms, the path of the Vulkan ICD file
include an architecture-specific infix to distinguish it from
other architectures. (Most notably x86_64 vs i686). This change
attempts to discover the arch-specific ICD file in addition to
the standard nvidia_icd.json.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-04 23:06:16 +02:00
Evan Lezar
e046d6ae79 Add disabled-device-node-modification hook to CDI spec
Some checks failed
CI Pipeline / code-scanning (push) Has been cancelled
CI Pipeline / variables (push) Has been cancelled
CI Pipeline / golang (push) Has been cancelled
CI Pipeline / image (push) Has been cancelled
CI Pipeline / e2e-test (push) Has been cancelled
This hook is not added to management specs.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-04 19:08:48 +02:00
Evan Lezar
0c8723a93a Add a hook to disable device node creation in a container
If required, this hook creates a modified params file (with ModifyDeviceFiles: 0) in a tmpfs
and mounts this over /proc/driver/nvidia/params.

This prevents device node creation when running tools such as nvidia-smi. In general the
creation of these devices is cosmetic as a container does not have the required cgroup
access for the devices.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-04 19:08:48 +02:00
Evan Lezar
fdcd250362 Merge pull request #1129 from elezar/fix-deduplicate-driver-store-wsl
Minor cleanup of WSL2 CDI spec generation
2025-06-04 10:16:36 +02:00
Evan Lezar
b66d37bedb [no-relnote] Minor code cleanup in WSL2 discoverer
Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-03 23:43:17 +02:00
Evan Lezar
0c905d0de2 [no-relnote] Remove unneeded indirection
Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-03 23:43:17 +02:00
Evan Lezar
0d0b56816e Remove redundant deduplication of search paths for WSL
The GetDriverStorePaths function is implemented so as to
remove duplicate driver store paths which means that the
additional deduplication (which had a bug) can be removed.

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-03 23:43:10 +02:00
Evan Lezar
d59fd3da11 Merge pull request #1077 from ArangoGutierrez/1074
Some checks failed
CI Pipeline / code-scanning (push) Has been cancelled
CI Pipeline / variables (push) Has been cancelled
CI Pipeline / golang (push) Has been cancelled
CI Pipeline / image (push) Has been cancelled
CI Pipeline / e2e-test (push) Has been cancelled
Add the ability to disable specific (or all) CDI hooks when generating a CDI specification
2025-06-03 16:03:18 +02:00
Carlos Eduardo Arango Gutierrez
6cf0248321 Added ability to disable specific (or all) CDI hooks
This change adds the ability to disabled specific (or all) CDI hooks to
both the nvidia-ctk cdi generate command and the nvcdi API.

Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Signed-off-by: Evan Lezar <elezar@nvidia.com>
2025-06-03 16:01:20 +02:00
Carlos Eduardo Arango Gutierrez
b4787511d2 Consolidate HookName functionality on internal/discover pkg
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
2025-06-03 15:24:43 +02:00
109 changed files with 11637 additions and 3160 deletions

View File

@@ -22,6 +22,7 @@ import (
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-cdi-hook/chmod" "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-cdi-hook/chmod"
symlinks "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-cdi-hook/create-symlinks" symlinks "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-cdi-hook/create-symlinks"
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-cdi-hook/cudacompat" "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-cdi-hook/cudacompat"
disabledevicenodemodification "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-cdi-hook/disable-device-node-modification"
ldcache "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-cdi-hook/update-ldcache" ldcache "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-cdi-hook/update-ldcache"
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger" "github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
) )
@@ -34,6 +35,7 @@ func New(logger logger.Interface) []*cli.Command {
symlinks.NewCommand(logger), symlinks.NewCommand(logger),
chmod.NewCommand(logger), chmod.NewCommand(logger),
cudacompat.NewCommand(logger), cudacompat.NewCommand(logger),
disabledevicenodemodification.NewCommand(logger),
} }
} }

View File

@@ -0,0 +1,144 @@
/**
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
**/
package disabledevicenodemodification
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"os"
"strings"
"github.com/urfave/cli/v2"
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
)
const (
nvidiaDriverParamsPath = "/proc/driver/nvidia/params"
)
type options struct {
containerSpec string
}
// NewCommand constructs an disable-device-node-modification subcommand with the specified logger
func NewCommand(logger logger.Interface) *cli.Command {
cfg := options{}
c := cli.Command{
Name: "disable-device-node-modification",
Usage: "Ensure that the /proc/driver/nvidia/params file present in the container does not allow device node modifications.",
Before: func(c *cli.Context) error {
return validateFlags(c, &cfg)
},
Action: func(c *cli.Context) error {
return run(c, &cfg)
},
}
c.Flags = []cli.Flag{
&cli.StringFlag{
Name: "container-spec",
Hidden: true,
Usage: "Specify the path to the OCI container spec. If empty or '-' the spec will be read from STDIN",
Destination: &cfg.containerSpec,
},
}
return &c
}
func validateFlags(c *cli.Context, cfg *options) error {
return nil
}
func run(_ *cli.Context, cfg *options) error {
modifiedParamsFileContents, err := getModifiedNVIDIAParamsContents()
if err != nil {
return fmt.Errorf("failed to get modified params file contents: %w", err)
}
if len(modifiedParamsFileContents) == 0 {
return nil
}
s, err := oci.LoadContainerState(cfg.containerSpec)
if err != nil {
return fmt.Errorf("failed to load container state: %w", err)
}
containerRootDirPath, err := s.GetContainerRoot()
if err != nil {
return fmt.Errorf("failed to determined container root: %w", err)
}
return createParamsFileInContainer(containerRootDirPath, modifiedParamsFileContents)
}
func getModifiedNVIDIAParamsContents() ([]byte, error) {
hostNvidiaParamsFile, err := os.Open(nvidiaDriverParamsPath)
if errors.Is(err, os.ErrNotExist) {
return nil, nil
}
if err != nil {
return nil, fmt.Errorf("failed to load params file: %w", err)
}
defer hostNvidiaParamsFile.Close()
modifiedContents, err := getModifiedParamsFileContentsFromReader(hostNvidiaParamsFile)
if err != nil {
return nil, fmt.Errorf("failed to get modfied params file contents: %w", err)
}
return modifiedContents, nil
}
// getModifiedParamsFileContentsFromReader returns the contents of a modified params file from the specified reader.
func getModifiedParamsFileContentsFromReader(r io.Reader) ([]byte, error) {
var modified bytes.Buffer
scanner := bufio.NewScanner(r)
var requiresModification bool
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "ModifyDeviceFiles: ") {
if line == "ModifyDeviceFiles: 0" {
return nil, nil
}
if line == "ModifyDeviceFiles: 1" {
line = "ModifyDeviceFiles: 0"
requiresModification = true
}
}
if _, err := modified.WriteString(line + "\n"); err != nil {
return nil, fmt.Errorf("failed to create output buffer: %w", err)
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("failed to read params file: %w", err)
}
if !requiresModification {
return nil, nil
}
return modified.Bytes(), nil
}

View File

@@ -0,0 +1,91 @@
/**
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
**/
package disabledevicenodemodification
import (
"bytes"
"testing"
"github.com/stretchr/testify/require"
)
func TestGetModifiedParamsFileContentsFromReader(t *testing.T) {
testCases := map[string]struct {
contents []byte
expectedError error
expectedContents []byte
}{
"no contents": {
contents: nil,
expectedError: nil,
expectedContents: nil,
},
"other contents are ignored": {
contents: []byte(`# Some other content
that we don't care about
`),
expectedError: nil,
expectedContents: nil,
},
"already zero requires no modification": {
contents: []byte("ModifyDeviceFiles: 0"),
expectedError: nil,
expectedContents: nil,
},
"leading spaces require no modification": {
contents: []byte(" ModifyDeviceFiles: 1"),
},
"Trailing spaces require no modification": {
contents: []byte("ModifyDeviceFiles: 1 "),
},
"Not 1 require no modification": {
contents: []byte("ModifyDeviceFiles: 11"),
},
"single line requires modification": {
contents: []byte("ModifyDeviceFiles: 1"),
expectedError: nil,
expectedContents: []byte("ModifyDeviceFiles: 0\n"),
},
"single line with trailing newline requires modification": {
contents: []byte("ModifyDeviceFiles: 1\n"),
expectedError: nil,
expectedContents: []byte("ModifyDeviceFiles: 0\n"),
},
"other content is maintained": {
contents: []byte(`ModifyDeviceFiles: 1
other content
that
is maintained`),
expectedError: nil,
expectedContents: []byte(`ModifyDeviceFiles: 0
other content
that
is maintained
`),
},
}
for description, tc := range testCases {
t.Run(description, func(t *testing.T) {
contents, err := getModifiedParamsFileContentsFromReader(bytes.NewReader(tc.contents))
require.EqualValues(t, tc.expectedError, err)
require.EqualValues(t, string(tc.expectedContents), string(contents))
})
}
}

View File

@@ -0,0 +1,63 @@
//go:build linux
/**
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
**/
package disabledevicenodemodification
import (
"fmt"
"os"
"path/filepath"
"github.com/opencontainers/runc/libcontainer/utils"
"golang.org/x/sys/unix"
)
func createParamsFileInContainer(containerRootDirPath string, contents []byte) error {
tmpRoot, err := os.MkdirTemp("", "nvct-empty-dir*")
if err != nil {
return fmt.Errorf("failed to create temp root: %w", err)
}
if err := createTmpFs(tmpRoot, len(contents)); err != nil {
return fmt.Errorf("failed to create tmpfs mount for params file: %w", err)
}
modifiedParamsFile, err := os.OpenFile(filepath.Join(tmpRoot, "nvct-params"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0444)
if err != nil {
return fmt.Errorf("failed to open modified params file: %w", err)
}
defer modifiedParamsFile.Close()
if _, err := modifiedParamsFile.Write(contents); err != nil {
return fmt.Errorf("failed to write temporary params file: %w", err)
}
err = utils.WithProcfd(containerRootDirPath, nvidiaDriverParamsPath, func(nvidiaDriverParamsFdPath string) error {
return unix.Mount(modifiedParamsFile.Name(), nvidiaDriverParamsFdPath, "", unix.MS_BIND|unix.MS_RDONLY|unix.MS_NODEV|unix.MS_PRIVATE|unix.MS_NOSYMFOLLOW, "")
})
if err != nil {
return fmt.Errorf("failed to mount modified params file: %w", err)
}
return nil
}
func createTmpFs(target string, size int) error {
return unix.Mount("tmpfs", target, "tmpfs", 0, fmt.Sprintf("size=%d", size))
}

View File

@@ -0,0 +1,27 @@
//go:build !linux
// +build !linux
/**
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
**/
package disabledevicenodemodification
import "fmt"
func createParamsFileInContainer(containerRootDirPath string, contents []byte) error {
return fmt.Errorf("not supported")
}

View File

@@ -13,10 +13,6 @@ import (
"github.com/NVIDIA/nvidia-container-toolkit/internal/config/image" "github.com/NVIDIA/nvidia-container-toolkit/internal/config/image"
) )
const (
capSysAdmin = "CAP_SYS_ADMIN"
)
type nvidiaConfig struct { type nvidiaConfig struct {
Devices []string Devices []string
MigConfigDevices string MigConfigDevices string
@@ -103,9 +99,9 @@ func loadSpec(path string) (spec *Spec) {
return return
} }
func isPrivileged(s *Spec) bool { func (s *Spec) GetCapabilities() []string {
if s.Process.Capabilities == nil { if s == nil || s.Process == nil || s.Process.Capabilities == nil {
return false return nil
} }
var caps []string var caps []string
@@ -118,67 +114,22 @@ func isPrivileged(s *Spec) bool {
if err != nil { if err != nil {
log.Panicln("could not decode Process.Capabilities in OCI spec:", err) log.Panicln("could not decode Process.Capabilities in OCI spec:", err)
} }
for _, c := range caps { return caps
if c == capSysAdmin {
return true
}
}
return false
} }
// Otherwise, parse s.Process.Capabilities as: // Otherwise, parse s.Process.Capabilities as:
// github.com/opencontainers/runtime-spec/blob/v1.0.0/specs-go/config.go#L30-L54 // github.com/opencontainers/runtime-spec/blob/v1.0.0/specs-go/config.go#L30-L54
process := specs.Process{ capabilities := specs.LinuxCapabilities{}
Env: s.Process.Env, err := json.Unmarshal(*s.Process.Capabilities, &capabilities)
}
err := json.Unmarshal(*s.Process.Capabilities, &process.Capabilities)
if err != nil { if err != nil {
log.Panicln("could not decode Process.Capabilities in OCI spec:", err) log.Panicln("could not decode Process.Capabilities in OCI spec:", err)
} }
fullSpec := specs.Spec{ return image.OCISpecCapabilities(capabilities).GetCapabilities()
Version: *s.Version,
Process: &process,
}
return image.IsPrivileged(&fullSpec)
} }
func getDevicesFromEnvvar(containerImage image.CUDA, swarmResourceEnvvars []string) []string { func isPrivileged(s *Spec) bool {
// We check if the image has at least one of the Swarm resource envvars defined and use this return image.IsPrivileged(s)
// if specified.
for _, envvar := range swarmResourceEnvvars {
if containerImage.HasEnvvar(envvar) {
return containerImage.DevicesFromEnvvars(swarmResourceEnvvars...).List()
}
}
return containerImage.VisibleDevicesFromEnvVar()
}
func (hookConfig *hookConfig) getDevices(image image.CUDA, privileged bool) []string {
// If enabled, try and get the device list from volume mounts first
if hookConfig.AcceptDeviceListAsVolumeMounts {
devices := image.VisibleDevicesFromMounts()
if len(devices) > 0 {
return devices
}
}
// Fallback to reading from the environment variable if privileges are correct
devices := getDevicesFromEnvvar(image, hookConfig.getSwarmResourceEnvvars())
if len(devices) == 0 {
return nil
}
if privileged || hookConfig.AcceptEnvvarUnprivileged {
return devices
}
configName := hookConfig.getConfigOption("AcceptEnvvarUnprivileged")
log.Printf("Ignoring devices specified in NVIDIA_VISIBLE_DEVICES (privileged=%v, %v=%v) ", privileged, configName, hookConfig.AcceptEnvvarUnprivileged)
return nil
} }
func getMigConfigDevices(i image.CUDA) *string { func getMigConfigDevices(i image.CUDA) *string {
@@ -225,7 +176,6 @@ func (hookConfig *hookConfig) getDriverCapabilities(cudaImage image.CUDA, legacy
// We use the default driver capabilities by default. This is filtered to only include the // We use the default driver capabilities by default. This is filtered to only include the
// supported capabilities // supported capabilities
supportedDriverCapabilities := image.NewDriverCapabilities(hookConfig.SupportedDriverCapabilities) supportedDriverCapabilities := image.NewDriverCapabilities(hookConfig.SupportedDriverCapabilities)
capabilities := supportedDriverCapabilities.Intersection(image.DefaultDriverCapabilities) capabilities := supportedDriverCapabilities.Intersection(image.DefaultDriverCapabilities)
capsEnvSpecified := cudaImage.HasEnvvar(image.EnvVarNvidiaDriverCapabilities) capsEnvSpecified := cudaImage.HasEnvvar(image.EnvVarNvidiaDriverCapabilities)
@@ -251,7 +201,7 @@ func (hookConfig *hookConfig) getDriverCapabilities(cudaImage image.CUDA, legacy
func (hookConfig *hookConfig) getNvidiaConfig(image image.CUDA, privileged bool) *nvidiaConfig { func (hookConfig *hookConfig) getNvidiaConfig(image image.CUDA, privileged bool) *nvidiaConfig {
legacyImage := image.IsLegacy() legacyImage := image.IsLegacy()
devices := hookConfig.getDevices(image, privileged) devices := image.VisibleDevices()
if len(devices) == 0 { if len(devices) == 0 {
// empty devices means this is not a GPU container. // empty devices means this is not a GPU container.
return nil return nil
@@ -306,20 +256,25 @@ func (hookConfig *hookConfig) getContainerConfig() (config containerConfig) {
s := loadSpec(path.Join(b, "config.json")) s := loadSpec(path.Join(b, "config.json"))
image, err := image.New( privileged := isPrivileged(s)
i, err := image.New(
image.WithEnv(s.Process.Env), image.WithEnv(s.Process.Env),
image.WithMounts(s.Mounts), image.WithMounts(s.Mounts),
image.WithPrivileged(privileged),
image.WithDisableRequire(hookConfig.DisableRequire), image.WithDisableRequire(hookConfig.DisableRequire),
image.WithAcceptDeviceListAsVolumeMounts(hookConfig.AcceptDeviceListAsVolumeMounts),
image.WithAcceptEnvvarUnprivileged(hookConfig.AcceptEnvvarUnprivileged),
image.WithPreferredVisibleDevicesEnvVars(hookConfig.getSwarmResourceEnvvars()...),
) )
if err != nil { if err != nil {
log.Panicln(err) log.Panicln(err)
} }
privileged := isPrivileged(s)
return containerConfig{ return containerConfig{
Pid: h.Pid, Pid: h.Pid,
Rootfs: s.Root.Path, Rootfs: s.Root.Path,
Image: image, Image: i,
Nvidia: hookConfig.getNvidiaConfig(image, privileged), Nvidia: hookConfig.getNvidiaConfig(i, privileged),
} }
} }

View File

@@ -1,10 +1,8 @@
package main package main
import ( import (
"path/filepath"
"testing" "testing"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/NVIDIA/nvidia-container-toolkit/internal/config" "github.com/NVIDIA/nvidia-container-toolkit/internal/config"
@@ -479,7 +477,10 @@ func TestGetNvidiaConfig(t *testing.T) {
t.Run(tc.description, func(t *testing.T) { t.Run(tc.description, func(t *testing.T) {
image, _ := image.New( image, _ := image.New(
image.WithEnvMap(tc.env), image.WithEnvMap(tc.env),
image.WithPrivileged(tc.privileged),
image.WithPreferredVisibleDevicesEnvVars(tc.hookConfig.getSwarmResourceEnvvars()...),
) )
// Wrap the call to getNvidiaConfig() in a closure. // Wrap the call to getNvidiaConfig() in a closure.
var cfg *nvidiaConfig var cfg *nvidiaConfig
getConfig := func() { getConfig := func() {
@@ -518,340 +519,6 @@ func TestGetNvidiaConfig(t *testing.T) {
} }
} }
func TestDeviceListSourcePriority(t *testing.T) {
var tests = []struct {
description string
mountDevices []specs.Mount
envvarDevices string
privileged bool
acceptUnprivileged bool
acceptMounts bool
expectedDevices []string
}{
{
description: "Mount devices, unprivileged, no accept unprivileged",
mountDevices: []specs.Mount{
{
Source: "/dev/null",
Destination: filepath.Join(image.DeviceListAsVolumeMountsRoot, "GPU0"),
},
{
Source: "/dev/null",
Destination: filepath.Join(image.DeviceListAsVolumeMountsRoot, "GPU1"),
},
},
envvarDevices: "GPU2,GPU3",
privileged: false,
acceptUnprivileged: false,
acceptMounts: true,
expectedDevices: []string{"GPU0", "GPU1"},
},
{
description: "No mount devices, unprivileged, no accept unprivileged",
mountDevices: nil,
envvarDevices: "GPU0,GPU1",
privileged: false,
acceptUnprivileged: false,
acceptMounts: true,
expectedDevices: nil,
},
{
description: "No mount devices, privileged, no accept unprivileged",
mountDevices: nil,
envvarDevices: "GPU0,GPU1",
privileged: true,
acceptUnprivileged: false,
acceptMounts: true,
expectedDevices: []string{"GPU0", "GPU1"},
},
{
description: "No mount devices, unprivileged, accept unprivileged",
mountDevices: nil,
envvarDevices: "GPU0,GPU1",
privileged: false,
acceptUnprivileged: true,
acceptMounts: true,
expectedDevices: []string{"GPU0", "GPU1"},
},
{
description: "Mount devices, unprivileged, accept unprivileged, no accept mounts",
mountDevices: []specs.Mount{
{
Source: "/dev/null",
Destination: filepath.Join(image.DeviceListAsVolumeMountsRoot, "GPU0"),
},
{
Source: "/dev/null",
Destination: filepath.Join(image.DeviceListAsVolumeMountsRoot, "GPU1"),
},
},
envvarDevices: "GPU2,GPU3",
privileged: false,
acceptUnprivileged: true,
acceptMounts: false,
expectedDevices: []string{"GPU2", "GPU3"},
},
{
description: "Mount devices, unprivileged, no accept unprivileged, no accept mounts",
mountDevices: []specs.Mount{
{
Source: "/dev/null",
Destination: filepath.Join(image.DeviceListAsVolumeMountsRoot, "GPU0"),
},
{
Source: "/dev/null",
Destination: filepath.Join(image.DeviceListAsVolumeMountsRoot, "GPU1"),
},
},
envvarDevices: "GPU2,GPU3",
privileged: false,
acceptUnprivileged: false,
acceptMounts: false,
expectedDevices: nil,
},
}
for _, tc := range tests {
t.Run(tc.description, func(t *testing.T) {
// Wrap the call to getDevices() in a closure.
var devices []string
getDevices := func() {
image, _ := image.New(
image.WithEnvMap(
map[string]string{
image.EnvVarNvidiaVisibleDevices: tc.envvarDevices,
},
),
image.WithMounts(tc.mountDevices),
)
defaultConfig, _ := config.GetDefault()
cfg := &hookConfig{defaultConfig}
cfg.AcceptEnvvarUnprivileged = tc.acceptUnprivileged
cfg.AcceptDeviceListAsVolumeMounts = tc.acceptMounts
devices = cfg.getDevices(image, tc.privileged)
}
// For all other tests, just grab the devices and check the results
getDevices()
require.Equal(t, tc.expectedDevices, devices)
})
}
}
func TestGetDevicesFromEnvvar(t *testing.T) {
envDockerResourceGPUs := "DOCKER_RESOURCE_GPUS"
gpuID := "GPU-12345"
anotherGPUID := "GPU-67890"
thirdGPUID := "MIG-12345"
var tests = []struct {
description string
swarmResourceEnvvars []string
env map[string]string
expectedDevices []string
}{
{
description: "empty env returns nil for non-legacy image",
},
{
description: "blank NVIDIA_VISIBLE_DEVICES returns nil for non-legacy image",
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: "",
},
},
{
description: "'void' NVIDIA_VISIBLE_DEVICES returns nil for non-legacy image",
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: "void",
},
},
{
description: "'none' NVIDIA_VISIBLE_DEVICES returns empty for non-legacy image",
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: "none",
},
expectedDevices: []string{""},
},
{
description: "NVIDIA_VISIBLE_DEVICES set returns value for non-legacy image",
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: gpuID,
},
expectedDevices: []string{gpuID},
},
{
description: "NVIDIA_VISIBLE_DEVICES set returns value for legacy image",
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: gpuID,
image.EnvVarCudaVersion: "legacy",
},
expectedDevices: []string{gpuID},
},
{
description: "empty env returns all for legacy image",
env: map[string]string{
image.EnvVarCudaVersion: "legacy",
},
expectedDevices: []string{"all"},
},
// Add the `DOCKER_RESOURCE_GPUS` envvar and ensure that this is ignored when
// not enabled
{
description: "missing NVIDIA_VISIBLE_DEVICES returns nil for non-legacy image",
env: map[string]string{
envDockerResourceGPUs: anotherGPUID,
},
},
{
description: "blank NVIDIA_VISIBLE_DEVICES returns nil for non-legacy image",
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: "",
envDockerResourceGPUs: anotherGPUID,
},
},
{
description: "'void' NVIDIA_VISIBLE_DEVICES returns nil for non-legacy image",
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: "void",
envDockerResourceGPUs: anotherGPUID,
},
},
{
description: "'none' NVIDIA_VISIBLE_DEVICES returns empty for non-legacy image",
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: "none",
envDockerResourceGPUs: anotherGPUID,
},
expectedDevices: []string{""},
},
{
description: "NVIDIA_VISIBLE_DEVICES set returns value for non-legacy image",
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: gpuID,
envDockerResourceGPUs: anotherGPUID,
},
expectedDevices: []string{gpuID},
},
{
description: "NVIDIA_VISIBLE_DEVICES set returns value for legacy image",
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: gpuID,
envDockerResourceGPUs: anotherGPUID,
image.EnvVarCudaVersion: "legacy",
},
expectedDevices: []string{gpuID},
},
{
description: "empty env returns all for legacy image",
env: map[string]string{
envDockerResourceGPUs: anotherGPUID,
image.EnvVarCudaVersion: "legacy",
},
expectedDevices: []string{"all"},
},
// Add the `DOCKER_RESOURCE_GPUS` envvar and ensure that this is selected when
// enabled
{
description: "empty env returns nil for non-legacy image",
swarmResourceEnvvars: []string{envDockerResourceGPUs},
},
{
description: "blank DOCKER_RESOURCE_GPUS returns nil for non-legacy image",
swarmResourceEnvvars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: "",
},
},
{
description: "'void' DOCKER_RESOURCE_GPUS returns nil for non-legacy image",
swarmResourceEnvvars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: "void",
},
},
{
description: "'none' DOCKER_RESOURCE_GPUS returns empty for non-legacy image",
swarmResourceEnvvars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: "none",
},
expectedDevices: []string{""},
},
{
description: "DOCKER_RESOURCE_GPUS set returns value for non-legacy image",
swarmResourceEnvvars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: gpuID,
},
expectedDevices: []string{gpuID},
},
{
description: "DOCKER_RESOURCE_GPUS set returns value for legacy image",
swarmResourceEnvvars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: gpuID,
image.EnvVarCudaVersion: "legacy",
},
expectedDevices: []string{gpuID},
},
{
description: "DOCKER_RESOURCE_GPUS is selected if present",
swarmResourceEnvvars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: anotherGPUID,
},
expectedDevices: []string{anotherGPUID},
},
{
description: "DOCKER_RESOURCE_GPUS overrides NVIDIA_VISIBLE_DEVICES if present",
swarmResourceEnvvars: []string{envDockerResourceGPUs},
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: gpuID,
envDockerResourceGPUs: anotherGPUID,
},
expectedDevices: []string{anotherGPUID},
},
{
description: "DOCKER_RESOURCE_GPUS_ADDITIONAL overrides NVIDIA_VISIBLE_DEVICES if present",
swarmResourceEnvvars: []string{"DOCKER_RESOURCE_GPUS_ADDITIONAL"},
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: gpuID,
"DOCKER_RESOURCE_GPUS_ADDITIONAL": anotherGPUID,
},
expectedDevices: []string{anotherGPUID},
},
{
description: "All available swarm resource envvars are selected and override NVIDIA_VISIBLE_DEVICES if present",
swarmResourceEnvvars: []string{"DOCKER_RESOURCE_GPUS", "DOCKER_RESOURCE_GPUS_ADDITIONAL"},
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: gpuID,
"DOCKER_RESOURCE_GPUS": thirdGPUID,
"DOCKER_RESOURCE_GPUS_ADDITIONAL": anotherGPUID,
},
expectedDevices: []string{thirdGPUID, anotherGPUID},
},
{
description: "DOCKER_RESOURCE_GPUS_ADDITIONAL or DOCKER_RESOURCE_GPUS override NVIDIA_VISIBLE_DEVICES if present",
swarmResourceEnvvars: []string{"DOCKER_RESOURCE_GPUS", "DOCKER_RESOURCE_GPUS_ADDITIONAL"},
env: map[string]string{
image.EnvVarNvidiaVisibleDevices: gpuID,
"DOCKER_RESOURCE_GPUS_ADDITIONAL": anotherGPUID,
},
expectedDevices: []string{anotherGPUID},
},
}
for _, tc := range tests {
t.Run(tc.description, func(t *testing.T) {
image, _ := image.New(
image.WithEnvMap(tc.env),
)
devices := getDevicesFromEnvvar(image, tc.swarmResourceEnvvars)
require.EqualValues(t, tc.expectedDevices, devices)
})
}
}
func TestGetDriverCapabilities(t *testing.T) { func TestGetDriverCapabilities(t *testing.T) {
supportedCapabilities := "compute,display,utility,video" supportedCapabilities := "compute,display,utility,video"

View File

@@ -88,7 +88,7 @@ func (c hookConfig) getConfigOption(fieldName string) string {
// getSwarmResourceEnvvars returns the swarm resource envvars for the config. // getSwarmResourceEnvvars returns the swarm resource envvars for the config.
func (c *hookConfig) getSwarmResourceEnvvars() []string { func (c *hookConfig) getSwarmResourceEnvvars() []string {
if c.SwarmResource == "" { if c == nil || c.SwarmResource == "" {
return nil return nil
} }

View File

@@ -21,8 +21,8 @@ The `runtimes` config option allows for the low-level runtime to be specified. T
The default value for this setting is: The default value for this setting is:
```toml ```toml
runtimes = [ runtimes = [
"docker-runc",
"runc", "runc",
"crun",
] ]
``` ```

View File

@@ -27,7 +27,7 @@ const (
) )
var availableRuntimes = map[string]struct{}{"docker": {}, "crio": {}, "containerd": {}} var availableRuntimes = map[string]struct{}{"docker": {}, "crio": {}, "containerd": {}}
var defaultLowLevelRuntimes = []string{"docker-runc", "runc", "crun"} var defaultLowLevelRuntimes = []string{"runc", "crun"}
var waitingForSignal = make(chan bool, 1) var waitingForSignal = make(chan bool, 1)
var signalReceived = make(chan bool, 1) var signalReceived = make(chan bool, 1)

View File

@@ -67,7 +67,7 @@ swarm-resource = ""
debug = "/dev/null" debug = "/dev/null"
log-level = "info" log-level = "info"
mode = "auto" mode = "auto"
runtimes = ["docker-runc", "runc", "crun"] runtimes = ["runc", "crun"]
[nvidia-container-runtime.modes] [nvidia-container-runtime.modes]
@@ -131,7 +131,7 @@ swarm-resource = ""
debug = "/dev/null" debug = "/dev/null"
log-level = "info" log-level = "info"
mode = "auto" mode = "auto"
runtimes = ["docker-runc", "runc", "crun"] runtimes = ["runc", "crun"]
[nvidia-container-runtime.modes] [nvidia-container-runtime.modes]
@@ -198,7 +198,7 @@ swarm-resource = ""
debug = "/dev/null" debug = "/dev/null"
log-level = "info" log-level = "info"
mode = "auto" mode = "auto"
runtimes = ["docker-runc", "runc", "crun"] runtimes = ["runc", "crun"]
[nvidia-container-runtime.modes] [nvidia-container-runtime.modes]
@@ -262,7 +262,7 @@ swarm-resource = ""
debug = "/dev/null" debug = "/dev/null"
log-level = "info" log-level = "info"
mode = "auto" mode = "auto"
runtimes = ["docker-runc", "runc", "crun"] runtimes = ["runc", "crun"]
[nvidia-container-runtime.modes] [nvidia-container-runtime.modes]
@@ -348,7 +348,7 @@ swarm-resource = ""
debug = "/dev/null" debug = "/dev/null"
log-level = "info" log-level = "info"
mode = "auto" mode = "auto"
runtimes = ["docker-runc", "runc", "crun"] runtimes = ["runc", "crun"]
[nvidia-container-runtime.modes] [nvidia-container-runtime.modes]

View File

@@ -57,6 +57,7 @@ type options struct {
configSearchPaths cli.StringSlice configSearchPaths cli.StringSlice
librarySearchPaths cli.StringSlice librarySearchPaths cli.StringSlice
disabledHooks cli.StringSlice
csv struct { csv struct {
files cli.StringSlice files cli.StringSlice
@@ -96,17 +97,20 @@ func (m command) build() *cli.Command {
Name: "config-search-path", Name: "config-search-path",
Usage: "Specify the path to search for config files when discovering the entities that should be included in the CDI specification.", Usage: "Specify the path to search for config files when discovering the entities that should be included in the CDI specification.",
Destination: &opts.configSearchPaths, Destination: &opts.configSearchPaths,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_CONFIG_SEARCH_PATHS"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "output", Name: "output",
Usage: "Specify the file to output the generated CDI specification to. If this is '' the specification is output to STDOUT", Usage: "Specify the file to output the generated CDI specification to. If this is '' the specification is output to STDOUT",
Destination: &opts.output, Destination: &opts.output,
EnvVars: []string{"NVIDIA_CTK_CDI_OUTPUT_FILE_PATH"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "format", Name: "format",
Usage: "The output format for the generated spec [json | yaml]. This overrides the format defined by the output file extension (if specified).", Usage: "The output format for the generated spec [json | yaml]. This overrides the format defined by the output file extension (if specified).",
Value: spec.FormatYAML, Value: spec.FormatYAML,
Destination: &opts.format, Destination: &opts.format,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_OUTPUT_FORMAT"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "mode", Name: "mode",
@@ -116,27 +120,32 @@ func (m command) build() *cli.Command {
"If mode is set to 'auto' the mode will be determined based on the system configuration.", "If mode is set to 'auto' the mode will be determined based on the system configuration.",
Value: string(nvcdi.ModeAuto), Value: string(nvcdi.ModeAuto),
Destination: &opts.mode, Destination: &opts.mode,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_MODE"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "dev-root", Name: "dev-root",
Usage: "Specify the root where `/dev` is located. If this is not specified, the driver-root is assumed.", Usage: "Specify the root where `/dev` is located. If this is not specified, the driver-root is assumed.",
Destination: &opts.devRoot, Destination: &opts.devRoot,
EnvVars: []string{"NVIDIA_CTK_DEV_ROOT"},
}, },
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "device-name-strategy", Name: "device-name-strategy",
Usage: "Specify the strategy for generating device names. If this is specified multiple times, the devices will be duplicated for each strategy. One of [index | uuid | type-index]", Usage: "Specify the strategy for generating device names. If this is specified multiple times, the devices will be duplicated for each strategy. One of [index | uuid | type-index]",
Value: cli.NewStringSlice(nvcdi.DeviceNameStrategyIndex, nvcdi.DeviceNameStrategyUUID), Value: cli.NewStringSlice(nvcdi.DeviceNameStrategyIndex, nvcdi.DeviceNameStrategyUUID),
Destination: &opts.deviceNameStrategies, Destination: &opts.deviceNameStrategies,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_DEVICE_NAME_STRATEGIES"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "driver-root", Name: "driver-root",
Usage: "Specify the NVIDIA GPU driver root to use when discovering the entities that should be included in the CDI specification.", Usage: "Specify the NVIDIA GPU driver root to use when discovering the entities that should be included in the CDI specification.",
Destination: &opts.driverRoot, Destination: &opts.driverRoot,
EnvVars: []string{"NVIDIA_CTK_DRIVER_ROOT"},
}, },
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "library-search-path", Name: "library-search-path",
Usage: "Specify the path to search for libraries when discovering the entities that should be included in the CDI specification.\n\tNote: This option only applies to CSV mode.", Usage: "Specify the path to search for libraries when discovering the entities that should be included in the CDI specification.\n\tNote: This option only applies to CSV mode.",
Destination: &opts.librarySearchPaths, Destination: &opts.librarySearchPaths,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_LIBRARY_SEARCH_PATHS"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "nvidia-cdi-hook-path", Name: "nvidia-cdi-hook-path",
@@ -145,11 +154,13 @@ func (m command) build() *cli.Command {
"If not specified, the PATH will be searched for `nvidia-cdi-hook`. " + "If not specified, the PATH will be searched for `nvidia-cdi-hook`. " +
"NOTE: That if this is specified as `nvidia-ctk`, the PATH will be searched for `nvidia-ctk` instead.", "NOTE: That if this is specified as `nvidia-ctk`, the PATH will be searched for `nvidia-ctk` instead.",
Destination: &opts.nvidiaCDIHookPath, Destination: &opts.nvidiaCDIHookPath,
EnvVars: []string{"NVIDIA_CTK_CDI_HOOK_PATH"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "ldconfig-path", Name: "ldconfig-path",
Usage: "Specify the path to use for ldconfig in the generated CDI specification", Usage: "Specify the path to use for ldconfig in the generated CDI specification",
Destination: &opts.ldconfigPath, Destination: &opts.ldconfigPath,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_LDCONFIG_PATH"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "vendor", Name: "vendor",
@@ -157,6 +168,7 @@ func (m command) build() *cli.Command {
Usage: "the vendor string to use for the generated CDI specification.", Usage: "the vendor string to use for the generated CDI specification.",
Value: "nvidia.com", Value: "nvidia.com",
Destination: &opts.vendor, Destination: &opts.vendor,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_VENDOR"},
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "class", Name: "class",
@@ -164,17 +176,30 @@ func (m command) build() *cli.Command {
Usage: "the class string to use for the generated CDI specification.", Usage: "the class string to use for the generated CDI specification.",
Value: "gpu", Value: "gpu",
Destination: &opts.class, Destination: &opts.class,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_CLASS"},
}, },
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "csv.file", Name: "csv.file",
Usage: "The path to the list of CSV files to use when generating the CDI specification in CSV mode.", Usage: "The path to the list of CSV files to use when generating the CDI specification in CSV mode.",
Value: cli.NewStringSlice(csv.DefaultFileList()...), Value: cli.NewStringSlice(csv.DefaultFileList()...),
Destination: &opts.csv.files, Destination: &opts.csv.files,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_CSV_FILES"},
}, },
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "csv.ignore-pattern", Name: "csv.ignore-pattern",
Usage: "Specify a pattern the CSV mount specifications.", Usage: "specify a pattern the CSV mount specifications.",
Destination: &opts.csv.ignorePatterns, Destination: &opts.csv.ignorePatterns,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_CSV_IGNORE_PATTERNS"},
},
&cli.StringSliceFlag{
Name: "disable-hook",
Aliases: []string{"disable-hooks"},
Usage: "specify a specific hook to skip when generating CDI " +
"specifications. This can be specified multiple times and the " +
"special hook name 'all' can be used ensure that the generated " +
"CDI specification does not include any hooks.",
Destination: &opts.disabledHooks,
EnvVars: []string{"NVIDIA_CTK_CDI_GENERATE_DISABLED_HOOKS"},
}, },
} }
@@ -262,7 +287,7 @@ func (m command) generateSpec(opts *options) (spec.Interface, error) {
deviceNamers = append(deviceNamers, deviceNamer) deviceNamers = append(deviceNamers, deviceNamer)
} }
cdilib, err := nvcdi.New( cdiOptions := []nvcdi.Option{
nvcdi.WithLogger(m.logger), nvcdi.WithLogger(m.logger),
nvcdi.WithDriverRoot(opts.driverRoot), nvcdi.WithDriverRoot(opts.driverRoot),
nvcdi.WithDevRoot(opts.devRoot), nvcdi.WithDevRoot(opts.devRoot),
@@ -276,7 +301,13 @@ func (m command) generateSpec(opts *options) (spec.Interface, error) {
nvcdi.WithCSVIgnorePatterns(opts.csv.ignorePatterns.Value()), nvcdi.WithCSVIgnorePatterns(opts.csv.ignorePatterns.Value()),
// We set the following to allow for dependency injection: // We set the following to allow for dependency injection:
nvcdi.WithNvmlLib(opts.nvmllib), nvcdi.WithNvmlLib(opts.nvmllib),
) }
for _, hook := range opts.disabledHooks.Value() {
cdiOptions = append(cdiOptions, nvcdi.WithDisabledHook(hook))
}
cdilib, err := nvcdi.New(cdiOptions...)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create CDI library: %v", err) return nil, fmt.Errorf("failed to create CDI library: %v", err)
} }

View File

@@ -26,6 +26,7 @@ import (
"github.com/NVIDIA/go-nvml/pkg/nvml/mock/dgxa100" "github.com/NVIDIA/go-nvml/pkg/nvml/mock/dgxa100"
testlog "github.com/sirupsen/logrus/hooks/test" testlog "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/urfave/cli/v2"
"github.com/NVIDIA/nvidia-container-toolkit/internal/test" "github.com/NVIDIA/nvidia-container-toolkit/internal/test"
) )
@@ -110,6 +111,206 @@ containerEdits:
- /lib/x86_64-linux-gnu - /lib/x86_64-linux-gnu
env: env:
- NVIDIA_CTK_DEBUG=false - NVIDIA_CTK_DEBUG=false
- hookName: createContainer
path: /usr/bin/nvidia-cdi-hook
args:
- nvidia-cdi-hook
- disable-device-node-modification
env:
- NVIDIA_CTK_DEBUG=false
mounts:
- hostPath: {{ .driverRoot }}/lib/x86_64-linux-gnu/libcuda.so.999.88.77
containerPath: /lib/x86_64-linux-gnu/libcuda.so.999.88.77
options:
- ro
- nosuid
- nodev
- rbind
- rprivate
`,
},
{
description: "disableHooks1",
options: options{
format: "yaml",
mode: "nvml",
vendor: "example.com",
class: "device",
driverRoot: driverRoot,
disabledHooks: valueOf(cli.NewStringSlice("enable-cuda-compat")),
},
expectedOptions: options{
format: "yaml",
mode: "nvml",
vendor: "example.com",
class: "device",
nvidiaCDIHookPath: "/usr/bin/nvidia-cdi-hook",
driverRoot: driverRoot,
disabledHooks: valueOf(cli.NewStringSlice("enable-cuda-compat")),
},
expectedSpec: `---
cdiVersion: 0.5.0
kind: example.com/device
devices:
- name: "0"
containerEdits:
deviceNodes:
- path: /dev/nvidia0
hostPath: {{ .driverRoot }}/dev/nvidia0
- name: all
containerEdits:
deviceNodes:
- path: /dev/nvidia0
hostPath: {{ .driverRoot }}/dev/nvidia0
containerEdits:
env:
- NVIDIA_VISIBLE_DEVICES=void
deviceNodes:
- path: /dev/nvidiactl
hostPath: {{ .driverRoot }}/dev/nvidiactl
hooks:
- hookName: createContainer
path: /usr/bin/nvidia-cdi-hook
args:
- nvidia-cdi-hook
- create-symlinks
- --link
- libcuda.so.1::/lib/x86_64-linux-gnu/libcuda.so
env:
- NVIDIA_CTK_DEBUG=false
- hookName: createContainer
path: /usr/bin/nvidia-cdi-hook
args:
- nvidia-cdi-hook
- update-ldcache
- --folder
- /lib/x86_64-linux-gnu
env:
- NVIDIA_CTK_DEBUG=false
- hookName: createContainer
path: /usr/bin/nvidia-cdi-hook
args:
- nvidia-cdi-hook
- disable-device-node-modification
env:
- NVIDIA_CTK_DEBUG=false
mounts:
- hostPath: {{ .driverRoot }}/lib/x86_64-linux-gnu/libcuda.so.999.88.77
containerPath: /lib/x86_64-linux-gnu/libcuda.so.999.88.77
options:
- ro
- nosuid
- nodev
- rbind
- rprivate
`,
},
{
description: "disableHooks2",
options: options{
format: "yaml",
mode: "nvml",
vendor: "example.com",
class: "device",
driverRoot: driverRoot,
disabledHooks: valueOf(cli.NewStringSlice("enable-cuda-compat", "update-ldcache")),
},
expectedOptions: options{
format: "yaml",
mode: "nvml",
vendor: "example.com",
class: "device",
nvidiaCDIHookPath: "/usr/bin/nvidia-cdi-hook",
driverRoot: driverRoot,
disabledHooks: valueOf(cli.NewStringSlice("enable-cuda-compat", "update-ldcache")),
},
expectedSpec: `---
cdiVersion: 0.5.0
kind: example.com/device
devices:
- name: "0"
containerEdits:
deviceNodes:
- path: /dev/nvidia0
hostPath: {{ .driverRoot }}/dev/nvidia0
- name: all
containerEdits:
deviceNodes:
- path: /dev/nvidia0
hostPath: {{ .driverRoot }}/dev/nvidia0
containerEdits:
env:
- NVIDIA_VISIBLE_DEVICES=void
deviceNodes:
- path: /dev/nvidiactl
hostPath: {{ .driverRoot }}/dev/nvidiactl
hooks:
- hookName: createContainer
path: /usr/bin/nvidia-cdi-hook
args:
- nvidia-cdi-hook
- create-symlinks
- --link
- libcuda.so.1::/lib/x86_64-linux-gnu/libcuda.so
env:
- NVIDIA_CTK_DEBUG=false
- hookName: createContainer
path: /usr/bin/nvidia-cdi-hook
args:
- nvidia-cdi-hook
- disable-device-node-modification
env:
- NVIDIA_CTK_DEBUG=false
mounts:
- hostPath: {{ .driverRoot }}/lib/x86_64-linux-gnu/libcuda.so.999.88.77
containerPath: /lib/x86_64-linux-gnu/libcuda.so.999.88.77
options:
- ro
- nosuid
- nodev
- rbind
- rprivate
`,
},
{
description: "disableHooksAll",
options: options{
format: "yaml",
mode: "nvml",
vendor: "example.com",
class: "device",
driverRoot: driverRoot,
disabledHooks: valueOf(cli.NewStringSlice("all")),
},
expectedOptions: options{
format: "yaml",
mode: "nvml",
vendor: "example.com",
class: "device",
nvidiaCDIHookPath: "/usr/bin/nvidia-cdi-hook",
driverRoot: driverRoot,
disabledHooks: valueOf(cli.NewStringSlice("all")),
},
expectedSpec: `---
cdiVersion: 0.5.0
kind: example.com/device
devices:
- name: "0"
containerEdits:
deviceNodes:
- path: /dev/nvidia0
hostPath: {{ .driverRoot }}/dev/nvidia0
- name: all
containerEdits:
deviceNodes:
- path: /dev/nvidia0
hostPath: {{ .driverRoot }}/dev/nvidia0
containerEdits:
env:
- NVIDIA_VISIBLE_DEVICES=void
deviceNodes:
- path: /dev/nvidiactl
hostPath: {{ .driverRoot }}/dev/nvidiactl
mounts: mounts:
- hostPath: {{ .driverRoot }}/lib/x86_64-linux-gnu/libcuda.so.999.88.77 - hostPath: {{ .driverRoot }}/lib/x86_64-linux-gnu/libcuda.so.999.88.77
containerPath: /lib/x86_64-linux-gnu/libcuda.so.999.88.77 containerPath: /lib/x86_64-linux-gnu/libcuda.so.999.88.77
@@ -162,3 +363,9 @@ containerEdits:
}) })
} }
} }
// valueOf returns the value of a pointer.
// Note that this does not check for a nil pointer and is only used for testing.
func valueOf[T any](v *T) T {
return *v
}

View File

@@ -64,6 +64,7 @@ func (m command) build() *cli.Command {
Usage: "specify the directories to scan for CDI specifications", Usage: "specify the directories to scan for CDI specifications",
Value: cli.NewStringSlice(cdi.DefaultSpecDirs...), Value: cli.NewStringSlice(cdi.DefaultSpecDirs...),
Destination: &cfg.cdiSpecDirs, Destination: &cfg.cdiSpecDirs,
EnvVars: []string{"NVIDIA_CTK_CDI_SPEC_DIRS"},
}, },
} }

View File

@@ -14,7 +14,7 @@
# This Dockerfile is also used to define the golang version used in this project # This Dockerfile is also used to define the golang version used in this project
# This allows dependabot to manage this version in addition to other images. # This allows dependabot to manage this version in addition to other images.
FROM golang:1.24.3 FROM golang:1.24.4
WORKDIR /work WORKDIR /work
COPY * . COPY * .

View File

@@ -1,4 +1,3 @@
/**
# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. # Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,19 +11,13 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
**/
package nvcdi [Unit]
Description=Trigger CDI refresh on NVIDIA driver install / uninstall events
// disabledHooks allows individual hooks to be disabled. [Path]
type disabledHooks map[HookName]bool PathChanged=/lib/modules/%v/modules.dep
PathChanged=/lib/modules/%v/modules.dep.bin
// HookIsSupported checks whether a hook of the specified name is supported. [Install]
// Hooks must be explicitly disabled, meaning that if no disabled hooks are WantedBy=multi-user.target
// all hooks are supported.
func (l *nvcdilib) HookIsSupported(h HookName) bool {
if len(l.disabledHooks) == 0 {
return true
}
return !l.disabledHooks[h]
}

View File

@@ -0,0 +1,28 @@
# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[Unit]
Description=Refresh NVIDIA CDI specification file
ConditionPathExists=/usr/bin/nvidia-smi
ConditionPathExists=/usr/bin/nvidia-ctk
[Service]
Type=oneshot
EnvironmentFile=-/etc/nvidia-container-toolkit/cdi-refresh.env
ExecCondition=/usr/bin/grep -qE '/nvidia.ko' /lib/modules/%v/modules.dep
ExecStart=/usr/bin/nvidia-ctk cdi generate --output=/var/run/cdi/nvidia.yaml
CapabilityBoundingSet=CAP_SYS_MODULE CAP_SYS_ADMIN CAP_MKNOD
[Install]
WantedBy=multi-user.target

View File

@@ -55,6 +55,7 @@ RUN make PREFIX=${DIST_DIR} cmds
WORKDIR $DIST_DIR WORKDIR $DIST_DIR
COPY packaging/debian ./debian COPY packaging/debian ./debian
COPY deployments/systemd/ .
ARG LIBNVIDIA_CONTAINER_TOOLS_VERSION ARG LIBNVIDIA_CONTAINER_TOOLS_VERSION
ENV LIBNVIDIA_CONTAINER_TOOLS_VERSION ${LIBNVIDIA_CONTAINER_TOOLS_VERSION} ENV LIBNVIDIA_CONTAINER_TOOLS_VERSION ${LIBNVIDIA_CONTAINER_TOOLS_VERSION}

View File

@@ -46,6 +46,7 @@ RUN make PREFIX=${DIST_DIR} cmds
WORKDIR $DIST_DIR/.. WORKDIR $DIST_DIR/..
COPY packaging/rpm . COPY packaging/rpm .
COPY deployments/systemd/ .
ARG LIBNVIDIA_CONTAINER_TOOLS_VERSION ARG LIBNVIDIA_CONTAINER_TOOLS_VERSION
ENV LIBNVIDIA_CONTAINER_TOOLS_VERSION ${LIBNVIDIA_CONTAINER_TOOLS_VERSION} ENV LIBNVIDIA_CONTAINER_TOOLS_VERSION ${LIBNVIDIA_CONTAINER_TOOLS_VERSION}

View File

@@ -71,6 +71,7 @@ RUN make PREFIX=${DIST_DIR} cmds
WORKDIR $DIST_DIR/.. WORKDIR $DIST_DIR/..
COPY packaging/rpm . COPY packaging/rpm .
COPY deployments/systemd/ ${DIST_DIR}/
ARG LIBNVIDIA_CONTAINER_TOOLS_VERSION ARG LIBNVIDIA_CONTAINER_TOOLS_VERSION
ENV LIBNVIDIA_CONTAINER_TOOLS_VERSION ${LIBNVIDIA_CONTAINER_TOOLS_VERSION} ENV LIBNVIDIA_CONTAINER_TOOLS_VERSION ${LIBNVIDIA_CONTAINER_TOOLS_VERSION}

View File

@@ -53,6 +53,7 @@ RUN make PREFIX=${DIST_DIR} cmds
WORKDIR $DIST_DIR WORKDIR $DIST_DIR
COPY packaging/debian ./debian COPY packaging/debian ./debian
COPY deployments/systemd/ .
ARG LIBNVIDIA_CONTAINER_TOOLS_VERSION ARG LIBNVIDIA_CONTAINER_TOOLS_VERSION
ENV LIBNVIDIA_CONTAINER_TOOLS_VERSION ${LIBNVIDIA_CONTAINER_TOOLS_VERSION} ENV LIBNVIDIA_CONTAINER_TOOLS_VERSION ${LIBNVIDIA_CONTAINER_TOOLS_VERSION}

10
go.mod
View File

@@ -3,8 +3,8 @@ module github.com/NVIDIA/nvidia-container-toolkit
go 1.23.0 go 1.23.0
require ( require (
github.com/NVIDIA/go-nvlib v0.7.2 github.com/NVIDIA/go-nvlib v0.7.3
github.com/NVIDIA/go-nvml v0.12.4-1 github.com/NVIDIA/go-nvml v0.12.9-0
github.com/cyphar/filepath-securejoin v0.4.1 github.com/cyphar/filepath-securejoin v0.4.1
github.com/moby/sys/reexec v0.1.0 github.com/moby/sys/reexec v0.1.0
github.com/moby/sys/symlink v0.3.0 github.com/moby/sys/symlink v0.3.0
@@ -13,15 +13,15 @@ require (
github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml v1.9.5
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
github.com/urfave/cli/v2 v2.27.6 github.com/urfave/cli/v2 v2.27.7
golang.org/x/mod v0.24.0 golang.org/x/mod v0.25.0
golang.org/x/sys v0.33.0 golang.org/x/sys v0.33.0
tags.cncf.io/container-device-interface v1.0.1 tags.cncf.io/container-device-interface v1.0.1
tags.cncf.io/container-device-interface/specs-go v1.0.0 tags.cncf.io/container-device-interface/specs-go v1.0.0
) )
require ( require (
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect

20
go.sum
View File

@@ -1,11 +1,11 @@
github.com/NVIDIA/go-nvlib v0.7.2 h1:7sy/NVUa4sM9FLKwH6CjBfHSWrJUmv8emVyxLTzjfOA= github.com/NVIDIA/go-nvlib v0.7.3 h1:kXc8PkWUlrwedSpM4fR8xT/DAq1NKy8HqhpgteFcGAw=
github.com/NVIDIA/go-nvlib v0.7.2/go.mod h1:2Kh2kYSP5IJ8EKf0/SYDzHiQKb9EJkwOf2LQzu6pXzY= github.com/NVIDIA/go-nvlib v0.7.3/go.mod h1:i95Je7GinMy/+BDs++DAdbPmT2TubjNP8i8joC7DD7I=
github.com/NVIDIA/go-nvml v0.12.4-1 h1:WKUvqshhWSNTfm47ETRhv0A0zJyr1ncCuHiXwoTrBEc= github.com/NVIDIA/go-nvml v0.12.9-0 h1:e344UK8ZkeMeeLkdQtRhmXRxNf+u532LDZPGMtkdus0=
github.com/NVIDIA/go-nvml v0.12.4-1/go.mod h1:8Llmj+1Rr+9VGGwZuRer5N/aCjxGuR5nPb/9ebBiIEQ= github.com/NVIDIA/go-nvml v0.12.9-0/go.mod h1:+KNA7c7gIBH7SKSJ1ntlwkfN80zdx8ovl4hrK3LmPt4=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
@@ -69,8 +69,8 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -80,8 +80,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@@ -110,7 +110,7 @@ func GetDefault() (*Config, error) {
NVIDIAContainerRuntimeConfig: RuntimeConfig{ NVIDIAContainerRuntimeConfig: RuntimeConfig{
DebugFilePath: "/dev/null", DebugFilePath: "/dev/null",
LogLevel: "info", LogLevel: "info",
Runtimes: []string{"docker-runc", "runc", "crun"}, Runtimes: []string{"runc", "crun"},
Mode: "auto", Mode: "auto",
Modes: modesConfig{ Modes: modesConfig{
CSV: csvModeConfig{ CSV: csvModeConfig{

View File

@@ -63,7 +63,7 @@ func TestGetConfig(t *testing.T) {
NVIDIAContainerRuntimeConfig: RuntimeConfig{ NVIDIAContainerRuntimeConfig: RuntimeConfig{
DebugFilePath: "/dev/null", DebugFilePath: "/dev/null",
LogLevel: "info", LogLevel: "info",
Runtimes: []string{"docker-runc", "runc", "crun"}, Runtimes: []string{"runc", "crun"},
Mode: "auto", Mode: "auto",
Modes: modesConfig{ Modes: modesConfig{
CSV: csvModeConfig{ CSV: csvModeConfig{
@@ -170,7 +170,7 @@ func TestGetConfig(t *testing.T) {
NVIDIAContainerRuntimeConfig: RuntimeConfig{ NVIDIAContainerRuntimeConfig: RuntimeConfig{
DebugFilePath: "/dev/null", DebugFilePath: "/dev/null",
LogLevel: "info", LogLevel: "info",
Runtimes: []string{"docker-runc", "runc", "crun"}, Runtimes: []string{"runc", "crun"},
Mode: "auto", Mode: "auto",
Modes: modesConfig{ Modes: modesConfig{
CSV: csvModeConfig{ CSV: csvModeConfig{
@@ -289,7 +289,7 @@ func TestGetConfig(t *testing.T) {
NVIDIAContainerRuntimeConfig: RuntimeConfig{ NVIDIAContainerRuntimeConfig: RuntimeConfig{
DebugFilePath: "/dev/null", DebugFilePath: "/dev/null",
LogLevel: "info", LogLevel: "info",
Runtimes: []string{"docker-runc", "runc", "crun"}, Runtimes: []string{"runc", "crun"},
Mode: "auto", Mode: "auto",
Modes: modesConfig{ Modes: modesConfig{
CSV: csvModeConfig{ CSV: csvModeConfig{
@@ -331,7 +331,7 @@ func TestGetConfig(t *testing.T) {
NVIDIAContainerRuntimeConfig: RuntimeConfig{ NVIDIAContainerRuntimeConfig: RuntimeConfig{
DebugFilePath: "/dev/null", DebugFilePath: "/dev/null",
LogLevel: "info", LogLevel: "info",
Runtimes: []string{"docker-runc", "runc", "crun"}, Runtimes: []string{"runc", "crun"},
Mode: "auto", Mode: "auto",
Modes: modesConfig{ Modes: modesConfig{
CSV: csvModeConfig{ CSV: csvModeConfig{

View File

@@ -21,22 +21,35 @@ import (
"strings" "strings"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
) )
type builder struct { type builder struct {
env map[string]string CUDA
mounts []specs.Mount
disableRequire bool disableRequire bool
} }
// Option is a functional option for creating a CUDA image.
type Option func(*builder) error
// New creates a new CUDA image from the input options. // New creates a new CUDA image from the input options.
func New(opt ...Option) (CUDA, error) { func New(opt ...Option) (CUDA, error) {
b := &builder{} b := &builder{
CUDA: CUDA{
acceptEnvvarUnprivileged: true,
},
}
for _, o := range opt { for _, o := range opt {
if err := o(b); err != nil { if err := o(b); err != nil {
return CUDA{}, err return CUDA{}, err
} }
} }
if b.logger == nil {
b.logger = logger.New()
}
if b.env == nil { if b.env == nil {
b.env = make(map[string]string) b.env = make(map[string]string)
} }
@@ -50,15 +63,36 @@ func (b builder) build() (CUDA, error) {
b.env[EnvVarNvidiaDisableRequire] = "true" b.env[EnvVarNvidiaDisableRequire] = "true"
} }
c := CUDA{ return b.CUDA, nil
env: b.env,
mounts: b.mounts,
}
return c, nil
} }
// Option is a functional option for creating a CUDA image. func WithAcceptDeviceListAsVolumeMounts(acceptDeviceListAsVolumeMounts bool) Option {
type Option func(*builder) error return func(b *builder) error {
b.acceptDeviceListAsVolumeMounts = acceptDeviceListAsVolumeMounts
return nil
}
}
func WithAcceptEnvvarUnprivileged(acceptEnvvarUnprivileged bool) Option {
return func(b *builder) error {
b.acceptEnvvarUnprivileged = acceptEnvvarUnprivileged
return nil
}
}
func WithAnnotations(annotations map[string]string) Option {
return func(b *builder) error {
b.annotations = annotations
return nil
}
}
func WithAnnotationsPrefixes(annotationsPrefixes []string) Option {
return func(b *builder) error {
b.annotationsPrefixes = annotationsPrefixes
return nil
}
}
// WithDisableRequire sets the disable require option. // WithDisableRequire sets the disable require option.
func WithDisableRequire(disableRequire bool) Option { func WithDisableRequire(disableRequire bool) Option {
@@ -93,6 +127,14 @@ func WithEnvMap(env map[string]string) Option {
} }
} }
// WithLogger sets the logger to use when creating the CUDA image.
func WithLogger(logger logger.Interface) Option {
return func(b *builder) error {
b.logger = logger
return nil
}
}
// WithMounts sets the mounts associated with the CUDA image. // WithMounts sets the mounts associated with the CUDA image.
func WithMounts(mounts []specs.Mount) Option { func WithMounts(mounts []specs.Mount) Option {
return func(b *builder) error { return func(b *builder) error {
@@ -100,3 +142,20 @@ func WithMounts(mounts []specs.Mount) Option {
return nil return nil
} }
} }
// WithPreferredVisibleDevicesEnvVars sets the environment variables that
// should take precedence over the default NVIDIA_VISIBLE_DEVICES.
func WithPreferredVisibleDevicesEnvVars(preferredVisibleDeviceEnvVars ...string) Option {
return func(b *builder) error {
b.preferredVisibleDeviceEnvVars = preferredVisibleDeviceEnvVars
return nil
}
}
// WithPrivileged sets whether an image is privileged or not.
func WithPrivileged(isPrivileged bool) Option {
return func(b *builder) error {
b.isPrivileged = isPrivileged
return nil
}
}

View File

@@ -25,6 +25,8 @@ import (
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/mod/semver" "golang.org/x/mod/semver"
"tags.cncf.io/container-device-interface/pkg/parser" "tags.cncf.io/container-device-interface/pkg/parser"
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
) )
const ( const (
@@ -38,27 +40,44 @@ const (
// a map of environment variable to values that can be used to perform lookups // a map of environment variable to values that can be used to perform lookups
// such as requirements. // such as requirements.
type CUDA struct { type CUDA struct {
env map[string]string logger logger.Interface
mounts []specs.Mount
annotations map[string]string
env map[string]string
isPrivileged bool
mounts []specs.Mount
annotationsPrefixes []string
acceptDeviceListAsVolumeMounts bool
acceptEnvvarUnprivileged bool
preferredVisibleDeviceEnvVars []string
} }
// NewCUDAImageFromSpec creates a CUDA image from the input OCI runtime spec. // NewCUDAImageFromSpec creates a CUDA image from the input OCI runtime spec.
// The process environment is read (if present) to construc the CUDA Image. // The process environment is read (if present) to construc the CUDA Image.
func NewCUDAImageFromSpec(spec *specs.Spec) (CUDA, error) { func NewCUDAImageFromSpec(spec *specs.Spec, opts ...Option) (CUDA, error) {
if spec == nil {
return New(opts...)
}
var env []string var env []string
if spec != nil && spec.Process != nil { if spec.Process != nil {
env = spec.Process.Env env = spec.Process.Env
} }
return New( specOpts := []Option{
WithAnnotations(spec.Annotations),
WithEnv(env), WithEnv(env),
WithMounts(spec.Mounts), WithMounts(spec.Mounts),
) WithPrivileged(IsPrivileged((*OCISpec)(spec))),
}
return New(append(opts, specOpts...)...)
} }
// NewCUDAImageFromEnv creates a CUDA image from the input environment. The environment // newCUDAImageFromEnv creates a CUDA image from the input environment. The environment
// is a list of strings of the form ENVAR=VALUE. // is a list of strings of the form ENVAR=VALUE.
func NewCUDAImageFromEnv(env []string) (CUDA, error) { func newCUDAImageFromEnv(env []string) (CUDA, error) {
return New(WithEnv(env)) return New(WithEnv(env))
} }
@@ -83,6 +102,10 @@ func (i CUDA) IsLegacy() bool {
return len(legacyCudaVersion) > 0 && len(cudaRequire) == 0 return len(legacyCudaVersion) > 0 && len(cudaRequire) == 0
} }
func (i CUDA) IsPrivileged() bool {
return i.isPrivileged
}
// GetRequirements returns the requirements from all NVIDIA_REQUIRE_ environment // GetRequirements returns the requirements from all NVIDIA_REQUIRE_ environment
// variables. // variables.
func (i CUDA) GetRequirements() ([]string, error) { func (i CUDA) GetRequirements() ([]string, error) {
@@ -200,46 +223,115 @@ func parseMajorMinorVersion(version string) (string, error) {
// OnlyFullyQualifiedCDIDevices returns true if all devices requested in the image are requested as CDI devices/ // OnlyFullyQualifiedCDIDevices returns true if all devices requested in the image are requested as CDI devices/
func (i CUDA) OnlyFullyQualifiedCDIDevices() bool { func (i CUDA) OnlyFullyQualifiedCDIDevices() bool {
var hasCDIdevice bool var hasCDIdevice bool
for _, device := range i.VisibleDevicesFromEnvVar() { for _, device := range i.VisibleDevices() {
if !parser.IsQualifiedName(device) { if !parser.IsQualifiedName(device) {
return false return false
} }
hasCDIdevice = true hasCDIdevice = true
} }
for _, device := range i.DevicesFromMounts() {
if !strings.HasPrefix(device, "cdi/") {
return false
}
hasCDIdevice = true
}
return hasCDIdevice return hasCDIdevice
} }
// VisibleDevicesFromEnvVar returns the set of visible devices requested through // VisibleDevices returns a list of devices requested in the container image.
// the NVIDIA_VISIBLE_DEVICES environment variable. // If volume mount requests are enabled these are returned if requested,
func (i CUDA) VisibleDevicesFromEnvVar() []string { // otherwise device requests through environment variables are considered.
return i.DevicesFromEnvvars(EnvVarNvidiaVisibleDevices).List() // In cases where environment variable requests required privileged containers,
// such devices requests are ignored.
func (i CUDA) VisibleDevices() []string {
// If annotation device requests are present, these are preferred.
annotationDeviceRequests := i.cdiDeviceRequestsFromAnnotations()
if len(annotationDeviceRequests) > 0 {
return annotationDeviceRequests
}
// If enabled, try and get the device list from volume mounts first
if i.acceptDeviceListAsVolumeMounts {
volumeMountDeviceRequests := i.visibleDevicesFromMounts()
if len(volumeMountDeviceRequests) > 0 {
return volumeMountDeviceRequests
}
}
// Get the Fallback to reading from the environment variable if privileges are correct
envVarDeviceRequests := i.VisibleDevicesFromEnvVar()
if len(envVarDeviceRequests) == 0 {
return nil
}
// If the container is privileged, or environment variable requests are
// allowed for unprivileged containers, these devices are returned.
if i.isPrivileged || i.acceptEnvvarUnprivileged {
return envVarDeviceRequests
}
// We log a warning if we are ignoring the environment variable requests.
i.logger.Warningf("Ignoring devices specified in NVIDIA_VISIBLE_DEVICES in unprivileged container")
return nil
} }
// VisibleDevicesFromMounts returns the set of visible devices requested as mounts. // cdiDeviceRequestsFromAnnotations returns a list of devices specified in the
func (i CUDA) VisibleDevicesFromMounts() []string { // annotations.
// Keys starting with the specified prefixes are considered and expected to
// contain a comma-separated list of fully-qualified CDI devices names.
// The format of the requested devices is not checked and the list is not
// deduplicated.
func (i CUDA) cdiDeviceRequestsFromAnnotations() []string {
if len(i.annotationsPrefixes) == 0 || len(i.annotations) == 0 {
return nil
}
var devices []string var devices []string
for _, device := range i.DevicesFromMounts() { for key, value := range i.annotations {
switch { for _, prefix := range i.annotationsPrefixes {
case strings.HasPrefix(device, volumeMountDevicePrefixCDI): if strings.HasPrefix(key, prefix) {
continue devices = append(devices, strings.Split(value, ",")...)
case strings.HasPrefix(device, volumeMountDevicePrefixImex): // There is no need to check additional prefixes since we
continue // typically deduplicate devices in any case.
break
}
} }
devices = append(devices, device)
} }
return devices return devices
} }
// DevicesFromMounts returns a list of device specified as mounts. // VisibleDevicesFromEnvVar returns the set of visible devices requested through environment variables.
// TODO: This should be merged with getDevicesFromMounts used in the NVIDIA Container Runtime // If any of the preferredVisibleDeviceEnvVars are present in the image, they
func (i CUDA) DevicesFromMounts() []string { // are used to determine the visible devices. If this is not the case, the
// NVIDIA_VISIBLE_DEVICES environment variable is used.
func (i CUDA) VisibleDevicesFromEnvVar() []string {
for _, envVar := range i.preferredVisibleDeviceEnvVars {
if i.HasEnvvar(envVar) {
return i.DevicesFromEnvvars(i.preferredVisibleDeviceEnvVars...).List()
}
}
return i.DevicesFromEnvvars(EnvVarNvidiaVisibleDevices).List()
}
// visibleDevicesFromMounts returns the set of visible devices requested as mounts.
func (i CUDA) visibleDevicesFromMounts() []string {
var devices []string
for _, device := range i.requestsFromMounts() {
switch {
case strings.HasPrefix(device, volumeMountDevicePrefixImex):
continue
case strings.HasPrefix(device, volumeMountDevicePrefixCDI):
name, err := cdiDeviceMountRequest(device).qualifiedName()
if err != nil {
i.logger.Warningf("Ignoring invalid mount request for CDI device %v: %v", device, err)
continue
}
devices = append(devices, name)
default:
devices = append(devices, device)
}
}
return devices
}
// requestsFromMounts returns a list of device specified as mounts.
func (i CUDA) requestsFromMounts() []string {
root := filepath.Clean(DeviceListAsVolumeMountsRoot) root := filepath.Clean(DeviceListAsVolumeMountsRoot)
seen := make(map[string]bool) seen := make(map[string]bool)
var devices []string var devices []string
@@ -271,23 +363,30 @@ func (i CUDA) DevicesFromMounts() []string {
return devices return devices
} }
// CDIDevicesFromMounts returns a list of CDI devices specified as mounts on the image. // a cdiDeviceMountRequest represents a CDI device requests as a mount.
func (i CUDA) CDIDevicesFromMounts() []string { // Here the host path /dev/null is mounted to a particular path in the container.
var devices []string // The container path has the form:
for _, mountDevice := range i.DevicesFromMounts() { // /var/run/nvidia-container-devices/cdi/<vendor>/<class>/<device>
if !strings.HasPrefix(mountDevice, volumeMountDevicePrefixCDI) { // or
continue // /var/run/nvidia-container-devices/cdi/<vendor>/<class>=<device>
} type cdiDeviceMountRequest string
parts := strings.SplitN(strings.TrimPrefix(mountDevice, volumeMountDevicePrefixCDI), "/", 3)
if len(parts) != 3 { // qualifiedName returns the fully-qualified name of the CDI device.
continue func (m cdiDeviceMountRequest) qualifiedName() (string, error) {
} if !strings.HasPrefix(string(m), volumeMountDevicePrefixCDI) {
vendor := parts[0] return "", fmt.Errorf("invalid mount CDI device request: %s", m)
class := parts[1]
device := parts[2]
devices = append(devices, fmt.Sprintf("%s/%s=%s", vendor, class, device))
} }
return devices
requestedDevice := strings.TrimPrefix(string(m), volumeMountDevicePrefixCDI)
if parser.IsQualifiedName(requestedDevice) {
return requestedDevice, nil
}
parts := strings.SplitN(requestedDevice, "/", 3)
if len(parts) != 3 {
return "", fmt.Errorf("invalid mount CDI device request: %s", m)
}
return fmt.Sprintf("%s/%s=%s", parts[0], parts[1], parts[2]), nil
} }
// ImexChannelsFromEnvVar returns the list of IMEX channels requested for the image. // ImexChannelsFromEnvVar returns the list of IMEX channels requested for the image.
@@ -302,7 +401,7 @@ func (i CUDA) ImexChannelsFromEnvVar() []string {
// ImexChannelsFromMounts returns the list of IMEX channels requested for the image. // ImexChannelsFromMounts returns the list of IMEX channels requested for the image.
func (i CUDA) ImexChannelsFromMounts() []string { func (i CUDA) ImexChannelsFromMounts() []string {
var channels []string var channels []string
for _, mountDevice := range i.DevicesFromMounts() { for _, mountDevice := range i.requestsFromMounts() {
if !strings.HasPrefix(mountDevice, volumeMountDevicePrefixImex) { if !strings.HasPrefix(mountDevice, volumeMountDevicePrefixImex) {
continue continue
} }

View File

@@ -21,9 +21,91 @@ import (
"testing" "testing"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
testlog "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestNewCUDAImageFromSpec(t *testing.T) {
logger, _ := testlog.NewNullLogger()
testCases := []struct {
description string
spec *specs.Spec
options []Option
expected CUDA
}{
{
description: "no env vars",
spec: &specs.Spec{
Process: &specs.Process{
Env: []string{},
},
},
expected: CUDA{
logger: logger,
env: map[string]string{},
acceptEnvvarUnprivileged: true,
},
},
{
description: "NVIDIA_VISIBLE_DEVICES=all",
spec: &specs.Spec{
Process: &specs.Process{
Env: []string{"NVIDIA_VISIBLE_DEVICES=all"},
},
},
expected: CUDA{
logger: logger,
env: map[string]string{"NVIDIA_VISIBLE_DEVICES": "all"},
acceptEnvvarUnprivileged: true,
},
},
{
description: "Spec overrides options",
spec: &specs.Spec{
Process: &specs.Process{
Env: []string{"NVIDIA_VISIBLE_DEVICES=all"},
},
Mounts: []specs.Mount{
{
Source: "/spec-source",
Destination: "/spec-destination",
},
},
},
options: []Option{
WithEnvMap(map[string]string{"OTHER": "value"}),
WithMounts([]specs.Mount{
{
Source: "/option-source",
Destination: "/option-destination",
},
}),
},
expected: CUDA{
logger: logger,
env: map[string]string{"NVIDIA_VISIBLE_DEVICES": "all"},
mounts: []specs.Mount{
{
Source: "/spec-source",
Destination: "/spec-destination",
},
},
acceptEnvvarUnprivileged: true,
},
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
options := append([]Option{WithLogger(logger)}, tc.options...)
image, err := NewCUDAImageFromSpec(tc.spec, options...)
require.NoError(t, err)
require.EqualValues(t, tc.expected, image)
})
}
}
func TestParseMajorMinorVersionValid(t *testing.T) { func TestParseMajorMinorVersionValid(t *testing.T) {
var tests = []struct { var tests = []struct {
version string version string
@@ -122,7 +204,7 @@ func TestGetRequirements(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) { t.Run(tc.description, func(t *testing.T) {
image, err := NewCUDAImageFromEnv(tc.env) image, err := newCUDAImageFromEnv(tc.env)
require.NoError(t, err) require.NoError(t, err)
requirements, err := image.GetRequirements() requirements, err := image.GetRequirements()
@@ -133,6 +215,226 @@ func TestGetRequirements(t *testing.T) {
} }
} }
func TestGetDevicesFromEnvvar(t *testing.T) {
envDockerResourceGPUs := "DOCKER_RESOURCE_GPUS"
gpuID := "GPU-12345"
anotherGPUID := "GPU-67890"
thirdGPUID := "MIG-12345"
var tests = []struct {
description string
preferredVisibleDeviceEnvVars []string
env map[string]string
expectedDevices []string
}{
{
description: "empty env returns nil for non-legacy image",
},
{
description: "blank NVIDIA_VISIBLE_DEVICES returns nil for non-legacy image",
env: map[string]string{
EnvVarNvidiaVisibleDevices: "",
},
},
{
description: "'void' NVIDIA_VISIBLE_DEVICES returns nil for non-legacy image",
env: map[string]string{
EnvVarNvidiaVisibleDevices: "void",
},
},
{
description: "'none' NVIDIA_VISIBLE_DEVICES returns empty for non-legacy image",
env: map[string]string{
EnvVarNvidiaVisibleDevices: "none",
},
expectedDevices: []string{""},
},
{
description: "NVIDIA_VISIBLE_DEVICES set returns value for non-legacy image",
env: map[string]string{
EnvVarNvidiaVisibleDevices: gpuID,
},
expectedDevices: []string{gpuID},
},
{
description: "NVIDIA_VISIBLE_DEVICES set returns value for legacy image",
env: map[string]string{
EnvVarNvidiaVisibleDevices: gpuID,
EnvVarCudaVersion: "legacy",
},
expectedDevices: []string{gpuID},
},
{
description: "empty env returns all for legacy image",
env: map[string]string{
EnvVarCudaVersion: "legacy",
},
expectedDevices: []string{"all"},
},
// Add the `DOCKER_RESOURCE_GPUS` envvar and ensure that this is ignored when
// not enabled
{
description: "missing NVIDIA_VISIBLE_DEVICES returns nil for non-legacy image",
env: map[string]string{
envDockerResourceGPUs: anotherGPUID,
},
},
{
description: "blank NVIDIA_VISIBLE_DEVICES returns nil for non-legacy image",
env: map[string]string{
EnvVarNvidiaVisibleDevices: "",
envDockerResourceGPUs: anotherGPUID,
},
},
{
description: "'void' NVIDIA_VISIBLE_DEVICES returns nil for non-legacy image",
env: map[string]string{
EnvVarNvidiaVisibleDevices: "void",
envDockerResourceGPUs: anotherGPUID,
},
},
{
description: "'none' NVIDIA_VISIBLE_DEVICES returns empty for non-legacy image",
env: map[string]string{
EnvVarNvidiaVisibleDevices: "none",
envDockerResourceGPUs: anotherGPUID,
},
expectedDevices: []string{""},
},
{
description: "NVIDIA_VISIBLE_DEVICES set returns value for non-legacy image",
env: map[string]string{
EnvVarNvidiaVisibleDevices: gpuID,
envDockerResourceGPUs: anotherGPUID,
},
expectedDevices: []string{gpuID},
},
{
description: "NVIDIA_VISIBLE_DEVICES set returns value for legacy image",
env: map[string]string{
EnvVarNvidiaVisibleDevices: gpuID,
envDockerResourceGPUs: anotherGPUID,
EnvVarCudaVersion: "legacy",
},
expectedDevices: []string{gpuID},
},
{
description: "empty env returns all for legacy image",
env: map[string]string{
envDockerResourceGPUs: anotherGPUID,
EnvVarCudaVersion: "legacy",
},
expectedDevices: []string{"all"},
},
// Add the `DOCKER_RESOURCE_GPUS` envvar and ensure that this is selected when
// enabled
{
description: "empty env returns nil for non-legacy image",
preferredVisibleDeviceEnvVars: []string{envDockerResourceGPUs},
},
{
description: "blank DOCKER_RESOURCE_GPUS returns nil for non-legacy image",
preferredVisibleDeviceEnvVars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: "",
},
},
{
description: "'void' DOCKER_RESOURCE_GPUS returns nil for non-legacy image",
preferredVisibleDeviceEnvVars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: "void",
},
},
{
description: "'none' DOCKER_RESOURCE_GPUS returns empty for non-legacy image",
preferredVisibleDeviceEnvVars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: "none",
},
expectedDevices: []string{""},
},
{
description: "DOCKER_RESOURCE_GPUS set returns value for non-legacy image",
preferredVisibleDeviceEnvVars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: gpuID,
},
expectedDevices: []string{gpuID},
},
{
description: "DOCKER_RESOURCE_GPUS set returns value for legacy image",
preferredVisibleDeviceEnvVars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: gpuID,
EnvVarCudaVersion: "legacy",
},
expectedDevices: []string{gpuID},
},
{
description: "DOCKER_RESOURCE_GPUS is selected if present",
preferredVisibleDeviceEnvVars: []string{envDockerResourceGPUs},
env: map[string]string{
envDockerResourceGPUs: anotherGPUID,
},
expectedDevices: []string{anotherGPUID},
},
{
description: "DOCKER_RESOURCE_GPUS overrides NVIDIA_VISIBLE_DEVICES if present",
preferredVisibleDeviceEnvVars: []string{envDockerResourceGPUs},
env: map[string]string{
EnvVarNvidiaVisibleDevices: gpuID,
envDockerResourceGPUs: anotherGPUID,
},
expectedDevices: []string{anotherGPUID},
},
{
description: "DOCKER_RESOURCE_GPUS_ADDITIONAL overrides NVIDIA_VISIBLE_DEVICES if present",
preferredVisibleDeviceEnvVars: []string{"DOCKER_RESOURCE_GPUS_ADDITIONAL"},
env: map[string]string{
EnvVarNvidiaVisibleDevices: gpuID,
"DOCKER_RESOURCE_GPUS_ADDITIONAL": anotherGPUID,
},
expectedDevices: []string{anotherGPUID},
},
{
description: "All available swarm resource envvars are selected and override NVIDIA_VISIBLE_DEVICES if present",
preferredVisibleDeviceEnvVars: []string{"DOCKER_RESOURCE_GPUS", "DOCKER_RESOURCE_GPUS_ADDITIONAL"},
env: map[string]string{
EnvVarNvidiaVisibleDevices: gpuID,
"DOCKER_RESOURCE_GPUS": thirdGPUID,
"DOCKER_RESOURCE_GPUS_ADDITIONAL": anotherGPUID,
},
expectedDevices: []string{thirdGPUID, anotherGPUID},
},
{
description: "DOCKER_RESOURCE_GPUS_ADDITIONAL or DOCKER_RESOURCE_GPUS override NVIDIA_VISIBLE_DEVICES if present",
preferredVisibleDeviceEnvVars: []string{"DOCKER_RESOURCE_GPUS", "DOCKER_RESOURCE_GPUS_ADDITIONAL"},
env: map[string]string{
EnvVarNvidiaVisibleDevices: gpuID,
"DOCKER_RESOURCE_GPUS_ADDITIONAL": anotherGPUID,
},
expectedDevices: []string{anotherGPUID},
},
}
for _, tc := range tests {
t.Run(tc.description, func(t *testing.T) {
image, err := New(
WithEnvMap(tc.env),
WithPrivileged(true),
WithAcceptDeviceListAsVolumeMounts(false),
WithAcceptEnvvarUnprivileged(false),
WithPreferredVisibleDevicesEnvVars(tc.preferredVisibleDeviceEnvVars...),
)
require.NoError(t, err)
devices := image.VisibleDevicesFromEnvVar()
require.EqualValues(t, tc.expectedDevices, devices)
})
}
}
func TestGetVisibleDevicesFromMounts(t *testing.T) { func TestGetVisibleDevicesFromMounts(t *testing.T) {
var tests = []struct { var tests = []struct {
description string description string
@@ -185,9 +487,9 @@ func TestGetVisibleDevicesFromMounts(t *testing.T) {
expectedDevices: []string{"GPU0-MIG0/0/1", "GPU1-MIG0/0/1"}, expectedDevices: []string{"GPU0-MIG0/0/1", "GPU1-MIG0/0/1"},
}, },
{ {
description: "cdi devices are ignored", description: "cdi devices are included",
mounts: makeTestMounts("GPU0", "cdi/nvidia.com/gpu=all", "GPU1"), mounts: makeTestMounts("GPU0", "nvidia.com/gpu=all", "GPU1"),
expectedDevices: []string{"GPU0", "GPU1"}, expectedDevices: []string{"GPU0", "nvidia.com/gpu=all", "GPU1"},
}, },
{ {
description: "imex devices are ignored", description: "imex devices are ignored",
@@ -197,8 +499,121 @@ func TestGetVisibleDevicesFromMounts(t *testing.T) {
} }
for _, tc := range tests { for _, tc := range tests {
t.Run(tc.description, func(t *testing.T) { t.Run(tc.description, func(t *testing.T) {
image, _ := New(WithMounts(tc.mounts)) image, err := New(WithMounts(tc.mounts))
require.Equal(t, tc.expectedDevices, image.VisibleDevicesFromMounts()) require.NoError(t, err)
require.Equal(t, tc.expectedDevices, image.visibleDevicesFromMounts())
})
}
}
func TestVisibleDevices(t *testing.T) {
var tests = []struct {
description string
mountDevices []specs.Mount
envvarDevices string
privileged bool
acceptUnprivileged bool
acceptMounts bool
expectedDevices []string
}{
{
description: "Mount devices, unprivileged, no accept unprivileged",
mountDevices: []specs.Mount{
{
Source: "/dev/null",
Destination: filepath.Join(DeviceListAsVolumeMountsRoot, "GPU0"),
},
{
Source: "/dev/null",
Destination: filepath.Join(DeviceListAsVolumeMountsRoot, "GPU1"),
},
},
envvarDevices: "GPU2,GPU3",
privileged: false,
acceptUnprivileged: false,
acceptMounts: true,
expectedDevices: []string{"GPU0", "GPU1"},
},
{
description: "No mount devices, unprivileged, no accept unprivileged",
mountDevices: nil,
envvarDevices: "GPU0,GPU1",
privileged: false,
acceptUnprivileged: false,
acceptMounts: true,
expectedDevices: nil,
},
{
description: "No mount devices, privileged, no accept unprivileged",
mountDevices: nil,
envvarDevices: "GPU0,GPU1",
privileged: true,
acceptUnprivileged: false,
acceptMounts: true,
expectedDevices: []string{"GPU0", "GPU1"},
},
{
description: "No mount devices, unprivileged, accept unprivileged",
mountDevices: nil,
envvarDevices: "GPU0,GPU1",
privileged: false,
acceptUnprivileged: true,
acceptMounts: true,
expectedDevices: []string{"GPU0", "GPU1"},
},
{
description: "Mount devices, unprivileged, accept unprivileged, no accept mounts",
mountDevices: []specs.Mount{
{
Source: "/dev/null",
Destination: filepath.Join(DeviceListAsVolumeMountsRoot, "GPU0"),
},
{
Source: "/dev/null",
Destination: filepath.Join(DeviceListAsVolumeMountsRoot, "GPU1"),
},
},
envvarDevices: "GPU2,GPU3",
privileged: false,
acceptUnprivileged: true,
acceptMounts: false,
expectedDevices: []string{"GPU2", "GPU3"},
},
{
description: "Mount devices, unprivileged, no accept unprivileged, no accept mounts",
mountDevices: []specs.Mount{
{
Source: "/dev/null",
Destination: filepath.Join(DeviceListAsVolumeMountsRoot, "GPU0"),
},
{
Source: "/dev/null",
Destination: filepath.Join(DeviceListAsVolumeMountsRoot, "GPU1"),
},
},
envvarDevices: "GPU2,GPU3",
privileged: false,
acceptUnprivileged: false,
acceptMounts: false,
expectedDevices: nil,
},
}
for _, tc := range tests {
t.Run(tc.description, func(t *testing.T) {
// Wrap the call to getDevices() in a closure.
image, err := New(
WithEnvMap(
map[string]string{
EnvVarNvidiaVisibleDevices: tc.envvarDevices,
},
),
WithMounts(tc.mountDevices),
WithPrivileged(tc.privileged),
WithAcceptDeviceListAsVolumeMounts(tc.acceptMounts),
WithAcceptEnvvarUnprivileged(tc.acceptUnprivileged),
)
require.NoError(t, err)
require.Equal(t, tc.expectedDevices, image.VisibleDevices())
}) })
} }
} }
@@ -224,7 +639,7 @@ func TestImexChannelsFromEnvVar(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
for id, baseEnvvars := range map[string][]string{"": nil, "legacy": {"CUDA_VERSION=1.2.3"}} { for id, baseEnvvars := range map[string][]string{"": nil, "legacy": {"CUDA_VERSION=1.2.3"}} {
t.Run(tc.description+id, func(t *testing.T) { t.Run(tc.description+id, func(t *testing.T) {
i, err := NewCUDAImageFromEnv(append(baseEnvvars, tc.env...)) i, err := newCUDAImageFromEnv(append(baseEnvvars, tc.env...))
require.NoError(t, err) require.NoError(t, err)
channels := i.ImexChannelsFromEnvVar() channels := i.ImexChannelsFromEnvVar()
@@ -234,6 +649,73 @@ func TestImexChannelsFromEnvVar(t *testing.T) {
} }
} }
func TestCDIDeviceRequestsFromAnnotations(t *testing.T) {
testCases := []struct {
description string
prefixes []string
annotations map[string]string
expectedDevices []string
}{
{
description: "no annotations",
},
{
description: "no matching annotations",
prefixes: []string{"not-prefix/"},
annotations: map[string]string{
"prefix/foo": "example.com/device=bar",
},
},
{
description: "single matching annotation",
prefixes: []string{"prefix/"},
annotations: map[string]string{
"prefix/foo": "example.com/device=bar",
},
expectedDevices: []string{"example.com/device=bar"},
},
{
description: "multiple matching annotations",
prefixes: []string{"prefix/", "another-prefix/"},
annotations: map[string]string{
"prefix/foo": "example.com/device=bar",
"another-prefix/bar": "example.com/device=baz",
},
expectedDevices: []string{"example.com/device=bar", "example.com/device=baz"},
},
{
description: "multiple matching annotations with duplicate devices",
prefixes: []string{"prefix/", "another-prefix/"},
annotations: map[string]string{
"prefix/foo": "example.com/device=bar",
"another-prefix/bar": "example.com/device=bar",
},
expectedDevices: []string{"example.com/device=bar", "example.com/device=bar"},
},
{
description: "invalid devices are returned as is",
prefixes: []string{"prefix/"},
annotations: map[string]string{
"prefix/foo": "example.com/device",
},
expectedDevices: []string{"example.com/device"},
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
image, err := New(
WithAnnotationsPrefixes(tc.prefixes),
WithAnnotations(tc.annotations),
)
require.NoError(t, err)
devices := image.cdiDeviceRequestsFromAnnotations()
require.ElementsMatch(t, tc.expectedDevices, devices)
})
}
}
func makeTestMounts(paths ...string) []specs.Mount { func makeTestMounts(paths ...string) []specs.Mount {
var mounts []specs.Mount var mounts []specs.Mount
for _, path := range paths { for _, path := range paths {

View File

@@ -24,20 +24,39 @@ const (
capSysAdmin = "CAP_SYS_ADMIN" capSysAdmin = "CAP_SYS_ADMIN"
) )
type CapabilitiesGetter interface {
GetCapabilities() []string
}
type OCISpec specs.Spec
type OCISpecCapabilities specs.LinuxCapabilities
// IsPrivileged returns true if the container is a privileged container. // IsPrivileged returns true if the container is a privileged container.
func IsPrivileged(s *specs.Spec) bool { func IsPrivileged(s CapabilitiesGetter) bool {
if s.Process.Capabilities == nil { if s == nil {
return false return false
} }
for _, c := range s.GetCapabilities() {
// We only make sure that the bounding capabibility set has
// CAP_SYS_ADMIN. This allows us to make sure that the container was
// actually started as '--privileged', but also allow non-root users to
// access the privileged NVIDIA capabilities.
for _, c := range s.Process.Capabilities.Bounding {
if c == capSysAdmin { if c == capSysAdmin {
return true return true
} }
} }
return false return false
} }
func (s OCISpec) GetCapabilities() []string {
if s.Process == nil || s.Process.Capabilities == nil {
return nil
}
return (*OCISpecCapabilities)(s.Process.Capabilities).GetCapabilities()
}
func (c OCISpecCapabilities) GetCapabilities() []string {
// We only make sure that the bounding capability set has
// CAP_SYS_ADMIN. This allows us to make sure that the container was
// actually started as '--privileged', but also allow non-root users to
// access the privileged NVIDIA capabilities.
return c.Bounding
}

View File

@@ -0,0 +1,57 @@
/**
# Copyright (c) NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
**/
package image
import (
"testing"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/stretchr/testify/require"
)
func TestIsPrivileged(t *testing.T) {
var tests = []struct {
spec specs.Spec
expected bool
}{
{
specs.Spec{
Process: &specs.Process{
Capabilities: &specs.LinuxCapabilities{
Bounding: []string{"CAP_SYS_ADMIN"},
},
},
},
true,
},
{
specs.Spec{
Process: &specs.Process{
Capabilities: &specs.LinuxCapabilities{
Bounding: []string{"CAP_SYS_FOO"},
},
},
},
false,
},
}
for i, tc := range tests {
privileged := IsPrivileged((*OCISpec)(&tc.spec))
require.Equal(t, tc.expected, privileged, "%d: %v", i, tc)
}
}

View File

@@ -62,7 +62,7 @@ load-kmods = true
#debug = "/var/log/nvidia-container-runtime.log" #debug = "/var/log/nvidia-container-runtime.log"
log-level = "info" log-level = "info"
mode = "auto" mode = "auto"
runtimes = ["docker-runc", "runc", "crun"] runtimes = ["runc", "crun"]
[nvidia-container-runtime.modes] [nvidia-container-runtime.modes]

View File

@@ -29,10 +29,11 @@ type gdsDeviceDiscoverer struct {
} }
// NewGDSDiscoverer creates a discoverer for GPUDirect Storage devices and mounts. // NewGDSDiscoverer creates a discoverer for GPUDirect Storage devices and mounts.
func NewGDSDiscoverer(logger logger.Interface, driverRoot string, devRoot string) (Discover, error) { func NewGDSDiscoverer(logger logger.Interface, driverRoot string) (Discover, error) {
devices := NewCharDeviceDiscoverer( devices := NewCharDeviceDiscoverer(
logger, logger,
devRoot, // The /dev/nvidia-fs* devices are always created at /
"/",
[]string{"/dev/nvidia-fs*"}, []string{"/dev/nvidia-fs*"},
) )

View File

@@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"github.com/NVIDIA/nvidia-container-toolkit/internal/config/image" "github.com/NVIDIA/nvidia-container-toolkit/internal/config/image"
@@ -81,14 +82,25 @@ func NewGraphicsMountsDiscoverer(logger logger.Interface, driver *root.Driver, h
// vulkan ICD files are at {{ .driverRoot }}/vulkan instead of in /etc/vulkan. // vulkan ICD files are at {{ .driverRoot }}/vulkan instead of in /etc/vulkan.
func newVulkanConfigsDiscover(logger logger.Interface, driver *root.Driver) Discover { func newVulkanConfigsDiscover(logger logger.Interface, driver *root.Driver) Discover {
locator := lookup.First(driver.Configs(), driver.Files()) locator := lookup.First(driver.Configs(), driver.Files())
required := []string{
"vulkan/icd.d/nvidia_icd.json",
"vulkan/icd.d/nvidia_layers.json",
"vulkan/implicit_layer.d/nvidia_layers.json",
}
// For some RPM-based driver packages, the vulkan ICD files are installed to
// /usr/share/vulkan/icd.d/nvidia_icd.%{_target_cpu}.json
// We also include this in the list of candidates for the ICD file.
switch runtime.GOARCH {
case "amd64":
required = append(required, "vulkan/icd.d/nvidia_icd.x86_64.json")
case "arm64":
required = append(required, "vulkan/icd.d/nvidia_icd.aarch64.json")
}
return &mountsToContainerPath{ return &mountsToContainerPath{
logger: logger, logger: logger,
locator: locator, locator: locator,
required: []string{ required: required,
"vulkan/icd.d/nvidia_icd.json",
"vulkan/icd.d/nvidia_layers.json",
"vulkan/implicit_layer.d/nvidia_layers.json",
},
containerRoot: "/etc", containerRoot: "/etc",
} }
} }

View File

@@ -25,7 +25,7 @@ import (
func TestGraphicsLibrariesDiscoverer(t *testing.T) { func TestGraphicsLibrariesDiscoverer(t *testing.T) {
logger, _ := testlog.NewNullLogger() logger, _ := testlog.NewNullLogger()
hookCreator := NewHookCreator("/usr/bin/nvidia-cdi-hook", false) hookCreator := NewHookCreator()
testCases := []struct { testCases := []struct {
description string description string

View File

@@ -23,6 +23,33 @@ import (
"tags.cncf.io/container-device-interface/pkg/cdi" "tags.cncf.io/container-device-interface/pkg/cdi"
) )
// A HookName represents a supported CDI hooks.
type HookName string
const (
// AllHooks is a special hook name that allows all hooks to be matched.
AllHooks = HookName("all")
// A ChmodHook is used to set the file mode of the specified paths.
// Deprecated: The chmod hook is deprecated and will be removed in a future release.
ChmodHook = HookName("chmod")
// A CreateSymlinksHook is used to create symlinks in the container.
CreateSymlinksHook = HookName("create-symlinks")
// DisableDeviceNodeModificationHook refers to the hook used to ensure that
// device nodes are not created by libnvidia-ml.so or nvidia-smi in a
// container.
// Added in v1.17.8
DisableDeviceNodeModificationHook = HookName("disable-device-node-modification")
// An EnableCudaCompatHook is used to enabled CUDA Forward Compatibility.
// Added in v1.17.5
EnableCudaCompatHook = HookName("enable-cuda-compat")
// An UpdateLDCacheHook is the hook used to update the ldcache in the
// container. This allows injected libraries to be discoverable.
UpdateLDCacheHook = HookName("update-ldcache")
defaultNvidiaCDIHookPath = "/usr/bin/nvidia-cdi-hook"
)
var _ Discover = (*Hook)(nil) var _ Discover = (*Hook)(nil)
// Devices returns an empty list of devices for a Hook discoverer. // Devices returns an empty list of devices for a Hook discoverer.
@@ -45,52 +72,130 @@ func (h *Hook) Hooks() ([]Hook, error) {
return []Hook{*h}, nil return []Hook{*h}, nil
} }
// Option is a function that configures the nvcdilib type Option func(*cdiHookCreator)
type Option func(*CDIHook)
type CDIHook struct { type cdiHookCreator struct {
nvidiaCDIHookPath string nvidiaCDIHookPath string
debugLogging bool disabledHooks map[HookName]bool
fixedArgs []string
debugLogging bool
} }
// An allDisabledHookCreator is a HookCreator that does not create any hooks.
type allDisabledHookCreator struct{}
// Create returns nil for all hooks for an allDisabledHookCreator.
func (a *allDisabledHookCreator) Create(name HookName, args ...string) *Hook {
return nil
}
// A HookCreator defines an interface for creating discover hooks.
type HookCreator interface { type HookCreator interface {
Create(string, ...string) *Hook Create(HookName, ...string) *Hook
} }
func NewHookCreator(nvidiaCDIHookPath string, debugLogging bool) HookCreator { // WithDisabledHooks sets the set of hooks that are disabled for the CDI hook creator.
CDIHook := &CDIHook{ // This can be specified multiple times.
nvidiaCDIHookPath: nvidiaCDIHookPath, func WithDisabledHooks(hooks ...HookName) Option {
debugLogging: debugLogging, return func(c *cdiHookCreator) {
for _, hook := range hooks {
c.disabledHooks[hook] = true
}
}
}
// WithNVIDIACDIHookPath sets the path to the nvidia-cdi-hook binary.
func WithNVIDIACDIHookPath(nvidiaCDIHookPath string) Option {
return func(c *cdiHookCreator) {
c.nvidiaCDIHookPath = nvidiaCDIHookPath
}
}
func NewHookCreator(opts ...Option) HookCreator {
cdiHookCreator := &cdiHookCreator{
nvidiaCDIHookPath: defaultNvidiaCDIHookPath,
disabledHooks: make(map[HookName]bool),
}
for _, opt := range opts {
opt(cdiHookCreator)
} }
return CDIHook if cdiHookCreator.disabledHooks[AllHooks] {
return &allDisabledHookCreator{}
}
cdiHookCreator.fixedArgs = getFixedArgsForCDIHookCLI(cdiHookCreator.nvidiaCDIHookPath)
return cdiHookCreator
} }
func (c CDIHook) Create(name string, args ...string) *Hook { // Create creates a new hook with the given name and arguments.
if name == "create-symlinks" { // If a hook is disabled, a nil hook is returned.
if len(args) == 0 { func (c cdiHookCreator) Create(name HookName, args ...string) *Hook {
return nil if c.isDisabled(name, args...) {
} return nil
links := []string{}
for _, arg := range args {
links = append(links, "--link", arg)
}
args = links
} }
return &Hook{ return &Hook{
Lifecycle: cdi.CreateContainerHook, Lifecycle: cdi.CreateContainerHook,
Path: c.nvidiaCDIHookPath, Path: c.nvidiaCDIHookPath,
Args: append(c.requiredArgs(name), args...), Args: append(c.requiredArgs(name), c.transformArgs(name, args...)...),
Env: []string{fmt.Sprintf("NVIDIA_CTK_DEBUG=%v", c.debugLogging)}, Env: []string{fmt.Sprintf("NVIDIA_CTK_DEBUG=%v", c.debugLogging)},
} }
} }
func (c CDIHook) requiredArgs(name string) []string { // isDisabled checks if the specified hook name is disabled.
base := filepath.Base(c.nvidiaCDIHookPath) func (c cdiHookCreator) isDisabled(name HookName, args ...string) bool {
if base == "nvidia-ctk" { if c.disabledHooks[name] {
return []string{base, "hook", name} return true
} }
return []string{base, name}
switch name {
case CreateSymlinksHook:
if len(args) == 0 {
return true
}
case ChmodHook:
if len(args) == 0 {
return true
}
}
return false
}
func (c cdiHookCreator) requiredArgs(name HookName) []string {
return append(c.fixedArgs, string(name))
}
func (c cdiHookCreator) transformArgs(name HookName, args ...string) []string {
switch name {
case CreateSymlinksHook:
var transformedArgs []string
for _, arg := range args {
transformedArgs = append(transformedArgs, "--link", arg)
}
return transformedArgs
case ChmodHook:
var transformedArgs = []string{"--mode", "755"}
for _, arg := range args {
transformedArgs = append(transformedArgs, "--path", arg)
}
return transformedArgs
default:
return args
}
}
// getFixedArgsForCDIHookCLI returns the fixed arguments for the hook CLI.
// If the nvidia-ctk binary is used, hooks are implemented under the hook
// subcommand.
// For the nvidia-cdi-hook binary, the hooks are implemented as subcommands of
// the top-level CLI.
func getFixedArgsForCDIHookCLI(nvidiaCDIHookPath string) []string {
base := filepath.Base(nvidiaCDIHookPath)
if base == "nvidia-ctk" {
return []string{base, "hook"}
}
return []string{base}
} }

View File

@@ -72,7 +72,7 @@ func createLDCacheUpdateHook(hookCreator HookCreator, ldconfig string, libraries
args = append(args, "--folder", f) args = append(args, "--folder", f)
} }
return hookCreator.Create("update-ldcache", args...) return hookCreator.Create(UpdateLDCacheHook, args...)
} }
// getLibraryPaths extracts the library dirs from the specified mounts // getLibraryPaths extracts the library dirs from the specified mounts

View File

@@ -31,7 +31,7 @@ const (
func TestLDCacheUpdateHook(t *testing.T) { func TestLDCacheUpdateHook(t *testing.T) {
logger, _ := testlog.NewNullLogger() logger, _ := testlog.NewNullLogger()
hookCreator := NewHookCreator(testNvidiaCDIHookPath, false) hookCreator := NewHookCreator(WithNVIDIACDIHookPath(testNvidiaCDIHookPath))
testCases := []struct { testCases := []struct {
description string description string

View File

@@ -113,7 +113,7 @@ func TestWithWithDriverDotSoSymlinks(t *testing.T) {
expectedHooks: []Hook{ expectedHooks: []Hook{
{ {
Lifecycle: "createContainer", Lifecycle: "createContainer",
Path: "/path/to/nvidia-cdi-hook", Path: "/usr/bin/nvidia-cdi-hook",
Args: []string{"nvidia-cdi-hook", "create-symlinks", "--link", "libcuda.so.1::/usr/lib/libcuda.so"}, Args: []string{"nvidia-cdi-hook", "create-symlinks", "--link", "libcuda.so.1::/usr/lib/libcuda.so"},
Env: []string{"NVIDIA_CTK_DEBUG=false"}, Env: []string{"NVIDIA_CTK_DEBUG=false"},
}, },
@@ -146,7 +146,7 @@ func TestWithWithDriverDotSoSymlinks(t *testing.T) {
expectedHooks: []Hook{ expectedHooks: []Hook{
{ {
Lifecycle: "createContainer", Lifecycle: "createContainer",
Path: "/path/to/nvidia-cdi-hook", Path: "/usr/bin/nvidia-cdi-hook",
Args: []string{"nvidia-cdi-hook", "create-symlinks", "--link", "libcuda.so.1::/usr/lib/libcuda.so"}, Args: []string{"nvidia-cdi-hook", "create-symlinks", "--link", "libcuda.so.1::/usr/lib/libcuda.so"},
Env: []string{"NVIDIA_CTK_DEBUG=false"}, Env: []string{"NVIDIA_CTK_DEBUG=false"},
}, },
@@ -178,7 +178,7 @@ func TestWithWithDriverDotSoSymlinks(t *testing.T) {
expectedHooks: []Hook{ expectedHooks: []Hook{
{ {
Lifecycle: "createContainer", Lifecycle: "createContainer",
Path: "/path/to/nvidia-cdi-hook", Path: "/usr/bin/nvidia-cdi-hook",
Args: []string{"nvidia-cdi-hook", "create-symlinks", "--link", "libcuda.so.1::/usr/lib/libcuda.so"}, Args: []string{"nvidia-cdi-hook", "create-symlinks", "--link", "libcuda.so.1::/usr/lib/libcuda.so"},
Env: []string{"NVIDIA_CTK_DEBUG=false"}, Env: []string{"NVIDIA_CTK_DEBUG=false"},
}, },
@@ -248,7 +248,7 @@ func TestWithWithDriverDotSoSymlinks(t *testing.T) {
}, },
{ {
Lifecycle: "createContainer", Lifecycle: "createContainer",
Path: "/path/to/nvidia-cdi-hook", Path: "/usr/bin/nvidia-cdi-hook",
Args: []string{"nvidia-cdi-hook", "create-symlinks", "--link", "libcuda.so.1::/usr/lib/libcuda.so"}, Args: []string{"nvidia-cdi-hook", "create-symlinks", "--link", "libcuda.so.1::/usr/lib/libcuda.so"},
Env: []string{"NVIDIA_CTK_DEBUG=false"}, Env: []string{"NVIDIA_CTK_DEBUG=false"},
}, },
@@ -298,7 +298,7 @@ func TestWithWithDriverDotSoSymlinks(t *testing.T) {
expectedHooks: []Hook{ expectedHooks: []Hook{
{ {
Lifecycle: "createContainer", Lifecycle: "createContainer",
Path: "/path/to/nvidia-cdi-hook", Path: "/usr/bin/nvidia-cdi-hook",
Args: []string{ Args: []string{
"nvidia-cdi-hook", "create-symlinks", "nvidia-cdi-hook", "create-symlinks",
"--link", "libcuda.so.1::/usr/lib/libcuda.so", "--link", "libcuda.so.1::/usr/lib/libcuda.so",
@@ -311,7 +311,7 @@ func TestWithWithDriverDotSoSymlinks(t *testing.T) {
}, },
} }
hookCreator := NewHookCreator("/path/to/nvidia-cdi-hook", false) hookCreator := NewHookCreator()
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) { t.Run(tc.description, func(t *testing.T) {
d := WithDriverDotSoSymlinks( d := WithDriverDotSoSymlinks(

View File

@@ -184,7 +184,7 @@ func TestResolveAutoMode(t *testing.T) {
expectedMode: "legacy", expectedMode: "legacy",
}, },
{ {
description: "cdi mount and non-CDI envvar resolves to legacy", description: "cdi mount and non-CDI envvar resolves to cdi",
mode: "auto", mode: "auto",
envmap: map[string]string{ envmap: map[string]string{
"NVIDIA_VISIBLE_DEVICES": "0", "NVIDIA_VISIBLE_DEVICES": "0",
@@ -197,6 +197,22 @@ func TestResolveAutoMode(t *testing.T) {
"tegra": false, "tegra": false,
"nvgpu": false, "nvgpu": false,
}, },
expectedMode: "cdi",
},
{
description: "non-cdi mount and CDI envvar resolves to legacy",
mode: "auto",
envmap: map[string]string{
"NVIDIA_VISIBLE_DEVICES": "nvidia.com/gpu=0",
},
mounts: []string{
"/var/run/nvidia-container-devices/0",
},
info: map[string]bool{
"nvml": true,
"tegra": false,
"nvgpu": false,
},
expectedMode: "legacy", expectedMode: "legacy",
}, },
} }
@@ -232,6 +248,8 @@ func TestResolveAutoMode(t *testing.T) {
image, _ := image.New( image, _ := image.New(
image.WithEnvMap(tc.envmap), image.WithEnvMap(tc.envmap),
image.WithMounts(mounts), image.WithMounts(mounts),
image.WithAcceptDeviceListAsVolumeMounts(true),
image.WithAcceptEnvvarUnprivileged(true),
) )
mode := resolveMode(logger, tc.mode, image, properties) mode := resolveMode(logger, tc.mode, image, properties)
require.EqualValues(t, tc.expectedMode, mode) require.EqualValues(t, tc.expectedMode, mode)

View File

@@ -18,7 +18,6 @@ package modifier
import ( import (
"fmt" "fmt"
"strings"
"tags.cncf.io/container-device-interface/pkg/parser" "tags.cncf.io/container-device-interface/pkg/parser"
@@ -34,11 +33,13 @@ import (
// NewCDIModifier creates an OCI spec modifier that determines the modifications to make based on the // NewCDIModifier creates an OCI spec modifier that determines the modifications to make based on the
// CDI specifications available on the system. The NVIDIA_VISIBLE_DEVICES environment variable is // CDI specifications available on the system. The NVIDIA_VISIBLE_DEVICES environment variable is
// used to select the devices to include. // used to select the devices to include.
func NewCDIModifier(logger logger.Interface, cfg *config.Config, ociSpec oci.Spec) (oci.SpecModifier, error) { func NewCDIModifier(logger logger.Interface, cfg *config.Config, image image.CUDA) (oci.SpecModifier, error) {
devices, err := getDevicesFromSpec(logger, ociSpec, cfg) deviceRequestor := newCDIDeviceRequestor(
if err != nil { logger,
return nil, fmt.Errorf("failed to get required devices from OCI specification: %v", err) image,
} cfg.NVIDIAContainerRuntimeConfig.Modes.CDI.DefaultKind,
)
devices := deviceRequestor.DeviceRequests()
if len(devices) == 0 { if len(devices) == 0 {
logger.Debugf("No devices requested; no modification required.") logger.Debugf("No devices requested; no modification required.")
return nil, nil return nil, nil
@@ -65,87 +66,38 @@ func NewCDIModifier(logger logger.Interface, cfg *config.Config, ociSpec oci.Spe
) )
} }
func getDevicesFromSpec(logger logger.Interface, ociSpec oci.Spec, cfg *config.Config) ([]string, error) { type deviceRequestor interface {
rawSpec, err := ociSpec.Load() DeviceRequests() []string
if err != nil { }
return nil, fmt.Errorf("failed to load OCI spec: %v", err)
}
annotationDevices, err := getAnnotationDevices(cfg.NVIDIAContainerRuntimeConfig.Modes.CDI.AnnotationPrefixes, rawSpec.Annotations) type cdiDeviceRequestor struct {
if err != nil { image image.CUDA
return nil, fmt.Errorf("failed to parse container annotations: %v", err) logger logger.Interface
} defaultKind string
if len(annotationDevices) > 0 { }
return annotationDevices, nil
}
container, err := image.NewCUDAImageFromSpec(rawSpec) func newCDIDeviceRequestor(logger logger.Interface, image image.CUDA, defaultKind string) deviceRequestor {
if err != nil { c := &cdiDeviceRequestor{
return nil, err logger: logger,
} image: image,
if cfg.AcceptDeviceListAsVolumeMounts { defaultKind: defaultKind,
mountDevices := container.CDIDevicesFromMounts()
if len(mountDevices) > 0 {
return mountDevices, nil
}
} }
return withUniqueDevices(c)
}
func (c *cdiDeviceRequestor) DeviceRequests() []string {
if c == nil {
return nil
}
var devices []string var devices []string
seen := make(map[string]bool) for _, name := range c.image.VisibleDevices() {
for _, name := range container.VisibleDevicesFromEnvVar() {
if !parser.IsQualifiedName(name) { if !parser.IsQualifiedName(name) {
name = fmt.Sprintf("%s=%s", cfg.NVIDIAContainerRuntimeConfig.Modes.CDI.DefaultKind, name) name = fmt.Sprintf("%s=%s", c.defaultKind, name)
}
if seen[name] {
logger.Debugf("Ignoring duplicate device %q", name)
continue
} }
devices = append(devices, name) devices = append(devices, name)
} }
if len(devices) == 0 { return devices
return nil, nil
}
if cfg.AcceptEnvvarUnprivileged || image.IsPrivileged(rawSpec) {
return devices, nil
}
logger.Warningf("Ignoring devices specified in NVIDIA_VISIBLE_DEVICES: %v", devices)
return nil, nil
}
// getAnnotationDevices returns a list of devices specified in the annotations.
// Keys starting with the specified prefixes are considered and expected to contain a comma-separated list of
// fully-qualified CDI devices names. If any device name is not fully-quality an error is returned.
// The list of returned devices is deduplicated.
func getAnnotationDevices(prefixes []string, annotations map[string]string) ([]string, error) {
devicesByKey := make(map[string][]string)
for key, value := range annotations {
for _, prefix := range prefixes {
if strings.HasPrefix(key, prefix) {
devicesByKey[key] = strings.Split(value, ",")
}
}
}
seen := make(map[string]bool)
var annotationDevices []string
for key, devices := range devicesByKey {
for _, device := range devices {
if !parser.IsQualifiedName(device) {
return nil, fmt.Errorf("invalid device name %q in annotation %q", device, key)
}
if seen[device] {
continue
}
annotationDevices = append(annotationDevices, device)
seen[device] = true
}
}
return annotationDevices, nil
} }
// filterAutomaticDevices searches for "automatic" device names in the input slice. // filterAutomaticDevices searches for "automatic" device names in the input slice.
@@ -169,7 +121,7 @@ func newAutomaticCDISpecModifier(logger logger.Interface, cfg *config.Config, de
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to generate CDI spec: %w", err) return nil, fmt.Errorf("failed to generate CDI spec: %w", err)
} }
cdiModifier, err := cdi.New( cdiDeviceRequestor, err := cdi.New(
cdi.WithLogger(logger), cdi.WithLogger(logger),
cdi.WithSpec(spec.Raw()), cdi.WithSpec(spec.Raw()),
) )
@@ -177,7 +129,7 @@ func newAutomaticCDISpecModifier(logger logger.Interface, cfg *config.Config, de
return nil, fmt.Errorf("failed to construct CDI modifier: %w", err) return nil, fmt.Errorf("failed to construct CDI modifier: %w", err)
} }
return cdiModifier, nil return cdiDeviceRequestor, nil
} }
func generateAutomaticCDISpec(logger logger.Interface, cfg *config.Config, devices []string) (spec.Interface, error) { func generateAutomaticCDISpec(logger logger.Interface, cfg *config.Config, devices []string) (spec.Interface, error) {
@@ -192,26 +144,35 @@ func generateAutomaticCDISpec(logger logger.Interface, cfg *config.Config, devic
return nil, fmt.Errorf("failed to construct CDI library: %w", err) return nil, fmt.Errorf("failed to construct CDI library: %w", err)
} }
identifiers := []string{} var identifiers []string
for _, device := range devices { for _, device := range devices {
_, _, id := parser.ParseDevice(device) _, _, id := parser.ParseDevice(device)
identifiers = append(identifiers, id) identifiers = append(identifiers, id)
} }
deviceSpecs, err := cdilib.GetDeviceSpecsByID(identifiers...) return cdilib.GetSpec(identifiers...)
if err != nil { }
return nil, fmt.Errorf("failed to get CDI device specs: %w", err)
} type deduplicatedDeviceRequestor struct {
deviceRequestor
commonEdits, err := cdilib.GetCommonEdits() }
if err != nil {
return nil, fmt.Errorf("failed to get common CDI spec edits: %w", err) func withUniqueDevices(deviceRequestor deviceRequestor) deviceRequestor {
} return &deduplicatedDeviceRequestor{deviceRequestor: deviceRequestor}
}
return spec.New(
spec.WithDeviceSpecs(deviceSpecs), func (d *deduplicatedDeviceRequestor) DeviceRequests() []string {
spec.WithEdits(*commonEdits.ContainerEdits), if d == nil {
spec.WithVendor("runtime.nvidia.com"), return nil
spec.WithClass("gpu"), }
) seen := make(map[string]bool)
var devices []string
for _, device := range d.deviceRequestor.DeviceRequests() {
if seen[device] {
continue
}
seen[device] = true
devices = append(devices, device)
}
return devices
} }

View File

@@ -17,76 +17,144 @@
package modifier package modifier
import ( import (
"fmt"
"testing" "testing"
"github.com/opencontainers/runtime-spec/specs-go"
testlog "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/NVIDIA/nvidia-container-toolkit/internal/config/image"
) )
func TestGetAnnotationDevices(t *testing.T) { func TestDeviceRequests(t *testing.T) {
logger, _ := testlog.NewNullLogger()
testCases := []struct { testCases := []struct {
description string description string
input cdiDeviceRequestor
spec *specs.Spec
prefixes []string prefixes []string
annotations map[string]string
expectedDevices []string expectedDevices []string
expectedError error
}{ }{
{ {
description: "no annotations", description: "empty spec yields no devices",
},
{
description: "cdi devices from mounts",
input: cdiDeviceRequestor{
defaultKind: "nvidia.com/gpu",
},
spec: &specs.Spec{
Mounts: []specs.Mount{
{
Destination: "/var/run/nvidia-container-devices/cdi/nvidia.com/gpu/0",
Source: "/dev/null",
},
{
Destination: "/var/run/nvidia-container-devices/cdi/nvidia.com/gpu/1",
Source: "/dev/null",
},
},
},
expectedDevices: []string{"nvidia.com/gpu=0", "nvidia.com/gpu=1"},
},
{
description: "cdi devices from envvar",
input: cdiDeviceRequestor{
defaultKind: "nvidia.com/gpu",
},
spec: &specs.Spec{
Process: &specs.Process{
Env: []string{"NVIDIA_VISIBLE_DEVICES=0,example.com/class=device"},
},
},
expectedDevices: []string{"nvidia.com/gpu=0", "example.com/class=device"},
}, },
{ {
description: "no matching annotations", description: "no matching annotations",
prefixes: []string{"not-prefix/"}, prefixes: []string{"not-prefix/"},
annotations: map[string]string{ spec: &specs.Spec{
"prefix/foo": "example.com/device=bar", Annotations: map[string]string{
"prefix/foo": "example.com/device=bar",
},
}, },
}, },
{ {
description: "single matching annotation", description: "single matching annotation",
prefixes: []string{"prefix/"}, prefixes: []string{"prefix/"},
annotations: map[string]string{ spec: &specs.Spec{
"prefix/foo": "example.com/device=bar", Annotations: map[string]string{
"prefix/foo": "example.com/device=bar",
},
}, },
expectedDevices: []string{"example.com/device=bar"}, expectedDevices: []string{"example.com/device=bar"},
}, },
{ {
description: "multiple matching annotations", description: "multiple matching annotations",
prefixes: []string{"prefix/", "another-prefix/"}, prefixes: []string{"prefix/", "another-prefix/"},
annotations: map[string]string{ spec: &specs.Spec{
"prefix/foo": "example.com/device=bar", Annotations: map[string]string{
"another-prefix/bar": "example.com/device=baz", "prefix/foo": "example.com/device=bar",
"another-prefix/bar": "example.com/device=baz",
},
}, },
expectedDevices: []string{"example.com/device=bar", "example.com/device=baz"}, expectedDevices: []string{"example.com/device=bar", "example.com/device=baz"},
}, },
{ {
description: "multiple matching annotations with duplicate devices", description: "multiple matching annotations with duplicate devices",
prefixes: []string{"prefix/", "another-prefix/"}, prefixes: []string{"prefix/", "another-prefix/"},
annotations: map[string]string{ spec: &specs.Spec{
"prefix/foo": "example.com/device=bar", Annotations: map[string]string{
"another-prefix/bar": "example.com/device=bar", "prefix/foo": "example.com/device=bar",
"another-prefix/bar": "example.com/device=bar",
},
}, },
expectedDevices: []string{"example.com/device=bar"}, expectedDevices: []string{"example.com/device=bar", "example.com/device=bar"},
}, },
{ {
description: "invalid devices", description: "devices in annotations are expanded",
prefixes: []string{"prefix/"}, input: cdiDeviceRequestor{
annotations: map[string]string{ defaultKind: "nvidia.com/gpu",
"prefix/foo": "example.com/device",
}, },
expectedError: fmt.Errorf("invalid device %q", "example.com/device"), prefixes: []string{"prefix/"},
spec: &specs.Spec{
Annotations: map[string]string{
"prefix/foo": "device",
},
},
expectedDevices: []string{"nvidia.com/gpu=device"},
},
{
description: "invalid devices in annotations are treated as strings",
input: cdiDeviceRequestor{
defaultKind: "nvidia.com/gpu",
},
prefixes: []string{"prefix/"},
spec: &specs.Spec{
Annotations: map[string]string{
"prefix/foo": "example.com/device",
},
},
expectedDevices: []string{"nvidia.com/gpu=example.com/device"},
}, },
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) { tc.input.logger = logger
devices, err := getAnnotationDevices(tc.prefixes, tc.annotations)
if tc.expectedError != nil {
require.Error(t, err)
return
}
image, err := image.NewCUDAImageFromSpec(
tc.spec,
image.WithAcceptDeviceListAsVolumeMounts(true),
image.WithAcceptEnvvarUnprivileged(true),
image.WithAnnotationsPrefixes(tc.prefixes),
)
require.NoError(t, err)
tc.input.image = image
t.Run(tc.description, func(t *testing.T) {
devices := tc.input.DeviceRequests()
require.NoError(t, err) require.NoError(t, err)
require.ElementsMatch(t, tc.expectedDevices, devices) require.EqualValues(t, tc.expectedDevices, devices)
}) })
} }
} }

View File

@@ -48,7 +48,7 @@ func NewFeatureGatedModifier(logger logger.Interface, cfg *config.Config, image
devRoot := cfg.NVIDIAContainerCLIConfig.Root devRoot := cfg.NVIDIAContainerCLIConfig.Root
if image.Getenv("NVIDIA_GDS") == "enabled" { if image.Getenv("NVIDIA_GDS") == "enabled" {
d, err := discover.NewGDSDiscoverer(logger, driverRoot, devRoot) d, err := discover.NewGDSDiscoverer(logger, driverRoot)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to construct discoverer for GDS devices: %w", err) return nil, fmt.Errorf("failed to construct discoverer for GDS devices: %w", err)
} }

View File

@@ -183,7 +183,7 @@ func TestDiscovererFromCSVFiles(t *testing.T) {
}, },
} }
hookCreator := discover.NewHookCreator("/usr/bin/nvidia-cdi-hook", false) hookCreator := discover.NewHookCreator()
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) { t.Run(tc.description, func(t *testing.T) {
defer setGetTargetsFromCSVFiles(tc.moutSpecs)() defer setGetTargetsFromCSVFiles(tc.moutSpecs)()

View File

@@ -18,7 +18,6 @@ package runtime
import ( import (
"fmt" "fmt"
"os"
"github.com/NVIDIA/nvidia-container-toolkit/internal/config" "github.com/NVIDIA/nvidia-container-toolkit/internal/config"
"github.com/NVIDIA/nvidia-container-toolkit/internal/config/image" "github.com/NVIDIA/nvidia-container-toolkit/internal/config/image"
@@ -66,29 +65,17 @@ func newNVIDIAContainerRuntime(logger logger.Interface, cfg *config.Config, argv
// newSpecModifier is a factory method that creates constructs an OCI spec modifer based on the provided config. // newSpecModifier is a factory method that creates constructs an OCI spec modifer based on the provided config.
func newSpecModifier(logger logger.Interface, cfg *config.Config, ociSpec oci.Spec, driver *root.Driver) (oci.SpecModifier, error) { func newSpecModifier(logger logger.Interface, cfg *config.Config, ociSpec oci.Spec, driver *root.Driver) (oci.SpecModifier, error) {
rawSpec, err := ociSpec.Load() mode, image, err := initRuntimeModeAndImage(logger, cfg, ociSpec)
if err != nil {
return nil, fmt.Errorf("failed to load OCI spec: %v", err)
}
image, err := image.NewCUDAImageFromSpec(rawSpec)
if err != nil { if err != nil {
return nil, err return nil, err
} }
hookCreator := discover.NewHookCreator( modeModifier, err := newModeModifier(logger, mode, cfg, *image)
cfg.NVIDIACTKConfig.Path,
cfg.NVIDIAContainerRuntimeConfig.DebugFilePath == "" || cfg.NVIDIAContainerRuntimeConfig.DebugFilePath == os.DevNull,
)
mode := info.ResolveAutoMode(logger, cfg.NVIDIAContainerRuntimeConfig.Mode, image)
// We update the mode here so that we can continue passing just the config to other functions.
cfg.NVIDIAContainerRuntimeConfig.Mode = mode
modeModifier, err := newModeModifier(logger, mode, cfg, ociSpec, image)
if err != nil { if err != nil {
return nil, err return nil, err
} }
hookCreator := discover.NewHookCreator(discover.WithNVIDIACDIHookPath(cfg.NVIDIACTKConfig.Path))
var modifiers modifier.List var modifiers modifier.List
for _, modifierType := range supportedModifierTypes(mode) { for _, modifierType := range supportedModifierTypes(mode) {
switch modifierType { switch modifierType {
@@ -97,13 +84,13 @@ func newSpecModifier(logger logger.Interface, cfg *config.Config, ociSpec oci.Sp
case "nvidia-hook-remover": case "nvidia-hook-remover":
modifiers = append(modifiers, modifier.NewNvidiaContainerRuntimeHookRemover(logger)) modifiers = append(modifiers, modifier.NewNvidiaContainerRuntimeHookRemover(logger))
case "graphics": case "graphics":
graphicsModifier, err := modifier.NewGraphicsModifier(logger, cfg, image, driver, hookCreator) graphicsModifier, err := modifier.NewGraphicsModifier(logger, cfg, *image, driver, hookCreator)
if err != nil { if err != nil {
return nil, err return nil, err
} }
modifiers = append(modifiers, graphicsModifier) modifiers = append(modifiers, graphicsModifier)
case "feature-gated": case "feature-gated":
featureGatedModifier, err := modifier.NewFeatureGatedModifier(logger, cfg, image, driver, hookCreator) featureGatedModifier, err := modifier.NewFeatureGatedModifier(logger, cfg, *image, driver, hookCreator)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -114,19 +101,58 @@ func newSpecModifier(logger logger.Interface, cfg *config.Config, ociSpec oci.Sp
return modifiers, nil return modifiers, nil
} }
func newModeModifier(logger logger.Interface, mode string, cfg *config.Config, ociSpec oci.Spec, image image.CUDA) (oci.SpecModifier, error) { func newModeModifier(logger logger.Interface, mode string, cfg *config.Config, image image.CUDA) (oci.SpecModifier, error) {
switch mode { switch mode {
case "legacy": case "legacy":
return modifier.NewStableRuntimeModifier(logger, cfg.NVIDIAContainerRuntimeHookConfig.Path), nil return modifier.NewStableRuntimeModifier(logger, cfg.NVIDIAContainerRuntimeHookConfig.Path), nil
case "csv": case "csv":
return modifier.NewCSVModifier(logger, cfg, image) return modifier.NewCSVModifier(logger, cfg, image)
case "cdi": case "cdi":
return modifier.NewCDIModifier(logger, cfg, ociSpec) return modifier.NewCDIModifier(logger, cfg, image)
} }
return nil, fmt.Errorf("invalid runtime mode: %v", cfg.NVIDIAContainerRuntimeConfig.Mode) return nil, fmt.Errorf("invalid runtime mode: %v", cfg.NVIDIAContainerRuntimeConfig.Mode)
} }
// initRuntimeModeAndImage constructs an image from the specified OCI runtime
// specification and runtime config.
// The image is also used to determine the runtime mode to apply.
// If a non-CDI mode is detected we ensure that the image does not process
// annotation devices.
func initRuntimeModeAndImage(logger logger.Interface, cfg *config.Config, ociSpec oci.Spec) (string, *image.CUDA, error) {
rawSpec, err := ociSpec.Load()
if err != nil {
return "", nil, fmt.Errorf("failed to load OCI spec: %v", err)
}
image, err := image.NewCUDAImageFromSpec(
rawSpec,
image.WithLogger(logger),
image.WithAcceptDeviceListAsVolumeMounts(cfg.AcceptDeviceListAsVolumeMounts),
image.WithAcceptEnvvarUnprivileged(cfg.AcceptEnvvarUnprivileged),
image.WithAnnotationsPrefixes(cfg.NVIDIAContainerRuntimeConfig.Modes.CDI.AnnotationPrefixes),
)
if err != nil {
return "", nil, err
}
mode := info.ResolveAutoMode(logger, cfg.NVIDIAContainerRuntimeConfig.Mode, image)
// We update the mode here so that we can continue passing just the config to other functions.
cfg.NVIDIAContainerRuntimeConfig.Mode = mode
if mode == "cdi" || len(cfg.NVIDIAContainerRuntimeConfig.Modes.CDI.AnnotationPrefixes) == 0 {
return mode, &image, nil
}
// For non-cdi modes we explicitly set the annotation prefixes to nil and
// call this function again to force a reconstruction of the image.
// Note that since the mode is now explicitly set, we will effectively skip
// the mode resolution.
cfg.NVIDIAContainerRuntimeConfig.Modes.CDI.AnnotationPrefixes = nil
return initRuntimeModeAndImage(logger, cfg, ociSpec)
}
// supportedModifierTypes returns the modifiers supported for a specific runtime mode. // supportedModifierTypes returns the modifiers supported for a specific runtime mode.
func supportedModifierTypes(mode string) []string { func supportedModifierTypes(mode string) []string {
switch mode { switch mode {

View File

@@ -1,3 +1,5 @@
nvidia-container-runtime /usr/bin nvidia-container-runtime /usr/bin
nvidia-ctk /usr/bin nvidia-ctk /usr/bin
nvidia-cdi-hook /usr/bin nvidia-cdi-hook /usr/bin
nvidia-cdi-refresh.service /etc/systemd/system/
nvidia-cdi-refresh.path /etc/systemd/system/

View File

@@ -5,6 +5,16 @@ set -e
case "$1" in case "$1" in
configure) configure)
/usr/bin/nvidia-ctk --quiet config --config-file=/etc/nvidia-container-runtime/config.toml --in-place /usr/bin/nvidia-ctk --quiet config --config-file=/etc/nvidia-container-runtime/config.toml --in-place
if command -v systemctl >/dev/null 2>&1 \
&& systemctl --quiet is-system-running 2>/dev/null; then
systemctl daemon-reload || true
if [ -z "$2" ]; then # $2 empty → first install
systemctl enable --now nvidia-cdi-refresh.path || true
fi
fi
;; ;;
abort-upgrade|abort-remove|abort-deconfigure) abort-upgrade|abort-remove|abort-deconfigure)

View File

@@ -5,3 +5,14 @@
%: %:
dh $@ dh $@
override_dh_fixperms:
dh_fixperms
chmod 755 debian/$(shell dh_listpackages)/usr/bin/nvidia-container-runtime-hook || true
chmod 755 debian/$(shell dh_listpackages)/usr/bin/nvidia-container-runtime || true
chmod 755 debian/$(shell dh_listpackages)/usr/bin/nvidia-container-runtime.cdi || true
chmod 755 debian/$(shell dh_listpackages)/usr/bin/nvidia-container-runtime.legacy || true
chmod 755 debian/$(shell dh_listpackages)/usr/bin/nvidia-ctk || true
chmod 755 debian/$(shell dh_listpackages)/usr/bin/nvidia-cdi-hook || true
chmod 644 debian/$(shell dh_listpackages)/etc/systemd/system/nvidia-cdi-refresh.service || true
chmod 644 debian/$(shell dh_listpackages)/etc/systemd/system/nvidia-cdi-refresh.path || true

View File

@@ -17,6 +17,8 @@ Source3: nvidia-container-runtime
Source4: nvidia-container-runtime.cdi Source4: nvidia-container-runtime.cdi
Source5: nvidia-container-runtime.legacy Source5: nvidia-container-runtime.legacy
Source6: nvidia-cdi-hook Source6: nvidia-cdi-hook
Source7: nvidia-cdi-refresh.service
Source8: nvidia-cdi-refresh.path
Obsoletes: nvidia-container-runtime <= 3.5.0-1, nvidia-container-runtime-hook <= 1.4.0-2 Obsoletes: nvidia-container-runtime <= 3.5.0-1, nvidia-container-runtime-hook <= 1.4.0-2
Provides: nvidia-container-runtime Provides: nvidia-container-runtime
@@ -28,16 +30,20 @@ Requires: nvidia-container-toolkit-base == %{version}-%{release}
Provides tools and utilities to enable GPU support in containers. Provides tools and utilities to enable GPU support in containers.
%prep %prep
cp %{SOURCE0} %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} %{SOURCE6} . cp %{SOURCE0} %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} %{SOURCE6} %{SOURCE7} %{SOURCE8} .
%install %install
mkdir -p %{buildroot}%{_bindir} mkdir -p %{buildroot}%{_bindir}
mkdir -p %{buildroot}%{_sysconfdir}/systemd/system/
install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime-hook install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime-hook
install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime
install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime.cdi install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime.cdi
install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime.legacy install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime.legacy
install -m 755 -t %{buildroot}%{_bindir} nvidia-ctk install -m 755 -t %{buildroot}%{_bindir} nvidia-ctk
install -m 755 -t %{buildroot}%{_bindir} nvidia-cdi-hook install -m 755 -t %{buildroot}%{_bindir} nvidia-cdi-hook
install -m 644 -t %{buildroot}%{_sysconfdir}/systemd/system nvidia-cdi-refresh.service
install -m 644 -t %{buildroot}%{_sysconfdir}/systemd/system nvidia-cdi-refresh.path
%post %post
if [ $1 -gt 1 ]; then # only on package upgrade if [ $1 -gt 1 ]; then # only on package upgrade
@@ -45,6 +51,17 @@ if [ $1 -gt 1 ]; then # only on package upgrade
cp -af %{_bindir}/nvidia-container-runtime-hook %{_localstatedir}/lib/rpm-state/nvidia-container-toolkit cp -af %{_bindir}/nvidia-container-runtime-hook %{_localstatedir}/lib/rpm-state/nvidia-container-toolkit
fi fi
# Reload systemd unit cache
if command -v systemctl >/dev/null 2>&1 \
&& systemctl --quiet is-system-running 2>/dev/null; then
systemctl daemon-reload || true
# On fresh install ($1 == 1) enable the path unit so it starts at boot
if [ "$1" -eq 1 ]; then
systemctl enable --now nvidia-cdi-refresh.path || true
fi
fi
%posttrans %posttrans
if [ ! -e %{_bindir}/nvidia-container-runtime-hook ]; then if [ ! -e %{_bindir}/nvidia-container-runtime-hook ]; then
# repairing lost file nvidia-container-runtime-hook # repairing lost file nvidia-container-runtime-hook
@@ -89,6 +106,8 @@ Provides tools such as the NVIDIA Container Runtime and NVIDIA Container Toolkit
%{_bindir}/nvidia-container-runtime %{_bindir}/nvidia-container-runtime
%{_bindir}/nvidia-ctk %{_bindir}/nvidia-ctk
%{_bindir}/nvidia-cdi-hook %{_bindir}/nvidia-cdi-hook
%{_sysconfdir}/systemd/system/nvidia-cdi-refresh.service
%{_sysconfdir}/systemd/system/nvidia-cdi-refresh.path
# The OPERATOR EXTENSIONS package consists of components that are required to enable GPU support in Kubernetes. # The OPERATOR EXTENSIONS package consists of components that are required to enable GPU support in Kubernetes.
# This package is not distributed as part of the NVIDIA Container Toolkit RPMs. # This package is not distributed as part of the NVIDIA Container Toolkit RPMs.

View File

@@ -21,12 +21,13 @@ import (
"tags.cncf.io/container-device-interface/pkg/cdi" "tags.cncf.io/container-device-interface/pkg/cdi"
"tags.cncf.io/container-device-interface/specs-go" "tags.cncf.io/container-device-interface/specs-go"
"github.com/NVIDIA/nvidia-container-toolkit/internal/discover"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/spec" "github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/spec"
) )
// Interface defines the API for the nvcdi package // Interface defines the API for the nvcdi package
type Interface interface { type Interface interface {
GetSpec() (spec.Interface, error) GetSpec(...string) (spec.Interface, error)
GetCommonEdits() (*cdi.ContainerEdits, error) GetCommonEdits() (*cdi.ContainerEdits, error)
GetAllDeviceSpecs() ([]specs.Device, error) GetAllDeviceSpecs() ([]specs.Device, error)
GetGPUDeviceEdits(device.Device) (*cdi.ContainerEdits, error) GetGPUDeviceEdits(device.Device) (*cdi.ContainerEdits, error)
@@ -36,14 +37,32 @@ type Interface interface {
GetDeviceSpecsByID(...string) ([]specs.Device, error) GetDeviceSpecsByID(...string) ([]specs.Device, error)
} }
// A HookName refers to one of the predefined set of CDI hooks that may be // A HookName represents one of the predefined NVIDIA CDI hooks.
// included in the generated CDI specification. type HookName = discover.HookName
type HookName string
const ( const (
// HookEnableCudaCompat refers to the hook used to enable CUDA Forward Compatibility. // AllHooks is a special hook name that allows all hooks to be matched.
// This was added with v1.17.5 of the NVIDIA Container Toolkit. AllHooks = discover.AllHooks
HookEnableCudaCompat = HookName("enable-cuda-compat")
// A CreateSymlinksHook is used to create symlinks in the container.
CreateSymlinksHook = discover.CreateSymlinksHook
// DisableDeviceNodeModificationHook refers to the hook used to ensure that
// device nodes are not created by libnvidia-ml.so or nvidia-smi in a
// container.
// Added in v1.17.8
DisableDeviceNodeModificationHook = discover.DisableDeviceNodeModificationHook
// An EnableCudaCompatHook is used to enabled CUDA Forward Compatibility.
// Added in v1.17.5
EnableCudaCompatHook = discover.EnableCudaCompatHook
// An UpdateLDCacheHook is used to update the ldcache in the container.
UpdateLDCacheHook = discover.UpdateLDCacheHook
// Deprecated: Use CreateSymlinksHook instead.
HookCreateSymlinks = CreateSymlinksHook
// Deprecated: Use EnableCudaCompatHook instead.
HookEnableCudaCompat = EnableCudaCompatHook
// Deprecated: Use UpdateLDCacheHook instead.
HookUpdateLDCache = UpdateLDCacheHook
) )
// A FeatureFlag refers to a specific feature that can be toggled in the CDI api. // A FeatureFlag refers to a specific feature that can be toggled in the CDI api.

View File

@@ -106,15 +106,16 @@ func (l *nvcdilib) NewDriverLibraryDiscoverer(version string) (discover.Discover
) )
discoverers = append(discoverers, driverDotSoSymlinksDiscoverer) discoverers = append(discoverers, driverDotSoSymlinksDiscoverer)
if l.HookIsSupported(HookEnableCudaCompat) { // TODO: The following should use the version directly.
// TODO: The following should use the version directly. cudaCompatLibHookDiscoverer := discover.NewCUDACompatHookDiscoverer(l.logger, l.hookCreator, l.driver)
cudaCompatLibHookDiscoverer := discover.NewCUDACompatHookDiscoverer(l.logger, l.hookCreator, l.driver) discoverers = append(discoverers, cudaCompatLibHookDiscoverer)
discoverers = append(discoverers, cudaCompatLibHookDiscoverer)
}
updateLDCache, _ := discover.NewLDCacheUpdateHook(l.logger, libraries, l.hookCreator, l.ldconfigPath) updateLDCache, _ := discover.NewLDCacheUpdateHook(l.logger, libraries, l.hookCreator, l.ldconfigPath)
discoverers = append(discoverers, updateLDCache) discoverers = append(discoverers, updateLDCache)
disableDeviceNodeModification := l.hookCreator.Create(DisableDeviceNodeModificationHook)
discoverers = append(discoverers, disableDeviceNodeModification)
d := discover.Merge(discoverers...) d := discover.Merge(discoverers...)
return d, nil return d, nil

View File

@@ -40,13 +40,12 @@ var requiredDriverStoreFiles = []string{
// newWSLDriverDiscoverer returns a Discoverer for WSL2 drivers. // newWSLDriverDiscoverer returns a Discoverer for WSL2 drivers.
func newWSLDriverDiscoverer(logger logger.Interface, driverRoot string, hookCreator discover.HookCreator, ldconfigPath string) (discover.Discover, error) { func newWSLDriverDiscoverer(logger logger.Interface, driverRoot string, hookCreator discover.HookCreator, ldconfigPath string) (discover.Discover, error) {
err := dxcore.Init() if err := dxcore.Init(); err != nil {
if err != nil { return nil, fmt.Errorf("failed to initialize dxcore: %w", err)
return nil, fmt.Errorf("failed to initialize dxcore: %v", err)
} }
defer func() { defer func() {
if err := dxcore.Shutdown(); err != nil { if err := dxcore.Shutdown(); err != nil {
logger.Warningf("failed to shutdown dxcore: %v", err) logger.Warningf("failed to shutdown dxcore: %w", err)
} }
}() }()
@@ -54,32 +53,19 @@ func newWSLDriverDiscoverer(logger logger.Interface, driverRoot string, hookCrea
if len(driverStorePaths) == 0 { if len(driverStorePaths) == 0 {
return nil, fmt.Errorf("no driver store paths found") return nil, fmt.Errorf("no driver store paths found")
} }
if len(driverStorePaths) > 1 {
logger.Warningf("Found multiple driver store paths: %v", driverStorePaths)
}
logger.Infof("Using WSL driver store paths: %v", driverStorePaths) logger.Infof("Using WSL driver store paths: %v", driverStorePaths)
return newWSLDriverStoreDiscoverer(logger, driverRoot, hookCreator, ldconfigPath, driverStorePaths) driverStorePaths = append(driverStorePaths, "/usr/lib/wsl/lib")
}
// newWSLDriverStoreDiscoverer returns a Discoverer for WSL2 drivers in the driver store associated with a dxcore adapter. driverStoreMounts := discover.NewMounts(
func newWSLDriverStoreDiscoverer(logger logger.Interface, driverRoot string, hookCreator discover.HookCreator, ldconfigPath string, driverStorePaths []string) (discover.Discover, error) {
var searchPaths []string
seen := make(map[string]bool)
for _, path := range driverStorePaths {
if seen[path] {
continue
}
searchPaths = append(searchPaths, path)
}
if len(searchPaths) > 1 {
logger.Warningf("Found multiple driver store paths: %v", searchPaths)
}
searchPaths = append(searchPaths, "/usr/lib/wsl/lib")
libraries := discover.NewMounts(
logger, logger,
lookup.NewFileLocator( lookup.NewFileLocator(
lookup.WithLogger(logger), lookup.WithLogger(logger),
lookup.WithSearchPaths( lookup.WithSearchPaths(
searchPaths..., driverStorePaths...,
), ),
lookup.WithCount(1), lookup.WithCount(1),
), ),
@@ -89,14 +75,14 @@ func newWSLDriverStoreDiscoverer(logger logger.Interface, driverRoot string, hoo
symlinkHook := nvidiaSMISimlinkHook{ symlinkHook := nvidiaSMISimlinkHook{
logger: logger, logger: logger,
mountsFrom: libraries, mountsFrom: driverStoreMounts,
hookCreator: hookCreator, hookCreator: hookCreator,
} }
ldcacheHook, _ := discover.NewLDCacheUpdateHook(logger, libraries, hookCreator, ldconfigPath) ldcacheHook, _ := discover.NewLDCacheUpdateHook(logger, driverStoreMounts, hookCreator, ldconfigPath)
d := discover.Merge( d := discover.Merge(
libraries, driverStoreMounts,
symlinkHook, symlinkHook,
ldcacheHook, ldcacheHook,
) )
@@ -135,7 +121,7 @@ func (m nvidiaSMISimlinkHook) Hooks() ([]discover.Hook, error) {
} }
link := "/usr/bin/nvidia-smi" link := "/usr/bin/nvidia-smi"
links := []string{fmt.Sprintf("%s::%s", target, link)} links := []string{fmt.Sprintf("%s::%s", target, link)}
symlinkHook := m.hookCreator.Create("create-symlinks", links...) symlinkHook := m.hookCreator.Create(CreateSymlinksHook, links...)
return symlinkHook.Hooks() return symlinkHook.Hooks()
} }

View File

@@ -29,7 +29,7 @@ import (
func TestNvidiaSMISymlinkHook(t *testing.T) { func TestNvidiaSMISymlinkHook(t *testing.T) {
logger, _ := testlog.NewNullLogger() logger, _ := testlog.NewNullLogger()
hookCreator := discover.NewHookCreator("nvidia-cdi-hook", false) hookCreator := discover.NewHookCreator()
errMounts := errors.New("mounts error") errMounts := errors.New("mounts error")
@@ -93,7 +93,7 @@ func TestNvidiaSMISymlinkHook(t *testing.T) {
expectedHooks: []discover.Hook{ expectedHooks: []discover.Hook{
{ {
Lifecycle: "createContainer", Lifecycle: "createContainer",
Path: "nvidia-cdi-hook", Path: "/usr/bin/nvidia-cdi-hook",
Args: []string{"nvidia-cdi-hook", "create-symlinks", Args: []string{"nvidia-cdi-hook", "create-symlinks",
"--link", "nvidia-smi::/usr/bin/nvidia-smi"}, "--link", "nvidia-smi::/usr/bin/nvidia-smi"},
Env: []string{"NVIDIA_CTK_DEBUG=false"}, Env: []string{"NVIDIA_CTK_DEBUG=false"},
@@ -114,7 +114,7 @@ func TestNvidiaSMISymlinkHook(t *testing.T) {
expectedHooks: []discover.Hook{ expectedHooks: []discover.Hook{
{ {
Lifecycle: "createContainer", Lifecycle: "createContainer",
Path: "nvidia-cdi-hook", Path: "/usr/bin/nvidia-cdi-hook",
Args: []string{"nvidia-cdi-hook", "create-symlinks", Args: []string{"nvidia-cdi-hook", "create-symlinks",
"--link", "/some/path/nvidia-smi::/usr/bin/nvidia-smi"}, "--link", "/some/path/nvidia-smi::/usr/bin/nvidia-smi"},
Env: []string{"NVIDIA_CTK_DEBUG=false"}, Env: []string{"NVIDIA_CTK_DEBUG=false"},
@@ -135,7 +135,7 @@ func TestNvidiaSMISymlinkHook(t *testing.T) {
expectedHooks: []discover.Hook{ expectedHooks: []discover.Hook{
{ {
Lifecycle: "createContainer", Lifecycle: "createContainer",
Path: "nvidia-cdi-hook", Path: "/usr/bin/nvidia-cdi-hook",
Args: []string{"nvidia-cdi-hook", "create-symlinks", Args: []string{"nvidia-cdi-hook", "create-symlinks",
"--link", "/some/path/nvidia-smi::/usr/bin/nvidia-smi"}, "--link", "/some/path/nvidia-smi::/usr/bin/nvidia-smi"},
Env: []string{"NVIDIA_CTK_DEBUG=false"}, Env: []string{"NVIDIA_CTK_DEBUG=false"},

View File

@@ -34,7 +34,7 @@ var _ Interface = (*gdslib)(nil)
// GetAllDeviceSpecs returns the device specs for all available devices. // GetAllDeviceSpecs returns the device specs for all available devices.
func (l *gdslib) GetAllDeviceSpecs() ([]specs.Device, error) { func (l *gdslib) GetAllDeviceSpecs() ([]specs.Device, error) {
discoverer, err := discover.NewGDSDiscoverer(l.logger, l.driverRoot, l.devRoot) discoverer, err := discover.NewGDSDiscoverer(l.logger, l.driverRoot)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create GPUDirect Storage discoverer: %v", err) return nil, fmt.Errorf("failed to create GPUDirect Storage discoverer: %v", err)
} }
@@ -58,7 +58,7 @@ func (l *gdslib) GetCommonEdits() (*cdi.ContainerEdits, error) {
// GetSpec is unsppported for the gdslib specs. // GetSpec is unsppported for the gdslib specs.
// gdslib is typically wrapped by a spec that implements GetSpec. // gdslib is typically wrapped by a spec that implements GetSpec.
func (l *gdslib) GetSpec() (spec.Interface, error) { func (l *gdslib) GetSpec(...string) (spec.Interface, error) {
return nil, fmt.Errorf("GetSpec is not supported") return nil, fmt.Errorf("GetSpec is not supported")
} }

View File

@@ -34,7 +34,7 @@ type csvlib nvcdilib
var _ Interface = (*csvlib)(nil) var _ Interface = (*csvlib)(nil)
// GetSpec should not be called for wsllib // GetSpec should not be called for wsllib
func (l *csvlib) GetSpec() (spec.Interface, error) { func (l *csvlib) GetSpec(...string) (spec.Interface, error) {
return nil, fmt.Errorf("unexpected call to csvlib.GetSpec()") return nil, fmt.Errorf("unexpected call to csvlib.GetSpec()")
} }

View File

@@ -41,7 +41,7 @@ const (
) )
// GetSpec should not be called for imexlib. // GetSpec should not be called for imexlib.
func (l *imexlib) GetSpec() (spec.Interface, error) { func (l *imexlib) GetSpec(...string) (spec.Interface, error) {
return nil, fmt.Errorf("unexpected call to imexlib.GetSpec()") return nil, fmt.Errorf("unexpected call to imexlib.GetSpec()")
} }

View File

@@ -36,7 +36,7 @@ type nvmllib nvcdilib
var _ Interface = (*nvmllib)(nil) var _ Interface = (*nvmllib)(nil)
// GetSpec should not be called for nvmllib // GetSpec should not be called for nvmllib
func (l *nvmllib) GetSpec() (spec.Interface, error) { func (l *nvmllib) GetSpec(...string) (spec.Interface, error) {
return nil, fmt.Errorf("unexpected call to nvmllib.GetSpec()") return nil, fmt.Errorf("unexpected call to nvmllib.GetSpec()")
} }

View File

@@ -32,7 +32,7 @@ type wsllib nvcdilib
var _ Interface = (*wsllib)(nil) var _ Interface = (*wsllib)(nil)
// GetSpec should not be called for wsllib // GetSpec should not be called for wsllib
func (l *wsllib) GetSpec() (spec.Interface, error) { func (l *wsllib) GetSpec(...string) (spec.Interface, error) {
return nil, fmt.Errorf("unexpected call to wsllib.GetSpec()") return nil, fmt.Errorf("unexpected call to wsllib.GetSpec()")
} }

View File

@@ -58,16 +58,13 @@ type nvcdilib struct {
featureFlags map[FeatureFlag]bool featureFlags map[FeatureFlag]bool
disabledHooks disabledHooks disabledHooks []discover.HookName
hookCreator discover.HookCreator hookCreator discover.HookCreator
} }
// New creates a new nvcdi library // New creates a new nvcdi library
func New(opts ...Option) (Interface, error) { func New(opts ...Option) (Interface, error) {
l := &nvcdilib{ l := &nvcdilib{}
disabledHooks: make(disabledHooks),
featureFlags: make(map[FeatureFlag]bool),
}
for _, opt := range opts { for _, opt := range opts {
opt(l) opt(l)
} }
@@ -84,9 +81,6 @@ func New(opts ...Option) (Interface, error) {
if l.nvidiaCDIHookPath == "" { if l.nvidiaCDIHookPath == "" {
l.nvidiaCDIHookPath = "/usr/bin/nvidia-cdi-hook" l.nvidiaCDIHookPath = "/usr/bin/nvidia-cdi-hook"
} }
// create hookCreator
l.hookCreator = discover.NewHookCreator(l.nvidiaCDIHookPath, false)
if l.driverRoot == "" { if l.driverRoot == "" {
l.driverRoot = "/" l.driverRoot = "/"
} }
@@ -136,7 +130,7 @@ func New(opts ...Option) (Interface, error) {
l.vendor = "management.nvidia.com" l.vendor = "management.nvidia.com"
} }
// Management containers in general do not require CUDA Forward compatibility. // Management containers in general do not require CUDA Forward compatibility.
l.disabledHooks[HookEnableCudaCompat] = true l.disabledHooks = append(l.disabledHooks, HookEnableCudaCompat, DisableDeviceNodeModificationHook)
lib = (*managementlib)(l) lib = (*managementlib)(l)
case ModeNvml: case ModeNvml:
lib = (*nvmllib)(l) lib = (*nvmllib)(l)
@@ -161,6 +155,12 @@ func New(opts ...Option) (Interface, error) {
return nil, fmt.Errorf("unknown mode %q", l.mode) return nil, fmt.Errorf("unknown mode %q", l.mode)
} }
// create hookCreator
l.hookCreator = discover.NewHookCreator(
discover.WithNVIDIACDIHookPath(l.nvidiaCDIHookPath),
discover.WithDisabledHooks(l.disabledHooks...),
)
w := wrapper{ w := wrapper{
Interface: lib, Interface: lib,
vendor: l.vendor, vendor: l.vendor,

View File

@@ -180,7 +180,7 @@ func (m managementDiscoverer) nodeIsBlocked(path string) bool {
// GetSpec is unsppported for the managementlib specs. // GetSpec is unsppported for the managementlib specs.
// managementlib is typically wrapped by a spec that implements GetSpec. // managementlib is typically wrapped by a spec that implements GetSpec.
func (m *managementlib) GetSpec() (spec.Interface, error) { func (m *managementlib) GetSpec(...string) (spec.Interface, error) {
return nil, fmt.Errorf("GetSpec is not supported") return nil, fmt.Errorf("GetSpec is not supported")
} }

View File

@@ -58,7 +58,7 @@ func (l *mofedlib) GetCommonEdits() (*cdi.ContainerEdits, error) {
// GetSpec is unsppported for the mofedlib specs. // GetSpec is unsppported for the mofedlib specs.
// mofedlib is typically wrapped by a spec that implements GetSpec. // mofedlib is typically wrapped by a spec that implements GetSpec.
func (l *mofedlib) GetSpec() (spec.Interface, error) { func (l *mofedlib) GetSpec(...string) (spec.Interface, error) {
return nil, fmt.Errorf("GetSpec is not supported") return nil, fmt.Errorf("GetSpec is not supported")
} }

View File

@@ -21,6 +21,7 @@ import (
"github.com/NVIDIA/go-nvlib/pkg/nvlib/info" "github.com/NVIDIA/go-nvlib/pkg/nvlib/info"
"github.com/NVIDIA/go-nvml/pkg/nvml" "github.com/NVIDIA/go-nvml/pkg/nvml"
"github.com/NVIDIA/nvidia-container-toolkit/internal/discover"
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger" "github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/transform" "github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi/transform"
) )
@@ -158,12 +159,9 @@ func WithLibrarySearchPaths(paths []string) Option {
// WithDisabledHook allows specific hooks to the disabled. // WithDisabledHook allows specific hooks to the disabled.
// This option can be specified multiple times for each hook. // This option can be specified multiple times for each hook.
func WithDisabledHook(hook HookName) Option { func WithDisabledHook[T string | HookName](hook T) Option {
return func(o *nvcdilib) { return func(o *nvcdilib) {
if o.disabledHooks == nil { o.disabledHooks = append(o.disabledHooks, discover.HookName(hook))
o.disabledHooks = make(map[HookName]bool)
}
o.disabledHooks[hook] = true
} }
} }

View File

@@ -61,18 +61,9 @@ func (d *deviceFolderPermissions) Hooks() ([]discover.Hook, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get device subfolders: %v", err) return nil, fmt.Errorf("failed to get device subfolders: %v", err)
} }
if len(folders) == 0 {
return nil, nil
}
args := []string{"--mode", "755"} //nolint:staticcheck // The ChmodHook is deprecated and will be removed in a future release.
for _, folder := range folders { return d.hookCreator.Create(discover.ChmodHook, folders...).Hooks()
args = append(args, "--path", folder)
}
hook := d.hookCreator.Create("chmod", args...)
return []discover.Hook{*hook}, nil
} }
func (d *deviceFolderPermissions) getDeviceSubfolders() ([]string, error) { func (d *deviceFolderPermissions) getDeviceSubfolders() ([]string, error) {

View File

@@ -35,8 +35,11 @@ type wrapper struct {
} }
// GetSpec combines the device specs and common edits from the wrapped Interface to a single spec.Interface. // GetSpec combines the device specs and common edits from the wrapped Interface to a single spec.Interface.
func (l *wrapper) GetSpec() (spec.Interface, error) { func (l *wrapper) GetSpec(devices ...string) (spec.Interface, error) {
deviceSpecs, err := l.GetAllDeviceSpecs() if len(devices) == 0 {
devices = append(devices, "all")
}
deviceSpecs, err := l.GetDeviceSpecsByID(devices...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -55,6 +58,16 @@ func (l *wrapper) GetSpec() (spec.Interface, error) {
) )
} }
func (l *wrapper) GetDeviceSpecsByID(devices ...string) ([]specs.Device, error) {
for _, device := range devices {
if device != "all" {
continue
}
return l.GetAllDeviceSpecs()
}
return l.Interface.GetDeviceSpecsByID(devices...)
}
// GetAllDeviceSpecs returns the device specs for all available devices. // GetAllDeviceSpecs returns the device specs for all available devices.
func (l *wrapper) GetAllDeviceSpecs() ([]specs.Device, error) { func (l *wrapper) GetAllDeviceSpecs() ([]specs.Device, error) {
return l.Interface.GetAllDeviceSpecs() return l.Interface.GetAllDeviceSpecs()

View File

@@ -20,14 +20,8 @@ LOG_ARTIFACTS_DIR ?= $(CURDIR)/e2e_logs
GINKGO_BIN := $(CURDIR)/bin/ginkgo GINKGO_BIN := $(CURDIR)/bin/ginkgo
# If GINKGO_FOCUS is not set, run all tests
# current available tests:
# - nvidia-container-cli
# - docker
GINKGO_FOCUS ?=
test: $(GINKGO_BIN) test: $(GINKGO_BIN)
$(GINKGO_BIN) $(GINKGO_ARGS) -v --json-report ginkgo.json --focus="$(GINKGO_FOCUS)" ./tests/e2e/... $(GINKGO_BIN) $(GINKGO_ARGS) -v --json-report ginkgo.json ./tests/e2e/...
$(GINKGO_BIN): $(GINKGO_BIN):
mkdir -p $(CURDIR)/bin mkdir -p $(CURDIR)/bin

View File

@@ -28,21 +28,12 @@ var dockerInstallTemplate = `
#! /usr/bin/env bash #! /usr/bin/env bash
set -xe set -xe
# if the TEMP_DIR is already set, use it
if [ -f /tmp/ctk_e2e_temp_dir.txt ]; then
TEMP_DIR=$(cat /tmp/ctk_e2e_temp_dir.txt)
else
TEMP_DIR="/tmp/ctk_e2e.$(date +%s)_$RANDOM"
echo "$TEMP_DIR" > /tmp/ctk_e2e_temp_dir.txt
fi
# if TEMP_DIR does not exist, create it
if [ ! -d "$TEMP_DIR" ]; then
mkdir -p "$TEMP_DIR"
fi
: ${IMAGE:={{.Image}}} : ${IMAGE:={{.Image}}}
# Create a temporary directory
TEMP_DIR="/tmp/ctk_e2e.$(date +%s)_$RANDOM"
mkdir -p "$TEMP_DIR"
# Given that docker has an init function that checks for the existence of the # Given that docker has an init function that checks for the existence of the
# nvidia-container-toolkit, we need to create a symlink to the nvidia-container-runtime-hook # nvidia-container-toolkit, we need to create a symlink to the nvidia-container-runtime-hook
# in the /usr/bin directory. # in the /usr/bin directory.

View File

@@ -1,208 +0,0 @@
/*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package e2e
import (
"context"
"fmt"
"strings"
"text/template"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
const (
dockerDindTemplate = `docker run -d --rm --privileged \
-v {{.SharedDir}}/etc/docker:/etc/docker \
-v {{.SharedDir}}/run/nvidia:/run/nvidia \
-v {{.SharedDir}}/usr/local/nvidia:/usr/local/nvidia \
--name {{.ContainerName}} \
docker:dind -H unix://{{.DockerSocket}}`
dockerToolkitTemplate = `docker run -d --rm --privileged \
--volumes-from {{.DindContainerName}} \
--pid "container:{{.DindContainerName}}" \
-e RUNTIME_ARGS="--socket {{.DockerSocket}}" \
-v {{.TestScriptPath}}:/usr/local/bin/libnvidia-container-cli.sh \
--name {{.ContainerName}} \
{{.ToolkitImage}} /usr/local/bin/libnvidia-container-cli.sh`
dockerDefaultConfigTemplate = `
{
"registry-mirrors": ["https://mirror.gcr.io"]
}`
libnvidiaContainerCliTestTemplate = `#!/usr/bin/env bash
set -euo pipefail
apt-get update -y && apt-get install -y curl gnupg2
WORKDIR="$(mktemp -d)"
ROOTFS="${WORKDIR}/rootfs"
mkdir -p "${ROOTFS}"
export WORKDIR ROOTFS # make them visible in the child shell
unshare --mount --pid --fork --propagation private -- bash -eux <<'IN_NS'
: "${ROOTFS:?}" "${WORKDIR:?}" # abort if either is empty
# 1 Populate minimal Ubuntu base
curl -L http://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/ubuntu-base-22.04-base-amd64.tar.gz \
| tar -C "$ROOTFS" -xz
# 2 Add non-root user
useradd -R "$ROOTFS" -U -u 1000 -s /bin/bash nvidia
# 3 Bind-mount new root and unshare mounts
mount --bind "$ROOTFS" "$ROOTFS"
mount --make-private "$ROOTFS"
cd "$ROOTFS"
# 4 Minimal virtual filesystems
mount -t proc proc proc
mount -t sysfs sys sys
mount -t tmpfs tmp tmp
mount -t tmpfs run run
# 5 GPU setup
nvidia-container-cli --load-kmods --debug=container-cli.log \
configure --ldconfig=@/sbin/ldconfig.real \
--no-cgroups --utility --device=0 "$(pwd)"
# 6 Switch root
mkdir -p mnt
pivot_root . mnt
umount -l /mnt
exec nvidia-smi -L
IN_NS
`
)
// Integration tests for Docker runtime
var _ = Describe("nvidia-container-cli", Ordered, ContinueOnFailure, func() {
var runner Runner
var sharedDir string
var dindContainerName string
var toolkitContainerName string
var dockerSocket string
var hostOutput string
// Install the NVIDIA Container Toolkit
BeforeAll(func(ctx context.Context) {
runner = NewRunner(
WithHost(sshHost),
WithPort(sshPort),
WithSshKey(sshKey),
WithSshUser(sshUser),
)
// Setup shared directory and container names
sharedDir = "/tmp/nvidia-container-toolkit-test"
dindContainerName = "nvidia-container-toolkit-dind"
toolkitContainerName = "nvidia-container-toolkit-test"
dockerSocket = "/run/nvidia/docker.sock"
// Get host nvidia-smi output
var err error
hostOutput, _, err = runner.Run("nvidia-smi -L")
Expect(err).ToNot(HaveOccurred())
// Pull ubuntu image
_, _, err = runner.Run("docker pull ubuntu")
Expect(err).ToNot(HaveOccurred())
// Create shared directory structure
_, _, err = runner.Run(fmt.Sprintf("mkdir -p %s/{etc/docker,run/nvidia,usr/local/nvidia}", sharedDir))
Expect(err).ToNot(HaveOccurred())
// Copy docker default config
createDockerConfigCmd := fmt.Sprintf("cat > %s/etc/docker/daemon.json <<'EOF'\n%s\nEOF",
sharedDir, dockerDefaultConfigTemplate)
_, _, err = runner.Run(createDockerConfigCmd)
Expect(err).ToNot(HaveOccurred())
// Start Docker-in-Docker container
tmpl, err := template.New("dockerDind").Parse(dockerDindTemplate)
Expect(err).ToNot(HaveOccurred())
var dindCmdBuilder strings.Builder
err = tmpl.Execute(&dindCmdBuilder, map[string]string{
"SharedDir": sharedDir,
"ContainerName": dindContainerName,
"DockerSocket": dockerSocket,
})
Expect(err).ToNot(HaveOccurred())
_, _, err = runner.Run(dindCmdBuilder.String())
Expect(err).ToNot(HaveOccurred())
})
AfterAll(func(ctx context.Context) {
// Cleanup containers
runner.Run(fmt.Sprintf("docker rm -f %s", toolkitContainerName))
runner.Run(fmt.Sprintf("docker rm -f %s", dindContainerName))
// Cleanup shared directory
_, _, err := runner.Run(fmt.Sprintf("rm -rf %s", sharedDir))
Expect(err).ToNot(HaveOccurred())
})
When("running nvidia-smi -L", Ordered, func() {
It("should support NVIDIA_VISIBLE_DEVICES and NVIDIA_DRIVER_CAPABILITIES", func(ctx context.Context) {
// 1. Create the test script
testScriptPath := fmt.Sprintf("%s/libnvidia-container-cli.sh", sharedDir)
createScriptCmd := fmt.Sprintf("cat > %s <<'EOF'\n%s\nEOF\nchmod +x %s",
testScriptPath, libnvidiaContainerCliTestTemplate, testScriptPath)
_, _, err := runner.Run(createScriptCmd)
Expect(err).ToNot(HaveOccurred())
// 2. Start the toolkit container
tmpl, err := template.New("dockerToolkit").Parse(dockerToolkitTemplate)
Expect(err).ToNot(HaveOccurred())
var toolkitCmdBuilder strings.Builder
err = tmpl.Execute(&toolkitCmdBuilder, map[string]string{
"DindContainerName": dindContainerName,
"ContainerName": toolkitContainerName,
"DockerSocket": dockerSocket,
"TestScriptPath": testScriptPath,
"ToolkitImage": imageName + ":" + imageTag,
})
Expect(err).ToNot(HaveOccurred())
_, _, err = runner.Run(toolkitCmdBuilder.String())
Expect(err).ToNot(HaveOccurred())
// 3. Wait for and verify the output
expected := strings.TrimSpace(strings.ReplaceAll(hostOutput, "\r", ""))
Eventually(func() string {
logs, _, err := runner.Run(fmt.Sprintf("docker logs %s | tail -n 20", toolkitContainerName))
if err != nil {
return ""
}
logLines := strings.Split(strings.TrimSpace(logs), "\n")
if len(logLines) == 0 {
return ""
}
return strings.TrimSpace(strings.ReplaceAll(logLines[len(logLines)-1], "\r", ""))
}, "5m", "5s").Should(Equal(expected))
})
})
})

View File

@@ -216,4 +216,23 @@ var _ = Describe("docker", Ordered, ContinueOnFailure, func() {
Expect(ldconfigOut).To(ContainSubstring("/usr/lib64")) Expect(ldconfigOut).To(ContainSubstring("/usr/lib64"))
}) })
}) })
Describe("Disabling device node creation", Ordered, func() {
BeforeAll(func(ctx context.Context) {
_, _, err := runner.Run("docker pull ubuntu")
Expect(err).ToNot(HaveOccurred())
})
It("should work with nvidia-container-runtime-hook", func(ctx context.Context) {
output, _, err := runner.Run("docker run --rm -i --runtime=runc --gpus=all ubuntu bash -c \"grep ModifyDeviceFiles: /proc/driver/nvidia/params\"")
Expect(err).ToNot(HaveOccurred())
Expect(output).To(Equal("ModifyDeviceFiles: 0\n"))
})
It("should work with automatic CDI spec generation", func(ctx context.Context) {
output, _, err := runner.Run("docker run --rm -i --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=runtime.nvidia.com/gpu=all ubuntu bash -c \"grep ModifyDeviceFiles: /proc/driver/nvidia/params\"")
Expect(err).ToNot(HaveOccurred())
Expect(output).To(Equal("ModifyDeviceFiles: 0\n"))
})
})
}) })

View File

@@ -7,7 +7,7 @@ toolchain go1.24.1
require ( require (
github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/ginkgo/v2 v2.23.4
github.com/onsi/gomega v1.37.0 github.com/onsi/gomega v1.37.0
golang.org/x/crypto v0.38.0 golang.org/x/crypto v0.39.0
) )
require ( require (
@@ -16,9 +16,9 @@ require (
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect
golang.org/x/net v0.38.0 // indirect golang.org/x/net v0.40.0 // indirect
golang.org/x/sys v0.33.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect golang.org/x/text v0.26.0 // indirect
golang.org/x/tools v0.31.0 // indirect golang.org/x/tools v0.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View File

@@ -24,18 +24,18 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -1 +0,0 @@
{"ociVersion":"1.0.1-dev","process":{"terminal":true,"user":{"uid":0,"gid":0},"args":["sh"],"env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","TERM=xterm"],"cwd":"/","capabilities":{"bounding":["CAP_AUDIT_WRITE","CAP_KILL","CAP_NET_BIND_SERVICE"],"effective":["CAP_AUDIT_WRITE","CAP_KILL","CAP_NET_BIND_SERVICE"],"inheritable":["CAP_AUDIT_WRITE","CAP_KILL","CAP_NET_BIND_SERVICE"],"permitted":["CAP_AUDIT_WRITE","CAP_KILL","CAP_NET_BIND_SERVICE"],"ambient":["CAP_AUDIT_WRITE","CAP_KILL","CAP_NET_BIND_SERVICE"]},"rlimits":[{"type":"RLIMIT_NOFILE","hard":1024,"soft":1024}],"noNewPrivileges":true},"root":{"path":"rootfs","readonly":true},"hostname":"runc","mounts":[{"destination":"/proc","type":"proc","source":"proc"},{"destination":"/dev","type":"tmpfs","source":"tmpfs","options":["nosuid","strictatime","mode=755","size=65536k"]},{"destination":"/dev/pts","type":"devpts","source":"devpts","options":["nosuid","noexec","newinstance","ptmxmode=0666","mode=0620","gid=5"]},{"destination":"/dev/shm","type":"tmpfs","source":"shm","options":["nosuid","noexec","nodev","mode=1777","size=65536k"]},{"destination":"/dev/mqueue","type":"mqueue","source":"mqueue","options":["nosuid","noexec","nodev"]},{"destination":"/sys","type":"sysfs","source":"sysfs","options":["nosuid","noexec","nodev","ro"]},{"destination":"/sys/fs/cgroup","type":"cgroup","source":"cgroup","options":["nosuid","noexec","nodev","relatime","ro"]}],"hooks":{"prestart":[{"path":"nvidia-container-runtime-hook","args":["nvidia-container-runtime-hook","prestart"]}]},"linux":{"resources":{"devices":[{"allow":false,"access":"rwm"}]},"namespaces":[{"type":"pid"},{"type":"network"},{"type":"ipc"},{"type":"uts"},{"type":"mount"}],"maskedPaths":["/proc/kcore","/proc/latency_stats","/proc/timer_list","/proc/timer_stats","/proc/sched_debug","/sys/firmware","/proc/scsi"],"readonlyPaths":["/proc/asound","/proc/bus","/proc/fs","/proc/irq","/proc/sys","/proc/sysrq-trigger"]}}

View File

@@ -20,14 +20,19 @@ import (
// returned by MultiAlgorithmSigner and don't appear in the Signature.Format // returned by MultiAlgorithmSigner and don't appear in the Signature.Format
// field. // field.
const ( const (
CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" // Deprecated: DSA is only supported at insecure key sizes, and was removed
CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" // from major implementations.
CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" CertAlgoDSAv01 = InsecureCertAlgoDSAv01
CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" // Deprecated: DSA is only supported at insecure key sizes, and was removed
CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" // from major implementations.
CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" InsecureCertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com" CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
// CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a // CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a
// Certificate.Type (or PublicKey.Type), but only in // Certificate.Type (or PublicKey.Type), but only in
@@ -485,16 +490,16 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
// //
// This map must be kept in sync with the one in agent/client.go. // This map must be kept in sync with the one in agent/client.go.
var certKeyAlgoNames = map[string]string{ var certKeyAlgoNames = map[string]string{
CertAlgoRSAv01: KeyAlgoRSA, CertAlgoRSAv01: KeyAlgoRSA,
CertAlgoRSASHA256v01: KeyAlgoRSASHA256, CertAlgoRSASHA256v01: KeyAlgoRSASHA256,
CertAlgoRSASHA512v01: KeyAlgoRSASHA512, CertAlgoRSASHA512v01: KeyAlgoRSASHA512,
CertAlgoDSAv01: KeyAlgoDSA, InsecureCertAlgoDSAv01: InsecureKeyAlgoDSA,
CertAlgoECDSA256v01: KeyAlgoECDSA256, CertAlgoECDSA256v01: KeyAlgoECDSA256,
CertAlgoECDSA384v01: KeyAlgoECDSA384, CertAlgoECDSA384v01: KeyAlgoECDSA384,
CertAlgoECDSA521v01: KeyAlgoECDSA521, CertAlgoECDSA521v01: KeyAlgoECDSA521,
CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256,
CertAlgoED25519v01: KeyAlgoED25519, CertAlgoED25519v01: KeyAlgoED25519,
CertAlgoSKED25519v01: KeyAlgoSKED25519, CertAlgoSKED25519v01: KeyAlgoSKED25519,
} }
// underlyingAlgo returns the signature algorithm associated with algo (which is // underlyingAlgo returns the signature algorithm associated with algo (which is

View File

@@ -58,11 +58,11 @@ func newRC4(key, iv []byte) (cipher.Stream, error) {
type cipherMode struct { type cipherMode struct {
keySize int keySize int
ivSize int ivSize int
create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) create func(key, iv []byte, macKey []byte, algs DirectionAlgorithms) (packetCipher, error)
} }
func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) { func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) {
return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { return func(key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) {
stream, err := createFunc(key, iv) stream, err := createFunc(key, iv)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -98,36 +98,36 @@ func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream,
var cipherModes = map[string]*cipherMode{ var cipherModes = map[string]*cipherMode{
// Ciphers from RFC 4344, which introduced many CTR-based ciphers. Algorithms // Ciphers from RFC 4344, which introduced many CTR-based ciphers. Algorithms
// are defined in the order specified in the RFC. // are defined in the order specified in the RFC.
"aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)}, CipherAES128CTR: {16, aes.BlockSize, streamCipherMode(0, newAESCTR)},
"aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)}, CipherAES192CTR: {24, aes.BlockSize, streamCipherMode(0, newAESCTR)},
"aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)}, CipherAES256CTR: {32, aes.BlockSize, streamCipherMode(0, newAESCTR)},
// Ciphers from RFC 4345, which introduces security-improved arcfour ciphers. // Ciphers from RFC 4345, which introduces security-improved arcfour ciphers.
// They are defined in the order specified in the RFC. // They are defined in the order specified in the RFC.
"arcfour128": {16, 0, streamCipherMode(1536, newRC4)}, InsecureCipherRC4128: {16, 0, streamCipherMode(1536, newRC4)},
"arcfour256": {32, 0, streamCipherMode(1536, newRC4)}, InsecureCipherRC4256: {32, 0, streamCipherMode(1536, newRC4)},
// Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
// Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
// RC4) has problems with weak keys, and should be used with caution." // RC4) has problems with weak keys, and should be used with caution."
// RFC 4345 introduces improved versions of Arcfour. // RFC 4345 introduces improved versions of Arcfour.
"arcfour": {16, 0, streamCipherMode(0, newRC4)}, InsecureCipherRC4: {16, 0, streamCipherMode(0, newRC4)},
// AEAD ciphers // AEAD ciphers
gcm128CipherID: {16, 12, newGCMCipher}, CipherAES128GCM: {16, 12, newGCMCipher},
gcm256CipherID: {32, 12, newGCMCipher}, CipherAES256GCM: {32, 12, newGCMCipher},
chacha20Poly1305ID: {64, 0, newChaCha20Cipher}, CipherChaCha20Poly1305: {64, 0, newChaCha20Cipher},
// CBC mode is insecure and so is not included in the default config. // CBC mode is insecure and so is not included in the default config.
// (See https://www.ieee-security.org/TC/SP2013/papers/4977a526.pdf). If absolutely // (See https://www.ieee-security.org/TC/SP2013/papers/4977a526.pdf). If absolutely
// needed, it's possible to specify a custom Config to enable it. // needed, it's possible to specify a custom Config to enable it.
// You should expect that an active attacker can recover plaintext if // You should expect that an active attacker can recover plaintext if
// you do. // you do.
aes128cbcID: {16, aes.BlockSize, newAESCBCCipher}, InsecureCipherAES128CBC: {16, aes.BlockSize, newAESCBCCipher},
// 3des-cbc is insecure and is not included in the default // 3des-cbc is insecure and is not included in the default
// config. // config.
tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher}, InsecureCipherTripleDESCBC: {24, des.BlockSize, newTripleDESCBCCipher},
} }
// prefixLen is the length of the packet prefix that contains the packet length // prefixLen is the length of the packet prefix that contains the packet length
@@ -307,7 +307,7 @@ type gcmCipher struct {
buf []byte buf []byte
} }
func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs DirectionAlgorithms) (packetCipher, error) {
c, err := aes.NewCipher(key) c, err := aes.NewCipher(key)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -429,7 +429,7 @@ type cbcCipher struct {
oracleCamouflage uint32 oracleCamouflage uint32
} }
func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) {
cbc := &cbcCipher{ cbc := &cbcCipher{
mac: macModes[algs.MAC].new(macKey), mac: macModes[algs.MAC].new(macKey),
decrypter: cipher.NewCBCDecrypter(c, iv), decrypter: cipher.NewCBCDecrypter(c, iv),
@@ -443,7 +443,7 @@ func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorith
return cbc, nil return cbc, nil
} }
func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { func newAESCBCCipher(key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) {
c, err := aes.NewCipher(key) c, err := aes.NewCipher(key)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -457,7 +457,7 @@ func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCi
return cbc, nil return cbc, nil
} }
func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { func newTripleDESCBCCipher(key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) {
c, err := des.NewTripleDESCipher(key) c, err := des.NewTripleDESCipher(key)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -635,8 +635,6 @@ func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader
return nil return nil
} }
const chacha20Poly1305ID = "chacha20-poly1305@openssh.com"
// chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com // chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com
// AEAD, which is described here: // AEAD, which is described here:
// //
@@ -650,7 +648,7 @@ type chacha20Poly1305Cipher struct {
buf []byte buf []byte
} }
func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs DirectionAlgorithms) (packetCipher, error) {
if len(key) != 64 { if len(key) != 64 {
panic(len(key)) panic(len(key))
} }

View File

@@ -110,6 +110,7 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e
} }
c.sessionID = c.transport.getSessionID() c.sessionID = c.transport.getSessionID()
c.algorithms = c.transport.getAlgorithms()
return c.clientAuthenticate(config) return c.clientAuthenticate(config)
} }

View File

@@ -10,6 +10,7 @@ import (
"fmt" "fmt"
"io" "io"
"math" "math"
"slices"
"sync" "sync"
_ "crypto/sha1" _ "crypto/sha1"
@@ -24,69 +25,258 @@ const (
serviceSSH = "ssh-connection" serviceSSH = "ssh-connection"
) )
// supportedCiphers lists ciphers we support but might not recommend. // The ciphers currently or previously implemented by this library, to use in
var supportedCiphers = []string{ // [Config.Ciphers]. For a list, see the [Algorithms.Ciphers] returned by
"aes128-ctr", "aes192-ctr", "aes256-ctr", // [SupportedAlgorithms] or [InsecureAlgorithms].
"aes128-gcm@openssh.com", gcm256CipherID, const (
chacha20Poly1305ID, CipherAES128GCM = "aes128-gcm@openssh.com"
"arcfour256", "arcfour128", "arcfour", CipherAES256GCM = "aes256-gcm@openssh.com"
aes128cbcID, CipherChaCha20Poly1305 = "chacha20-poly1305@openssh.com"
tripledescbcID, CipherAES128CTR = "aes128-ctr"
CipherAES192CTR = "aes192-ctr"
CipherAES256CTR = "aes256-ctr"
InsecureCipherAES128CBC = "aes128-cbc"
InsecureCipherTripleDESCBC = "3des-cbc"
InsecureCipherRC4 = "arcfour"
InsecureCipherRC4128 = "arcfour128"
InsecureCipherRC4256 = "arcfour256"
)
// The key exchanges currently or previously implemented by this library, to use
// in [Config.KeyExchanges]. For a list, see the
// [Algorithms.KeyExchanges] returned by [SupportedAlgorithms] or
// [InsecureAlgorithms].
const (
InsecureKeyExchangeDH1SHA1 = "diffie-hellman-group1-sha1"
InsecureKeyExchangeDH14SHA1 = "diffie-hellman-group14-sha1"
KeyExchangeDH14SHA256 = "diffie-hellman-group14-sha256"
KeyExchangeDH16SHA512 = "diffie-hellman-group16-sha512"
KeyExchangeECDHP256 = "ecdh-sha2-nistp256"
KeyExchangeECDHP384 = "ecdh-sha2-nistp384"
KeyExchangeECDHP521 = "ecdh-sha2-nistp521"
KeyExchangeCurve25519 = "curve25519-sha256"
InsecureKeyExchangeDHGEXSHA1 = "diffie-hellman-group-exchange-sha1"
KeyExchangeDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
// KeyExchangeMLKEM768X25519 is supported from Go 1.24.
KeyExchangeMLKEM768X25519 = "mlkem768x25519-sha256"
// An alias for KeyExchangeCurve25519SHA256. This kex ID will be added if
// KeyExchangeCurve25519SHA256 is requested for backward compatibility with
// OpenSSH versions up to 7.2.
keyExchangeCurve25519LibSSH = "curve25519-sha256@libssh.org"
)
// The message authentication code (MAC) currently or previously implemented by
// this library, to use in [Config.MACs]. For a list, see the
// [Algorithms.MACs] returned by [SupportedAlgorithms] or
// [InsecureAlgorithms].
const (
HMACSHA256ETM = "hmac-sha2-256-etm@openssh.com"
HMACSHA512ETM = "hmac-sha2-512-etm@openssh.com"
HMACSHA256 = "hmac-sha2-256"
HMACSHA512 = "hmac-sha2-512"
HMACSHA1 = "hmac-sha1"
InsecureHMACSHA196 = "hmac-sha1-96"
)
var (
// supportedKexAlgos specifies key-exchange algorithms implemented by this
// package in preference order, excluding those with security issues.
supportedKexAlgos = []string{
KeyExchangeCurve25519,
KeyExchangeECDHP256,
KeyExchangeECDHP384,
KeyExchangeECDHP521,
KeyExchangeDH14SHA256,
KeyExchangeDH16SHA512,
KeyExchangeDHGEXSHA256,
}
// defaultKexAlgos specifies the default preference for key-exchange
// algorithms in preference order.
defaultKexAlgos = []string{
KeyExchangeCurve25519,
KeyExchangeECDHP256,
KeyExchangeECDHP384,
KeyExchangeECDHP521,
KeyExchangeDH14SHA256,
InsecureKeyExchangeDH14SHA1,
}
// insecureKexAlgos specifies key-exchange algorithms implemented by this
// package and which have security issues.
insecureKexAlgos = []string{
InsecureKeyExchangeDH14SHA1,
InsecureKeyExchangeDH1SHA1,
InsecureKeyExchangeDHGEXSHA1,
}
// supportedCiphers specifies cipher algorithms implemented by this package
// in preference order, excluding those with security issues.
supportedCiphers = []string{
CipherAES128GCM,
CipherAES256GCM,
CipherChaCha20Poly1305,
CipherAES128CTR,
CipherAES192CTR,
CipherAES256CTR,
}
// defaultCiphers specifies the default preference for ciphers algorithms
// in preference order.
defaultCiphers = supportedCiphers
// insecureCiphers specifies cipher algorithms implemented by this
// package and which have security issues.
insecureCiphers = []string{
InsecureCipherAES128CBC,
InsecureCipherTripleDESCBC,
InsecureCipherRC4256,
InsecureCipherRC4128,
InsecureCipherRC4,
}
// supportedMACs specifies MAC algorithms implemented by this package in
// preference order, excluding those with security issues.
supportedMACs = []string{
HMACSHA256ETM,
HMACSHA512ETM,
HMACSHA256,
HMACSHA512,
HMACSHA1,
}
// defaultMACs specifies the default preference for MAC algorithms in
// preference order.
defaultMACs = []string{
HMACSHA256ETM,
HMACSHA512ETM,
HMACSHA256,
HMACSHA512,
HMACSHA1,
InsecureHMACSHA196,
}
// insecureMACs specifies MAC algorithms implemented by this
// package and which have security issues.
insecureMACs = []string{
InsecureHMACSHA196,
}
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e.
// methods of authenticating servers) implemented by this package in
// preference order, excluding those with security issues.
supportedHostKeyAlgos = []string{
CertAlgoRSASHA256v01,
CertAlgoRSASHA512v01,
CertAlgoECDSA256v01,
CertAlgoECDSA384v01,
CertAlgoECDSA521v01,
CertAlgoED25519v01,
KeyAlgoRSASHA256,
KeyAlgoRSASHA512,
KeyAlgoECDSA256,
KeyAlgoECDSA384,
KeyAlgoECDSA521,
KeyAlgoED25519,
}
// defaultHostKeyAlgos specifies the default preference for host-key
// algorithms in preference order.
defaultHostKeyAlgos = []string{
CertAlgoRSASHA256v01,
CertAlgoRSASHA512v01,
CertAlgoRSAv01,
InsecureCertAlgoDSAv01,
CertAlgoECDSA256v01,
CertAlgoECDSA384v01,
CertAlgoECDSA521v01,
CertAlgoED25519v01,
KeyAlgoECDSA256,
KeyAlgoECDSA384,
KeyAlgoECDSA521,
KeyAlgoRSASHA256,
KeyAlgoRSASHA512,
KeyAlgoRSA,
InsecureKeyAlgoDSA,
KeyAlgoED25519,
}
// insecureHostKeyAlgos specifies host-key algorithms implemented by this
// package and which have security issues.
insecureHostKeyAlgos = []string{
KeyAlgoRSA,
InsecureKeyAlgoDSA,
CertAlgoRSAv01,
InsecureCertAlgoDSAv01,
}
// supportedPubKeyAuthAlgos specifies the supported client public key
// authentication algorithms. Note that this doesn't include certificate
// types since those use the underlying algorithm. Order is irrelevant.
supportedPubKeyAuthAlgos = []string{
KeyAlgoED25519,
KeyAlgoSKED25519,
KeyAlgoSKECDSA256,
KeyAlgoECDSA256,
KeyAlgoECDSA384,
KeyAlgoECDSA521,
KeyAlgoRSASHA256,
KeyAlgoRSASHA512,
}
// defaultPubKeyAuthAlgos specifies the preferred client public key
// authentication algorithms. This list is sent to the client if it supports
// the server-sig-algs extension. Order is irrelevant.
defaultPubKeyAuthAlgos = []string{
KeyAlgoED25519,
KeyAlgoSKED25519,
KeyAlgoSKECDSA256,
KeyAlgoECDSA256,
KeyAlgoECDSA384,
KeyAlgoECDSA521,
KeyAlgoRSASHA256,
KeyAlgoRSASHA512,
KeyAlgoRSA,
InsecureKeyAlgoDSA,
}
// insecurePubKeyAuthAlgos specifies client public key authentication
// algorithms implemented by this package and which have security issues.
insecurePubKeyAuthAlgos = []string{
KeyAlgoRSA,
InsecureKeyAlgoDSA,
}
)
// NegotiatedAlgorithms defines algorithms negotiated between client and server.
type NegotiatedAlgorithms struct {
KeyExchange string
HostKey string
Read DirectionAlgorithms
Write DirectionAlgorithms
} }
// preferredCiphers specifies the default preference for ciphers. // Algorithms defines a set of algorithms that can be configured in the client
var preferredCiphers = []string{ // or server config for negotiation during a handshake.
"aes128-gcm@openssh.com", gcm256CipherID, type Algorithms struct {
chacha20Poly1305ID, KeyExchanges []string
"aes128-ctr", "aes192-ctr", "aes256-ctr", Ciphers []string
MACs []string
HostKeys []string
PublicKeyAuths []string
} }
// supportedKexAlgos specifies the supported key-exchange algorithms in // SupportedAlgorithms returns algorithms currently implemented by this package,
// preference order. // excluding those with security issues, which are returned by
var supportedKexAlgos = []string{ // InsecureAlgorithms. The algorithms listed here are in preference order.
kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH, func SupportedAlgorithms() Algorithms {
// P384 and P521 are not constant-time yet, but since we don't return Algorithms{
// reuse ephemeral keys, using them for ECDH should be OK. Ciphers: slices.Clone(supportedCiphers),
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, MACs: slices.Clone(supportedMACs),
kexAlgoDH14SHA256, kexAlgoDH16SHA512, kexAlgoDH14SHA1, KeyExchanges: slices.Clone(supportedKexAlgos),
kexAlgoDH1SHA1, HostKeys: slices.Clone(supportedHostKeyAlgos),
PublicKeyAuths: slices.Clone(supportedPubKeyAuthAlgos),
}
} }
// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden // InsecureAlgorithms returns algorithms currently implemented by this package
// for the server half. // and which have security issues.
var serverForbiddenKexAlgos = map[string]struct{}{ func InsecureAlgorithms() Algorithms {
kexAlgoDHGEXSHA1: {}, // server half implementation is only minimal to satisfy the automated tests return Algorithms{
kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests KeyExchanges: slices.Clone(insecureKexAlgos),
} Ciphers: slices.Clone(insecureCiphers),
MACs: slices.Clone(insecureMACs),
// preferredKexAlgos specifies the default preference for key-exchange HostKeys: slices.Clone(insecureHostKeyAlgos),
// algorithms in preference order. The diffie-hellman-group16-sha512 algorithm PublicKeyAuths: slices.Clone(insecurePubKeyAuthAlgos),
// is disabled by default because it is a bit slower than the others. }
var preferredKexAlgos = []string{
kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH,
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
kexAlgoDH14SHA256, kexAlgoDH14SHA1,
}
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
// of authenticating servers) in preference order.
var supportedHostKeyAlgos = []string{
CertAlgoRSASHA256v01, CertAlgoRSASHA512v01,
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
KeyAlgoRSASHA256, KeyAlgoRSASHA512,
KeyAlgoRSA, KeyAlgoDSA,
KeyAlgoED25519,
}
// supportedMACs specifies a default set of MAC algorithms in preference order.
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
// because they have reached the end of their useful life.
var supportedMACs = []string{
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "hmac-sha2-256", "hmac-sha2-512", "hmac-sha1", "hmac-sha1-96",
} }
var supportedCompressions = []string{compressionNone} var supportedCompressions = []string{compressionNone}
@@ -94,13 +284,13 @@ var supportedCompressions = []string{compressionNone}
// hashFuncs keeps the mapping of supported signature algorithms to their // hashFuncs keeps the mapping of supported signature algorithms to their
// respective hashes needed for signing and verification. // respective hashes needed for signing and verification.
var hashFuncs = map[string]crypto.Hash{ var hashFuncs = map[string]crypto.Hash{
KeyAlgoRSA: crypto.SHA1, KeyAlgoRSA: crypto.SHA1,
KeyAlgoRSASHA256: crypto.SHA256, KeyAlgoRSASHA256: crypto.SHA256,
KeyAlgoRSASHA512: crypto.SHA512, KeyAlgoRSASHA512: crypto.SHA512,
KeyAlgoDSA: crypto.SHA1, InsecureKeyAlgoDSA: crypto.SHA1,
KeyAlgoECDSA256: crypto.SHA256, KeyAlgoECDSA256: crypto.SHA256,
KeyAlgoECDSA384: crypto.SHA384, KeyAlgoECDSA384: crypto.SHA384,
KeyAlgoECDSA521: crypto.SHA512, KeyAlgoECDSA521: crypto.SHA512,
// KeyAlgoED25519 doesn't pre-hash. // KeyAlgoED25519 doesn't pre-hash.
KeyAlgoSKECDSA256: crypto.SHA256, KeyAlgoSKECDSA256: crypto.SHA256,
KeyAlgoSKED25519: crypto.SHA256, KeyAlgoSKED25519: crypto.SHA256,
@@ -135,18 +325,6 @@ func isRSACert(algo string) bool {
return isRSA(algo) return isRSA(algo)
} }
// supportedPubKeyAuthAlgos specifies the supported client public key
// authentication algorithms. Note that this doesn't include certificate types
// since those use the underlying algorithm. This list is sent to the client if
// it supports the server-sig-algs extension. Order is irrelevant.
var supportedPubKeyAuthAlgos = []string{
KeyAlgoED25519,
KeyAlgoSKED25519, KeyAlgoSKECDSA256,
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA,
KeyAlgoDSA,
}
// unexpectedMessageError results when the SSH message that we received didn't // unexpectedMessageError results when the SSH message that we received didn't
// match what we wanted. // match what we wanted.
func unexpectedMessageError(expected, got uint8) error { func unexpectedMessageError(expected, got uint8) error {
@@ -169,20 +347,21 @@ func findCommon(what string, client []string, server []string) (common string, e
return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server)
} }
// directionAlgorithms records algorithm choices in one direction (either read or write) // DirectionAlgorithms defines the algorithms negotiated in one direction
type directionAlgorithms struct { // (either read or write).
type DirectionAlgorithms struct {
Cipher string Cipher string
MAC string MAC string
Compression string compression string
} }
// rekeyBytes returns a rekeying intervals in bytes. // rekeyBytes returns a rekeying intervals in bytes.
func (a *directionAlgorithms) rekeyBytes() int64 { func (a *DirectionAlgorithms) rekeyBytes() int64 {
// According to RFC 4344 block ciphers should rekey after // According to RFC 4344 block ciphers should rekey after
// 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
// 128. // 128.
switch a.Cipher { switch a.Cipher {
case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcm128CipherID, gcm256CipherID, aes128cbcID: case CipherAES128CTR, CipherAES192CTR, CipherAES256CTR, CipherAES128GCM, CipherAES256GCM, InsecureCipherAES128CBC:
return 16 * (1 << 32) return 16 * (1 << 32)
} }
@@ -192,32 +371,25 @@ func (a *directionAlgorithms) rekeyBytes() int64 {
} }
var aeadCiphers = map[string]bool{ var aeadCiphers = map[string]bool{
gcm128CipherID: true, CipherAES128GCM: true,
gcm256CipherID: true, CipherAES256GCM: true,
chacha20Poly1305ID: true, CipherChaCha20Poly1305: true,
} }
type algorithms struct { func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *NegotiatedAlgorithms, err error) {
kex string result := &NegotiatedAlgorithms{}
hostKey string
w directionAlgorithms
r directionAlgorithms
}
func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { result.KeyExchange, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos)
result := &algorithms{}
result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos)
if err != nil { if err != nil {
return return
} }
result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) result.HostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
if err != nil { if err != nil {
return return
} }
stoc, ctos := &result.w, &result.r stoc, ctos := &result.Write, &result.Read
if isClient { if isClient {
ctos, stoc = stoc, ctos ctos, stoc = stoc, ctos
} }
@@ -246,12 +418,12 @@ func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMs
} }
} }
ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) ctos.compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
if err != nil { if err != nil {
return return
} }
stoc.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) stoc.compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
if err != nil { if err != nil {
return return
} }
@@ -297,7 +469,7 @@ func (c *Config) SetDefaults() {
c.Rand = rand.Reader c.Rand = rand.Reader
} }
if c.Ciphers == nil { if c.Ciphers == nil {
c.Ciphers = preferredCiphers c.Ciphers = defaultCiphers
} }
var ciphers []string var ciphers []string
for _, c := range c.Ciphers { for _, c := range c.Ciphers {
@@ -309,19 +481,22 @@ func (c *Config) SetDefaults() {
c.Ciphers = ciphers c.Ciphers = ciphers
if c.KeyExchanges == nil { if c.KeyExchanges == nil {
c.KeyExchanges = preferredKexAlgos c.KeyExchanges = defaultKexAlgos
} }
var kexs []string var kexs []string
for _, k := range c.KeyExchanges { for _, k := range c.KeyExchanges {
if kexAlgoMap[k] != nil { if kexAlgoMap[k] != nil {
// Ignore the KEX if we have no kexAlgoMap definition. // Ignore the KEX if we have no kexAlgoMap definition.
kexs = append(kexs, k) kexs = append(kexs, k)
if k == KeyExchangeCurve25519 && !contains(c.KeyExchanges, keyExchangeCurve25519LibSSH) {
kexs = append(kexs, keyExchangeCurve25519LibSSH)
}
} }
} }
c.KeyExchanges = kexs c.KeyExchanges = kexs
if c.MACs == nil { if c.MACs == nil {
c.MACs = supportedMACs c.MACs = defaultMACs
} }
var macs []string var macs []string
for _, m := range c.MACs { for _, m := range c.MACs {

View File

@@ -74,6 +74,13 @@ type Conn interface {
// Disconnect // Disconnect
} }
// AlgorithmsConnMetadata is a ConnMetadata that can return the algorithms
// negotiated between client and server.
type AlgorithmsConnMetadata interface {
ConnMetadata
Algorithms() NegotiatedAlgorithms
}
// DiscardRequests consumes and rejects all requests from the // DiscardRequests consumes and rejects all requests from the
// passed-in channel. // passed-in channel.
func DiscardRequests(in <-chan *Request) { func DiscardRequests(in <-chan *Request) {
@@ -106,6 +113,7 @@ type sshConn struct {
sessionID []byte sessionID []byte
clientVersion []byte clientVersion []byte
serverVersion []byte serverVersion []byte
algorithms NegotiatedAlgorithms
} }
func dup(src []byte) []byte { func dup(src []byte) []byte {
@@ -141,3 +149,7 @@ func (c *sshConn) ClientVersion() []byte {
func (c *sshConn) ServerVersion() []byte { func (c *sshConn) ServerVersion() []byte {
return dup(c.serverVersion) return dup(c.serverVersion)
} }
func (c *sshConn) Algorithms() NegotiatedAlgorithms {
return c.algorithms
}

View File

@@ -38,7 +38,7 @@ type keyingTransport interface {
// prepareKeyChange sets up a key change. The key change for a // prepareKeyChange sets up a key change. The key change for a
// direction will be effected if a msgNewKeys message is sent // direction will be effected if a msgNewKeys message is sent
// or received. // or received.
prepareKeyChange(*algorithms, *kexResult) error prepareKeyChange(*NegotiatedAlgorithms, *kexResult) error
// setStrictMode sets the strict KEX mode, notably triggering // setStrictMode sets the strict KEX mode, notably triggering
// sequence number resets on sending or receiving msgNewKeys. // sequence number resets on sending or receiving msgNewKeys.
@@ -115,7 +115,7 @@ type handshakeTransport struct {
bannerCallback BannerCallback bannerCallback BannerCallback
// Algorithms agreed in the last key exchange. // Algorithms agreed in the last key exchange.
algorithms *algorithms algorithms *NegotiatedAlgorithms
// Counters exclusively owned by readLoop. // Counters exclusively owned by readLoop.
readPacketsLeft uint32 readPacketsLeft uint32
@@ -164,7 +164,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt
if config.HostKeyAlgorithms != nil { if config.HostKeyAlgorithms != nil {
t.hostKeyAlgorithms = config.HostKeyAlgorithms t.hostKeyAlgorithms = config.HostKeyAlgorithms
} else { } else {
t.hostKeyAlgorithms = supportedHostKeyAlgos t.hostKeyAlgorithms = defaultHostKeyAlgos
} }
go t.readLoop() go t.readLoop()
go t.kexLoop() go t.kexLoop()
@@ -184,6 +184,10 @@ func (t *handshakeTransport) getSessionID() []byte {
return t.sessionID return t.sessionID
} }
func (t *handshakeTransport) getAlgorithms() NegotiatedAlgorithms {
return *t.algorithms
}
// waitSession waits for the session to be established. This should be // waitSession waits for the session to be established. This should be
// the first thing to call after instantiating handshakeTransport. // the first thing to call after instantiating handshakeTransport.
func (t *handshakeTransport) waitSession() error { func (t *handshakeTransport) waitSession() error {
@@ -290,7 +294,7 @@ func (t *handshakeTransport) resetWriteThresholds() {
if t.config.RekeyThreshold > 0 { if t.config.RekeyThreshold > 0 {
t.writeBytesLeft = int64(t.config.RekeyThreshold) t.writeBytesLeft = int64(t.config.RekeyThreshold)
} else if t.algorithms != nil { } else if t.algorithms != nil {
t.writeBytesLeft = t.algorithms.w.rekeyBytes() t.writeBytesLeft = t.algorithms.Write.rekeyBytes()
} else { } else {
t.writeBytesLeft = 1 << 30 t.writeBytesLeft = 1 << 30
} }
@@ -407,7 +411,7 @@ func (t *handshakeTransport) resetReadThresholds() {
if t.config.RekeyThreshold > 0 { if t.config.RekeyThreshold > 0 {
t.readBytesLeft = int64(t.config.RekeyThreshold) t.readBytesLeft = int64(t.config.RekeyThreshold)
} else if t.algorithms != nil { } else if t.algorithms != nil {
t.readBytesLeft = t.algorithms.r.rekeyBytes() t.readBytesLeft = t.algorithms.Read.rekeyBytes()
} else { } else {
t.readBytesLeft = 1 << 30 t.readBytesLeft = 1 << 30
} }
@@ -700,9 +704,9 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
} }
} }
kex, ok := kexAlgoMap[t.algorithms.kex] kex, ok := kexAlgoMap[t.algorithms.KeyExchange]
if !ok { if !ok {
return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex) return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.KeyExchange)
} }
var result *kexResult var result *kexResult
@@ -809,12 +813,12 @@ func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner {
} }
func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) { func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) {
hostKey := pickHostKey(t.hostKeys, t.algorithms.hostKey) hostKey := pickHostKey(t.hostKeys, t.algorithms.HostKey)
if hostKey == nil { if hostKey == nil {
return nil, errors.New("ssh: internal error: negotiated unsupported signature type") return nil, errors.New("ssh: internal error: negotiated unsupported signature type")
} }
r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.hostKey) r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.HostKey)
return r, err return r, err
} }
@@ -829,7 +833,7 @@ func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (
return nil, err return nil, err
} }
if err := verifyHostKeySignature(hostKey, t.algorithms.hostKey, result); err != nil { if err := verifyHostKeySignature(hostKey, t.algorithms.HostKey, result); err != nil {
return nil, err return nil, err
} }

View File

@@ -20,21 +20,18 @@ import (
) )
const ( const (
kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" // This is the group called diffie-hellman-group1-sha1 in RFC 4253 and
kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" // Oakley Group 2 in RFC 2409.
kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256" oakleyGroup2 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
kexAlgoDH16SHA512 = "diffie-hellman-group16-sha512" // This is the group called diffie-hellman-group14-sha1 in RFC 4253 and
kexAlgoECDH256 = "ecdh-sha2-nistp256" // Oakley Group 14 in RFC 3526.
kexAlgoECDH384 = "ecdh-sha2-nistp384" oakleyGroup14 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"
kexAlgoECDH521 = "ecdh-sha2-nistp521" // This is the group called diffie-hellman-group15-sha512 in RFC 8268 and
kexAlgoCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org" // Oakley Group 15 in RFC 3526.
kexAlgoCurve25519SHA256 = "curve25519-sha256" oakleyGroup15 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
// This is the group called diffie-hellman-group16-sha512 in RFC 8268 and
// For the following kex only the client half contains a production // Oakley Group 16 in RFC 3526.
// ready implementation. The server half only consists of a minimal oakleyGroup16 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF"
// implementation to satisfy the automated tests.
kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1"
kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
) )
// kexResult captures the outcome of a key exchange. // kexResult captures the outcome of a key exchange.
@@ -402,53 +399,46 @@ func ecHash(curve elliptic.Curve) crypto.Hash {
var kexAlgoMap = map[string]kexAlgorithm{} var kexAlgoMap = map[string]kexAlgorithm{}
func init() { func init() {
// This is the group called diffie-hellman-group1-sha1 in p, _ := new(big.Int).SetString(oakleyGroup2, 16)
// RFC 4253 and Oakley Group 2 in RFC 2409. kexAlgoMap[InsecureKeyExchangeDH1SHA1] = &dhGroup{
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
g: new(big.Int).SetInt64(2), g: new(big.Int).SetInt64(2),
p: p, p: p,
pMinus1: new(big.Int).Sub(p, bigOne), pMinus1: new(big.Int).Sub(p, bigOne),
hashFunc: crypto.SHA1, hashFunc: crypto.SHA1,
} }
// This are the groups called diffie-hellman-group14-sha1 and p, _ = new(big.Int).SetString(oakleyGroup14, 16)
// diffie-hellman-group14-sha256 in RFC 4253 and RFC 8268,
// and Oakley Group 14 in RFC 3526.
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
group14 := &dhGroup{ group14 := &dhGroup{
g: new(big.Int).SetInt64(2), g: new(big.Int).SetInt64(2),
p: p, p: p,
pMinus1: new(big.Int).Sub(p, bigOne), pMinus1: new(big.Int).Sub(p, bigOne),
} }
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ kexAlgoMap[InsecureKeyExchangeDH14SHA1] = &dhGroup{
g: group14.g, p: group14.p, pMinus1: group14.pMinus1, g: group14.g, p: group14.p, pMinus1: group14.pMinus1,
hashFunc: crypto.SHA1, hashFunc: crypto.SHA1,
} }
kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{ kexAlgoMap[KeyExchangeDH14SHA256] = &dhGroup{
g: group14.g, p: group14.p, pMinus1: group14.pMinus1, g: group14.g, p: group14.p, pMinus1: group14.pMinus1,
hashFunc: crypto.SHA256, hashFunc: crypto.SHA256,
} }
// This is the group called diffie-hellman-group16-sha512 in RFC p, _ = new(big.Int).SetString(oakleyGroup16, 16)
// 8268 and Oakley Group 16 in RFC 3526.
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH16SHA512] = &dhGroup{ kexAlgoMap[KeyExchangeDH16SHA512] = &dhGroup{
g: new(big.Int).SetInt64(2), g: new(big.Int).SetInt64(2),
p: p, p: p,
pMinus1: new(big.Int).Sub(p, bigOne), pMinus1: new(big.Int).Sub(p, bigOne),
hashFunc: crypto.SHA512, hashFunc: crypto.SHA512,
} }
kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} kexAlgoMap[KeyExchangeECDHP521] = &ecdh{elliptic.P521()}
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} kexAlgoMap[KeyExchangeECDHP384] = &ecdh{elliptic.P384()}
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} kexAlgoMap[KeyExchangeECDHP256] = &ecdh{elliptic.P256()}
kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} kexAlgoMap[KeyExchangeCurve25519] = &curve25519sha256{}
kexAlgoMap[kexAlgoCurve25519SHA256LibSSH] = &curve25519sha256{} kexAlgoMap[keyExchangeCurve25519LibSSH] = &curve25519sha256{}
kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1} kexAlgoMap[InsecureKeyExchangeDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256} kexAlgoMap[KeyExchangeDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
} }
// curve25519sha256 implements the curve25519-sha256 (formerly known as // curve25519sha256 implements the curve25519-sha256 (formerly known as
@@ -601,9 +591,9 @@ const (
func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
// Send GexRequest // Send GexRequest
kexDHGexRequest := kexDHGexRequestMsg{ kexDHGexRequest := kexDHGexRequestMsg{
MinBits: dhGroupExchangeMinimumBits, MinBits: dhGroupExchangeMinimumBits,
PreferedBits: dhGroupExchangePreferredBits, PreferredBits: dhGroupExchangePreferredBits,
MaxBits: dhGroupExchangeMaximumBits, MaxBits: dhGroupExchangeMaximumBits,
} }
if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil { if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil {
return nil, err return nil, err
@@ -690,9 +680,7 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak
} }
// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256. // Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256.
// func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
// This is a minimal implementation to satisfy the automated tests.
func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
// Receive GexRequest // Receive GexRequest
packet, err := c.readPacket() packet, err := c.readPacket()
if err != nil { if err != nil {
@@ -702,13 +690,32 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
if err = Unmarshal(packet, &kexDHGexRequest); err != nil { if err = Unmarshal(packet, &kexDHGexRequest); err != nil {
return return
} }
// We check that the request received is valid and that the MaxBits
// requested are at least equal to our supported minimum. This is the same
// check done in OpenSSH:
// https://github.com/openssh/openssh-portable/blob/80a2f64b/kexgexs.c#L94
//
// Furthermore, we also check that the required MinBits are less than or
// equal to 4096 because we can use up to Oakley Group 16.
if kexDHGexRequest.MaxBits < kexDHGexRequest.MinBits || kexDHGexRequest.PreferredBits < kexDHGexRequest.MinBits ||
kexDHGexRequest.MaxBits < kexDHGexRequest.PreferredBits || kexDHGexRequest.MaxBits < dhGroupExchangeMinimumBits ||
kexDHGexRequest.MinBits > 4096 {
return nil, fmt.Errorf("ssh: DH GEX request out of range, min: %d, max: %d, preferred: %d", kexDHGexRequest.MinBits,
kexDHGexRequest.MaxBits, kexDHGexRequest.PreferredBits)
}
var p *big.Int
// We hardcode sending Oakley Group 14 (2048 bits), Oakley Group 15 (3072
// bits) or Oakley Group 16 (4096 bits), based on the requested max size.
if kexDHGexRequest.MaxBits < 3072 {
p, _ = new(big.Int).SetString(oakleyGroup14, 16)
} else if kexDHGexRequest.MaxBits < 4096 {
p, _ = new(big.Int).SetString(oakleyGroup15, 16)
} else {
p, _ = new(big.Int).SetString(oakleyGroup16, 16)
}
// Send GexGroup
// This is the group called diffie-hellman-group14-sha1 in RFC
// 4253 and Oakley Group 14 in RFC 3526.
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
g := big.NewInt(2) g := big.NewInt(2)
msg := &kexDHGexGroupMsg{ msg := &kexDHGexGroupMsg{
P: p, P: p,
G: g, G: g,
@@ -746,9 +753,9 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
h := gex.hashFunc.New() h := gex.hashFunc.New()
magics.write(h) magics.write(h)
writeString(h, hostKeyBytes) writeString(h, hostKeyBytes)
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) binary.Write(h, binary.BigEndian, kexDHGexRequest.MinBits)
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) binary.Write(h, binary.BigEndian, kexDHGexRequest.PreferredBits)
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) binary.Write(h, binary.BigEndian, kexDHGexRequest.MaxBits)
writeInt(h, p) writeInt(h, p)
writeInt(h, g) writeInt(h, g)
writeInt(h, kexDHGexInit.X) writeInt(h, kexDHGexInit.X)

View File

@@ -36,14 +36,19 @@ import (
// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner // ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner
// arguments. // arguments.
const ( const (
KeyAlgoRSA = "ssh-rsa" KeyAlgoRSA = "ssh-rsa"
KeyAlgoDSA = "ssh-dss" // Deprecated: DSA is only supported at insecure key sizes, and was removed
KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" // from major implementations.
KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com" KeyAlgoDSA = InsecureKeyAlgoDSA
KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" // Deprecated: DSA is only supported at insecure key sizes, and was removed
KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" // from major implementations.
KeyAlgoED25519 = "ssh-ed25519" InsecureKeyAlgoDSA = "ssh-dss"
KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com" KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com"
KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
KeyAlgoED25519 = "ssh-ed25519"
KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"
// KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not // KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not
// public key formats, so they can't appear as a PublicKey.Type. The // public key formats, so they can't appear as a PublicKey.Type. The
@@ -67,7 +72,7 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
switch algo { switch algo {
case KeyAlgoRSA: case KeyAlgoRSA:
return parseRSA(in) return parseRSA(in)
case KeyAlgoDSA: case InsecureKeyAlgoDSA:
return parseDSA(in) return parseDSA(in)
case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
return parseECDSA(in) return parseECDSA(in)
@@ -77,7 +82,7 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
return parseED25519(in) return parseED25519(in)
case KeyAlgoSKED25519: case KeyAlgoSKED25519:
return parseSKEd25519(in) return parseSKEd25519(in)
case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01: case CertAlgoRSAv01, InsecureCertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
cert, err := parseCert(in, certKeyAlgoNames[algo]) cert, err := parseCert(in, certKeyAlgoNames[algo])
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

View File

@@ -47,22 +47,22 @@ func (t truncatingMAC) Size() int {
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() } func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
var macModes = map[string]*macMode{ var macModes = map[string]*macMode{
"hmac-sha2-512-etm@openssh.com": {64, true, func(key []byte) hash.Hash { HMACSHA512ETM: {64, true, func(key []byte) hash.Hash {
return hmac.New(sha512.New, key) return hmac.New(sha512.New, key)
}}, }},
"hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash { HMACSHA256ETM: {32, true, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key) return hmac.New(sha256.New, key)
}}, }},
"hmac-sha2-512": {64, false, func(key []byte) hash.Hash { HMACSHA512: {64, false, func(key []byte) hash.Hash {
return hmac.New(sha512.New, key) return hmac.New(sha512.New, key)
}}, }},
"hmac-sha2-256": {32, false, func(key []byte) hash.Hash { HMACSHA256: {32, false, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key) return hmac.New(sha256.New, key)
}}, }},
"hmac-sha1": {20, false, func(key []byte) hash.Hash { HMACSHA1: {20, false, func(key []byte) hash.Hash {
return hmac.New(sha1.New, key) return hmac.New(sha1.New, key)
}}, }},
"hmac-sha1-96": {20, false, func(key []byte) hash.Hash { InsecureHMACSHA196: {20, false, func(key []byte) hash.Hash {
return truncatingMAC{12, hmac.New(sha1.New, key)} return truncatingMAC{12, hmac.New(sha1.New, key)}
}}, }},
} }

View File

@@ -122,9 +122,9 @@ type kexDHGexReplyMsg struct {
const msgKexDHGexRequest = 34 const msgKexDHGexRequest = 34
type kexDHGexRequestMsg struct { type kexDHGexRequestMsg struct {
MinBits uint32 `sshtype:"34"` MinBits uint32 `sshtype:"34"`
PreferedBits uint32 PreferredBits uint32
MaxBits uint32 MaxBits uint32
} }
// See RFC 4253, section 10. // See RFC 4253, section 10.

View File

@@ -19,19 +19,15 @@ import (
"golang.org/x/crypto/curve25519" "golang.org/x/crypto/curve25519"
) )
const (
kexAlgoMLKEM768xCurve25519SHA256 = "mlkem768x25519-sha256"
)
func init() { func init() {
// After Go 1.24rc1 mlkem swapped the order of return values of Encapsulate. // After Go 1.24rc1 mlkem swapped the order of return values of Encapsulate.
// See #70950. // See #70950.
if runtime.Version() == "go1.24rc1" { if runtime.Version() == "go1.24rc1" {
return return
} }
supportedKexAlgos = slices.Insert(supportedKexAlgos, 0, kexAlgoMLKEM768xCurve25519SHA256) supportedKexAlgos = slices.Insert(supportedKexAlgos, 0, KeyExchangeMLKEM768X25519)
preferredKexAlgos = slices.Insert(preferredKexAlgos, 0, kexAlgoMLKEM768xCurve25519SHA256) defaultKexAlgos = slices.Insert(defaultKexAlgos, 0, KeyExchangeMLKEM768X25519)
kexAlgoMap[kexAlgoMLKEM768xCurve25519SHA256] = &mlkem768WithCurve25519sha256{} kexAlgoMap[KeyExchangeMLKEM768X25519] = &mlkem768WithCurve25519sha256{}
} }
// mlkem768WithCurve25519sha256 implements the hybrid ML-KEM768 with // mlkem768WithCurve25519sha256 implements the hybrid ML-KEM768 with

View File

@@ -243,22 +243,15 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
fullConf.MaxAuthTries = 6 fullConf.MaxAuthTries = 6
} }
if len(fullConf.PublicKeyAuthAlgorithms) == 0 { if len(fullConf.PublicKeyAuthAlgorithms) == 0 {
fullConf.PublicKeyAuthAlgorithms = supportedPubKeyAuthAlgos fullConf.PublicKeyAuthAlgorithms = defaultPubKeyAuthAlgos
} else { } else {
for _, algo := range fullConf.PublicKeyAuthAlgorithms { for _, algo := range fullConf.PublicKeyAuthAlgorithms {
if !contains(supportedPubKeyAuthAlgos, algo) { if !contains(SupportedAlgorithms().PublicKeyAuths, algo) && !contains(InsecureAlgorithms().PublicKeyAuths, algo) {
c.Close() c.Close()
return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo) return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo)
} }
} }
} }
// Check if the config contains any unsupported key exchanges
for _, kex := range fullConf.KeyExchanges {
if _, ok := serverForbiddenKexAlgos[kex]; ok {
c.Close()
return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex)
}
}
s := &connection{ s := &connection{
sshConn: sshConn{conn: c}, sshConn: sshConn{conn: c},
@@ -315,6 +308,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
// We just did the key change, so the session ID is established. // We just did the key change, so the session ID is established.
s.sessionID = s.transport.getSessionID() s.sessionID = s.transport.getSessionID()
s.algorithms = s.transport.getAlgorithms()
var packet []byte var packet []byte
if packet, err = s.transport.readPacket(); err != nil { if packet, err = s.transport.readPacket(); err != nil {

View File

@@ -16,13 +16,6 @@ import (
// wire. No message decoding is done, to minimize the impact on timing. // wire. No message decoding is done, to minimize the impact on timing.
const debugTransport = false const debugTransport = false
const (
gcm128CipherID = "aes128-gcm@openssh.com"
gcm256CipherID = "aes256-gcm@openssh.com"
aes128cbcID = "aes128-cbc"
tripledescbcID = "3des-cbc"
)
// packetConn represents a transport that implements packet based // packetConn represents a transport that implements packet based
// operations. // operations.
type packetConn interface { type packetConn interface {
@@ -92,14 +85,14 @@ func (t *transport) setInitialKEXDone() {
// prepareKeyChange sets up key material for a keychange. The key changes in // prepareKeyChange sets up key material for a keychange. The key changes in
// both directions are triggered by reading and writing a msgNewKey packet // both directions are triggered by reading and writing a msgNewKey packet
// respectively. // respectively.
func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { func (t *transport) prepareKeyChange(algs *NegotiatedAlgorithms, kexResult *kexResult) error {
ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult) ciph, err := newPacketCipher(t.reader.dir, algs.Read, kexResult)
if err != nil { if err != nil {
return err return err
} }
t.reader.pendingKeyChange <- ciph t.reader.pendingKeyChange <- ciph
ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult) ciph, err = newPacketCipher(t.writer.dir, algs.Write, kexResult)
if err != nil { if err != nil {
return err return err
} }
@@ -259,7 +252,7 @@ var (
// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as // setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as
// described in RFC 4253, section 6.4. direction should either be serverKeys // described in RFC 4253, section 6.4. direction should either be serverKeys
// (to setup server->client keys) or clientKeys (for client->server keys). // (to setup server->client keys) or clientKeys (for client->server keys).
func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { func newPacketCipher(d direction, algs DirectionAlgorithms, kex *kexResult) (packetCipher, error) {
cipherMode := cipherModes[algs.Cipher] cipherMode := cipherModes[algs.Cipher]
iv := make([]byte, cipherMode.ivSize) iv := make([]byte, cipherMode.ivSize)

View File

@@ -10,6 +10,7 @@
// builds a list of push/pop events and their node type. Subsequent // builds a list of push/pop events and their node type. Subsequent
// method calls that request a traversal scan this list, rather than walk // method calls that request a traversal scan this list, rather than walk
// the AST, and perform type filtering using efficient bit sets. // the AST, and perform type filtering using efficient bit sets.
// This representation is sometimes called a "balanced parenthesis tree."
// //
// Experiments suggest the inspector's traversals are about 2.5x faster // Experiments suggest the inspector's traversals are about 2.5x faster
// than ast.Inspect, but it may take around 5 traversals for this // than ast.Inspect, but it may take around 5 traversals for this
@@ -47,9 +48,10 @@ type Inspector struct {
events []event events []event
} }
//go:linkname events //go:linkname events golang.org/x/tools/go/ast/inspector.events
func events(in *Inspector) []event { return in.events } func events(in *Inspector) []event { return in.events }
//go:linkname packEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.packEdgeKindAndIndex
func packEdgeKindAndIndex(ek edge.Kind, index int) int32 { func packEdgeKindAndIndex(ek edge.Kind, index int) int32 {
return int32(uint32(index+1)<<7 | uint32(ek)) return int32(uint32(index+1)<<7 | uint32(ek))
} }
@@ -57,7 +59,7 @@ func packEdgeKindAndIndex(ek edge.Kind, index int) int32 {
// unpackEdgeKindAndIndex unpacks the edge kind and edge index (within // unpackEdgeKindAndIndex unpacks the edge kind and edge index (within
// an []ast.Node slice) from the parent field of a pop event. // an []ast.Node slice) from the parent field of a pop event.
// //
//go:linkname unpackEdgeKindAndIndex //go:linkname unpackEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.unpackEdgeKindAndIndex
func unpackEdgeKindAndIndex(x int32) (edge.Kind, int) { func unpackEdgeKindAndIndex(x int32) (edge.Kind, int) {
// The "parent" field of a pop node holds the // The "parent" field of a pop node holds the
// edge Kind in the lower 7 bits and the index+1 // edge Kind in the lower 7 bits and the index+1

View File

@@ -217,7 +217,7 @@ func typeOf(n ast.Node) uint64 {
return 0 return 0
} }
//go:linkname maskOf //go:linkname maskOf golang.org/x/tools/go/ast/inspector.maskOf
func maskOf(nodes []ast.Node) uint64 { func maskOf(nodes []ast.Node) uint64 {
if len(nodes) == 0 { if len(nodes) == 0 {
return math.MaxUint64 // match all node types return math.MaxUint64 // match all node types

View File

@@ -56,7 +56,7 @@ go.uber.org/automaxprocs
go.uber.org/automaxprocs/internal/cgroups go.uber.org/automaxprocs/internal/cgroups
go.uber.org/automaxprocs/internal/runtime go.uber.org/automaxprocs/internal/runtime
go.uber.org/automaxprocs/maxprocs go.uber.org/automaxprocs/maxprocs
# golang.org/x/crypto v0.38.0 # golang.org/x/crypto v0.39.0
## explicit; go 1.23.0 ## explicit; go 1.23.0
golang.org/x/crypto/blowfish golang.org/x/crypto/blowfish
golang.org/x/crypto/chacha20 golang.org/x/crypto/chacha20
@@ -65,7 +65,7 @@ golang.org/x/crypto/internal/alias
golang.org/x/crypto/internal/poly1305 golang.org/x/crypto/internal/poly1305
golang.org/x/crypto/ssh golang.org/x/crypto/ssh
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
# golang.org/x/net v0.38.0 # golang.org/x/net v0.40.0
## explicit; go 1.23.0 ## explicit; go 1.23.0
golang.org/x/net/html golang.org/x/net/html
golang.org/x/net/html/atom golang.org/x/net/html/atom
@@ -74,7 +74,7 @@ golang.org/x/net/html/charset
## explicit; go 1.23.0 ## explicit; go 1.23.0
golang.org/x/sys/cpu golang.org/x/sys/cpu
golang.org/x/sys/unix golang.org/x/sys/unix
# golang.org/x/text v0.25.0 # golang.org/x/text v0.26.0
## explicit; go 1.23.0 ## explicit; go 1.23.0
golang.org/x/text/encoding golang.org/x/text/encoding
golang.org/x/text/encoding/charmap golang.org/x/text/encoding/charmap
@@ -93,7 +93,7 @@ golang.org/x/text/internal/utf8internal
golang.org/x/text/language golang.org/x/text/language
golang.org/x/text/runes golang.org/x/text/runes
golang.org/x/text/transform golang.org/x/text/transform
# golang.org/x/tools v0.31.0 # golang.org/x/tools v0.33.0
## explicit; go 1.23.0 ## explicit; go 1.23.0
golang.org/x/tools/cover golang.org/x/tools/cover
golang.org/x/tools/go/ast/inspector golang.org/x/tools/go/ast/inspector

View File

@@ -89,6 +89,10 @@ func (d *device) GetArchitectureAsString() (string, error) {
return "Ada Lovelace", nil return "Ada Lovelace", nil
case nvml.DEVICE_ARCH_HOPPER: case nvml.DEVICE_ARCH_HOPPER:
return "Hopper", nil return "Hopper", nil
case nvml.DEVICE_ARCH_BLACKWELL:
return "Blackwell", nil
case nvml.DEVICE_ARCH_T23X:
return "Orin", nil
case nvml.DEVICE_ARCH_UNKNOWN: case nvml.DEVICE_ARCH_UNKNOWN:
return "Unknown", nil return "Unknown", nil
} }

View File

@@ -52,6 +52,10 @@ const (
MAX_PHYSICAL_BRIDGE = 128 MAX_PHYSICAL_BRIDGE = 128
// MAX_THERMAL_SENSORS_PER_GPU as defined in nvml/nvml.h // MAX_THERMAL_SENSORS_PER_GPU as defined in nvml/nvml.h
MAX_THERMAL_SENSORS_PER_GPU = 3 MAX_THERMAL_SENSORS_PER_GPU = 3
// DEVICE_UUID_ASCII_LEN as defined in nvml/nvml.h
DEVICE_UUID_ASCII_LEN = 41
// DEVICE_UUID_BINARY_LEN as defined in nvml/nvml.h
DEVICE_UUID_BINARY_LEN = 16
// FlagDefault as defined in nvml/nvml.h // FlagDefault as defined in nvml/nvml.h
FlagDefault = 0 FlagDefault = 0
// FlagForce as defined in nvml/nvml.h // FlagForce as defined in nvml/nvml.h
@@ -62,54 +66,8 @@ const (
DOUBLE_BIT_ECC = 0 DOUBLE_BIT_ECC = 0
// MAX_GPU_PERF_PSTATES as defined in nvml/nvml.h // MAX_GPU_PERF_PSTATES as defined in nvml/nvml.h
MAX_GPU_PERF_PSTATES = 16 MAX_GPU_PERF_PSTATES = 16
// GRID_LICENSE_EXPIRY_NOT_AVAILABLE as defined in nvml/nvml.h // PERF_MODES_BUFFER_SIZE as defined in nvml/nvml.h
GRID_LICENSE_EXPIRY_NOT_AVAILABLE = 0 PERF_MODES_BUFFER_SIZE = 2048
// GRID_LICENSE_EXPIRY_INVALID as defined in nvml/nvml.h
GRID_LICENSE_EXPIRY_INVALID = 1
// GRID_LICENSE_EXPIRY_VALID as defined in nvml/nvml.h
GRID_LICENSE_EXPIRY_VALID = 2
// GRID_LICENSE_EXPIRY_NOT_APPLICABLE as defined in nvml/nvml.h
GRID_LICENSE_EXPIRY_NOT_APPLICABLE = 3
// GRID_LICENSE_EXPIRY_PERMANENT as defined in nvml/nvml.h
GRID_LICENSE_EXPIRY_PERMANENT = 4
// GRID_LICENSE_BUFFER_SIZE as defined in nvml/nvml.h
GRID_LICENSE_BUFFER_SIZE = 128
// VGPU_NAME_BUFFER_SIZE as defined in nvml/nvml.h
VGPU_NAME_BUFFER_SIZE = 64
// GRID_LICENSE_FEATURE_MAX_COUNT as defined in nvml/nvml.h
GRID_LICENSE_FEATURE_MAX_COUNT = 3
// INVALID_VGPU_PLACEMENT_ID as defined in nvml/nvml.h
INVALID_VGPU_PLACEMENT_ID = 65535
// VGPU_SCHEDULER_POLICY_UNKNOWN as defined in nvml/nvml.h
VGPU_SCHEDULER_POLICY_UNKNOWN = 0
// VGPU_SCHEDULER_POLICY_BEST_EFFORT as defined in nvml/nvml.h
VGPU_SCHEDULER_POLICY_BEST_EFFORT = 1
// VGPU_SCHEDULER_POLICY_EQUAL_SHARE as defined in nvml/nvml.h
VGPU_SCHEDULER_POLICY_EQUAL_SHARE = 2
// VGPU_SCHEDULER_POLICY_FIXED_SHARE as defined in nvml/nvml.h
VGPU_SCHEDULER_POLICY_FIXED_SHARE = 3
// SUPPORTED_VGPU_SCHEDULER_POLICY_COUNT as defined in nvml/nvml.h
SUPPORTED_VGPU_SCHEDULER_POLICY_COUNT = 3
// SCHEDULER_SW_MAX_LOG_ENTRIES as defined in nvml/nvml.h
SCHEDULER_SW_MAX_LOG_ENTRIES = 200
// VGPU_SCHEDULER_ARR_DEFAULT as defined in nvml/nvml.h
VGPU_SCHEDULER_ARR_DEFAULT = 0
// VGPU_SCHEDULER_ARR_DISABLE as defined in nvml/nvml.h
VGPU_SCHEDULER_ARR_DISABLE = 1
// VGPU_SCHEDULER_ARR_ENABLE as defined in nvml/nvml.h
VGPU_SCHEDULER_ARR_ENABLE = 2
// GRID_LICENSE_STATE_UNKNOWN as defined in nvml/nvml.h
GRID_LICENSE_STATE_UNKNOWN = 0
// GRID_LICENSE_STATE_UNINITIALIZED as defined in nvml/nvml.h
GRID_LICENSE_STATE_UNINITIALIZED = 1
// GRID_LICENSE_STATE_UNLICENSED_UNRESTRICTED as defined in nvml/nvml.h
GRID_LICENSE_STATE_UNLICENSED_UNRESTRICTED = 2
// GRID_LICENSE_STATE_UNLICENSED_RESTRICTED as defined in nvml/nvml.h
GRID_LICENSE_STATE_UNLICENSED_RESTRICTED = 3
// GRID_LICENSE_STATE_UNLICENSED as defined in nvml/nvml.h
GRID_LICENSE_STATE_UNLICENSED = 4
// GRID_LICENSE_STATE_LICENSED as defined in nvml/nvml.h
GRID_LICENSE_STATE_LICENSED = 5
// GSP_FIRMWARE_VERSION_BUF_SIZE as defined in nvml/nvml.h // GSP_FIRMWARE_VERSION_BUF_SIZE as defined in nvml/nvml.h
GSP_FIRMWARE_VERSION_BUF_SIZE = 64 GSP_FIRMWARE_VERSION_BUF_SIZE = 64
// DEVICE_ARCH_KEPLER as defined in nvml/nvml.h // DEVICE_ARCH_KEPLER as defined in nvml/nvml.h
@@ -128,6 +86,10 @@ const (
DEVICE_ARCH_ADA = 8 DEVICE_ARCH_ADA = 8
// DEVICE_ARCH_HOPPER as defined in nvml/nvml.h // DEVICE_ARCH_HOPPER as defined in nvml/nvml.h
DEVICE_ARCH_HOPPER = 9 DEVICE_ARCH_HOPPER = 9
// DEVICE_ARCH_BLACKWELL as defined in nvml/nvml.h
DEVICE_ARCH_BLACKWELL = 10
// DEVICE_ARCH_T23X as defined in nvml/nvml.h
DEVICE_ARCH_T23X = 11
// DEVICE_ARCH_UNKNOWN as defined in nvml/nvml.h // DEVICE_ARCH_UNKNOWN as defined in nvml/nvml.h
DEVICE_ARCH_UNKNOWN = 4294967295 DEVICE_ARCH_UNKNOWN = 4294967295
// BUS_TYPE_UNKNOWN as defined in nvml/nvml.h // BUS_TYPE_UNKNOWN as defined in nvml/nvml.h
@@ -170,6 +132,82 @@ const (
ADAPTIVE_CLOCKING_INFO_STATUS_ENABLED = 1 ADAPTIVE_CLOCKING_INFO_STATUS_ENABLED = 1
// MAX_GPU_UTILIZATIONS as defined in nvml/nvml.h // MAX_GPU_UTILIZATIONS as defined in nvml/nvml.h
MAX_GPU_UTILIZATIONS = 8 MAX_GPU_UTILIZATIONS = 8
// PCIE_ATOMICS_CAP_FETCHADD32 as defined in nvml/nvml.h
PCIE_ATOMICS_CAP_FETCHADD32 = 1
// PCIE_ATOMICS_CAP_FETCHADD64 as defined in nvml/nvml.h
PCIE_ATOMICS_CAP_FETCHADD64 = 2
// PCIE_ATOMICS_CAP_SWAP32 as defined in nvml/nvml.h
PCIE_ATOMICS_CAP_SWAP32 = 4
// PCIE_ATOMICS_CAP_SWAP64 as defined in nvml/nvml.h
PCIE_ATOMICS_CAP_SWAP64 = 8
// PCIE_ATOMICS_CAP_CAS32 as defined in nvml/nvml.h
PCIE_ATOMICS_CAP_CAS32 = 16
// PCIE_ATOMICS_CAP_CAS64 as defined in nvml/nvml.h
PCIE_ATOMICS_CAP_CAS64 = 32
// PCIE_ATOMICS_CAP_CAS128 as defined in nvml/nvml.h
PCIE_ATOMICS_CAP_CAS128 = 64
// PCIE_ATOMICS_OPS_MAX as defined in nvml/nvml.h
PCIE_ATOMICS_OPS_MAX = 7
// POWER_SCOPE_GPU as defined in nvml/nvml.h
POWER_SCOPE_GPU = 0
// POWER_SCOPE_MODULE as defined in nvml/nvml.h
POWER_SCOPE_MODULE = 1
// POWER_SCOPE_MEMORY as defined in nvml/nvml.h
POWER_SCOPE_MEMORY = 2
// GRID_LICENSE_EXPIRY_NOT_AVAILABLE as defined in nvml/nvml.h
GRID_LICENSE_EXPIRY_NOT_AVAILABLE = 0
// GRID_LICENSE_EXPIRY_INVALID as defined in nvml/nvml.h
GRID_LICENSE_EXPIRY_INVALID = 1
// GRID_LICENSE_EXPIRY_VALID as defined in nvml/nvml.h
GRID_LICENSE_EXPIRY_VALID = 2
// GRID_LICENSE_EXPIRY_NOT_APPLICABLE as defined in nvml/nvml.h
GRID_LICENSE_EXPIRY_NOT_APPLICABLE = 3
// GRID_LICENSE_EXPIRY_PERMANENT as defined in nvml/nvml.h
GRID_LICENSE_EXPIRY_PERMANENT = 4
// GRID_LICENSE_BUFFER_SIZE as defined in nvml/nvml.h
GRID_LICENSE_BUFFER_SIZE = 128
// VGPU_NAME_BUFFER_SIZE as defined in nvml/nvml.h
VGPU_NAME_BUFFER_SIZE = 64
// GRID_LICENSE_FEATURE_MAX_COUNT as defined in nvml/nvml.h
GRID_LICENSE_FEATURE_MAX_COUNT = 3
// INVALID_VGPU_PLACEMENT_ID as defined in nvml/nvml.h
INVALID_VGPU_PLACEMENT_ID = 65535
// VGPU_PGPU_HETEROGENEOUS_MODE as defined in nvml/nvml.h
VGPU_PGPU_HETEROGENEOUS_MODE = 0
// VGPU_PGPU_HOMOGENEOUS_MODE as defined in nvml/nvml.h
VGPU_PGPU_HOMOGENEOUS_MODE = 1
// VGPU_SCHEDULER_POLICY_UNKNOWN as defined in nvml/nvml.h
VGPU_SCHEDULER_POLICY_UNKNOWN = 0
// VGPU_SCHEDULER_POLICY_BEST_EFFORT as defined in nvml/nvml.h
VGPU_SCHEDULER_POLICY_BEST_EFFORT = 1
// VGPU_SCHEDULER_POLICY_EQUAL_SHARE as defined in nvml/nvml.h
VGPU_SCHEDULER_POLICY_EQUAL_SHARE = 2
// VGPU_SCHEDULER_POLICY_FIXED_SHARE as defined in nvml/nvml.h
VGPU_SCHEDULER_POLICY_FIXED_SHARE = 3
// SUPPORTED_VGPU_SCHEDULER_POLICY_COUNT as defined in nvml/nvml.h
SUPPORTED_VGPU_SCHEDULER_POLICY_COUNT = 3
// SCHEDULER_SW_MAX_LOG_ENTRIES as defined in nvml/nvml.h
SCHEDULER_SW_MAX_LOG_ENTRIES = 200
// VGPU_SCHEDULER_ARR_DEFAULT as defined in nvml/nvml.h
VGPU_SCHEDULER_ARR_DEFAULT = 0
// VGPU_SCHEDULER_ARR_DISABLE as defined in nvml/nvml.h
VGPU_SCHEDULER_ARR_DISABLE = 1
// VGPU_SCHEDULER_ARR_ENABLE as defined in nvml/nvml.h
VGPU_SCHEDULER_ARR_ENABLE = 2
// VGPU_SCHEDULER_ENGINE_TYPE_GRAPHICS as defined in nvml/nvml.h
VGPU_SCHEDULER_ENGINE_TYPE_GRAPHICS = 1
// GRID_LICENSE_STATE_UNKNOWN as defined in nvml/nvml.h
GRID_LICENSE_STATE_UNKNOWN = 0
// GRID_LICENSE_STATE_UNINITIALIZED as defined in nvml/nvml.h
GRID_LICENSE_STATE_UNINITIALIZED = 1
// GRID_LICENSE_STATE_UNLICENSED_UNRESTRICTED as defined in nvml/nvml.h
GRID_LICENSE_STATE_UNLICENSED_UNRESTRICTED = 2
// GRID_LICENSE_STATE_UNLICENSED_RESTRICTED as defined in nvml/nvml.h
GRID_LICENSE_STATE_UNLICENSED_RESTRICTED = 3
// GRID_LICENSE_STATE_UNLICENSED as defined in nvml/nvml.h
GRID_LICENSE_STATE_UNLICENSED = 4
// GRID_LICENSE_STATE_LICENSED as defined in nvml/nvml.h
GRID_LICENSE_STATE_LICENSED = 5
// FI_DEV_ECC_CURRENT as defined in nvml/nvml.h // FI_DEV_ECC_CURRENT as defined in nvml/nvml.h
FI_DEV_ECC_CURRENT = 1 FI_DEV_ECC_CURRENT = 1
// FI_DEV_ECC_PENDING as defined in nvml/nvml.h // FI_DEV_ECC_PENDING as defined in nvml/nvml.h
@@ -562,10 +600,188 @@ const (
FI_DEV_TEMPERATURE_MEM_MAX_TLIMIT = 195 FI_DEV_TEMPERATURE_MEM_MAX_TLIMIT = 195
// FI_DEV_TEMPERATURE_GPU_MAX_TLIMIT as defined in nvml/nvml.h // FI_DEV_TEMPERATURE_GPU_MAX_TLIMIT as defined in nvml/nvml.h
FI_DEV_TEMPERATURE_GPU_MAX_TLIMIT = 196 FI_DEV_TEMPERATURE_GPU_MAX_TLIMIT = 196
// FI_DEV_PCIE_COUNT_TX_BYTES as defined in nvml/nvml.h
FI_DEV_PCIE_COUNT_TX_BYTES = 197
// FI_DEV_PCIE_COUNT_RX_BYTES as defined in nvml/nvml.h
FI_DEV_PCIE_COUNT_RX_BYTES = 198
// FI_DEV_IS_MIG_MODE_INDEPENDENT_MIG_QUERY_CAPABLE as defined in nvml/nvml.h // FI_DEV_IS_MIG_MODE_INDEPENDENT_MIG_QUERY_CAPABLE as defined in nvml/nvml.h
FI_DEV_IS_MIG_MODE_INDEPENDENT_MIG_QUERY_CAPABLE = 199 FI_DEV_IS_MIG_MODE_INDEPENDENT_MIG_QUERY_CAPABLE = 199
// FI_DEV_NVLINK_GET_POWER_THRESHOLD_MAX as defined in nvml/nvml.h
FI_DEV_NVLINK_GET_POWER_THRESHOLD_MAX = 200
// FI_DEV_NVLINK_COUNT_XMIT_PACKETS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_XMIT_PACKETS = 201
// FI_DEV_NVLINK_COUNT_XMIT_BYTES as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_XMIT_BYTES = 202
// FI_DEV_NVLINK_COUNT_RCV_PACKETS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_RCV_PACKETS = 203
// FI_DEV_NVLINK_COUNT_RCV_BYTES as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_RCV_BYTES = 204
// FI_DEV_NVLINK_COUNT_VL15_DROPPED as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_VL15_DROPPED = 205
// FI_DEV_NVLINK_COUNT_MALFORMED_PACKET_ERRORS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_MALFORMED_PACKET_ERRORS = 206
// FI_DEV_NVLINK_COUNT_BUFFER_OVERRUN_ERRORS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_BUFFER_OVERRUN_ERRORS = 207
// FI_DEV_NVLINK_COUNT_RCV_ERRORS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_RCV_ERRORS = 208
// FI_DEV_NVLINK_COUNT_RCV_REMOTE_ERRORS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_RCV_REMOTE_ERRORS = 209
// FI_DEV_NVLINK_COUNT_RCV_GENERAL_ERRORS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_RCV_GENERAL_ERRORS = 210
// FI_DEV_NVLINK_COUNT_LOCAL_LINK_INTEGRITY_ERRORS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_LOCAL_LINK_INTEGRITY_ERRORS = 211
// FI_DEV_NVLINK_COUNT_XMIT_DISCARDS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_XMIT_DISCARDS = 212
// FI_DEV_NVLINK_COUNT_LINK_RECOVERY_SUCCESSFUL_EVENTS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_LINK_RECOVERY_SUCCESSFUL_EVENTS = 213
// FI_DEV_NVLINK_COUNT_LINK_RECOVERY_FAILED_EVENTS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_LINK_RECOVERY_FAILED_EVENTS = 214
// FI_DEV_NVLINK_COUNT_LINK_RECOVERY_EVENTS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_LINK_RECOVERY_EVENTS = 215
// FI_DEV_NVLINK_COUNT_RAW_BER_LANE0 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_RAW_BER_LANE0 = 216
// FI_DEV_NVLINK_COUNT_RAW_BER_LANE1 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_RAW_BER_LANE1 = 217
// FI_DEV_NVLINK_COUNT_RAW_BER as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_RAW_BER = 218
// FI_DEV_NVLINK_COUNT_EFFECTIVE_ERRORS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_EFFECTIVE_ERRORS = 219
// FI_DEV_NVLINK_COUNT_EFFECTIVE_BER as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_EFFECTIVE_BER = 220
// FI_DEV_NVLINK_COUNT_SYMBOL_ERRORS as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_SYMBOL_ERRORS = 221
// FI_DEV_NVLINK_COUNT_SYMBOL_BER as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_SYMBOL_BER = 222
// FI_DEV_NVLINK_GET_POWER_THRESHOLD_MIN as defined in nvml/nvml.h
FI_DEV_NVLINK_GET_POWER_THRESHOLD_MIN = 223
// FI_DEV_NVLINK_GET_POWER_THRESHOLD_UNITS as defined in nvml/nvml.h
FI_DEV_NVLINK_GET_POWER_THRESHOLD_UNITS = 224
// FI_DEV_NVLINK_GET_POWER_THRESHOLD_SUPPORTED as defined in nvml/nvml.h
FI_DEV_NVLINK_GET_POWER_THRESHOLD_SUPPORTED = 225
// FI_DEV_RESET_STATUS as defined in nvml/nvml.h
FI_DEV_RESET_STATUS = 226
// FI_DEV_DRAIN_AND_RESET_STATUS as defined in nvml/nvml.h
FI_DEV_DRAIN_AND_RESET_STATUS = 227
// FI_DEV_PCIE_OUTBOUND_ATOMICS_MASK as defined in nvml/nvml.h
FI_DEV_PCIE_OUTBOUND_ATOMICS_MASK = 228
// FI_DEV_PCIE_INBOUND_ATOMICS_MASK as defined in nvml/nvml.h
FI_DEV_PCIE_INBOUND_ATOMICS_MASK = 229
// FI_DEV_GET_GPU_RECOVERY_ACTION as defined in nvml/nvml.h
FI_DEV_GET_GPU_RECOVERY_ACTION = 230
// FI_DEV_C2C_LINK_ERROR_INTR as defined in nvml/nvml.h
FI_DEV_C2C_LINK_ERROR_INTR = 231
// FI_DEV_C2C_LINK_ERROR_REPLAY as defined in nvml/nvml.h
FI_DEV_C2C_LINK_ERROR_REPLAY = 232
// FI_DEV_C2C_LINK_ERROR_REPLAY_B2B as defined in nvml/nvml.h
FI_DEV_C2C_LINK_ERROR_REPLAY_B2B = 233
// FI_DEV_C2C_LINK_POWER_STATE as defined in nvml/nvml.h
FI_DEV_C2C_LINK_POWER_STATE = 234
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_0 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_0 = 235
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_1 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_1 = 236
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_2 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_2 = 237
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_3 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_3 = 238
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_4 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_4 = 239
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_5 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_5 = 240
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_6 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_6 = 241
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_7 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_7 = 242
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_8 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_8 = 243
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_9 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_9 = 244
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_10 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_10 = 245
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_11 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_11 = 246
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_12 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_12 = 247
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_13 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_13 = 248
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_14 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_14 = 249
// FI_DEV_NVLINK_COUNT_FEC_HISTORY_15 as defined in nvml/nvml.h
FI_DEV_NVLINK_COUNT_FEC_HISTORY_15 = 250
// FI_DEV_CLOCKS_EVENT_REASON_SW_POWER_CAP as defined in nvml/nvml.h
FI_DEV_CLOCKS_EVENT_REASON_SW_POWER_CAP = 74
// FI_DEV_CLOCKS_EVENT_REASON_SYNC_BOOST as defined in nvml/nvml.h
FI_DEV_CLOCKS_EVENT_REASON_SYNC_BOOST = 76
// FI_DEV_CLOCKS_EVENT_REASON_SW_THERM_SLOWDOWN as defined in nvml/nvml.h
FI_DEV_CLOCKS_EVENT_REASON_SW_THERM_SLOWDOWN = 251
// FI_DEV_CLOCKS_EVENT_REASON_HW_THERM_SLOWDOWN as defined in nvml/nvml.h
FI_DEV_CLOCKS_EVENT_REASON_HW_THERM_SLOWDOWN = 252
// FI_DEV_CLOCKS_EVENT_REASON_HW_POWER_BRAKE_SLOWDOWN as defined in nvml/nvml.h
FI_DEV_CLOCKS_EVENT_REASON_HW_POWER_BRAKE_SLOWDOWN = 253
// FI_DEV_POWER_SYNC_BALANCING_FREQ as defined in nvml/nvml.h
FI_DEV_POWER_SYNC_BALANCING_FREQ = 254
// FI_DEV_POWER_SYNC_BALANCING_AF as defined in nvml/nvml.h
FI_DEV_POWER_SYNC_BALANCING_AF = 255
// FI_PWR_SMOOTHING_ENABLED as defined in nvml/nvml.h
FI_PWR_SMOOTHING_ENABLED = 256
// FI_PWR_SMOOTHING_PRIV_LVL as defined in nvml/nvml.h
FI_PWR_SMOOTHING_PRIV_LVL = 257
// FI_PWR_SMOOTHING_IMM_RAMP_DOWN_ENABLED as defined in nvml/nvml.h
FI_PWR_SMOOTHING_IMM_RAMP_DOWN_ENABLED = 258
// FI_PWR_SMOOTHING_APPLIED_TMP_CEIL as defined in nvml/nvml.h
FI_PWR_SMOOTHING_APPLIED_TMP_CEIL = 259
// FI_PWR_SMOOTHING_APPLIED_TMP_FLOOR as defined in nvml/nvml.h
FI_PWR_SMOOTHING_APPLIED_TMP_FLOOR = 260
// FI_PWR_SMOOTHING_MAX_PERCENT_TMP_FLOOR_SETTING as defined in nvml/nvml.h
FI_PWR_SMOOTHING_MAX_PERCENT_TMP_FLOOR_SETTING = 261
// FI_PWR_SMOOTHING_MIN_PERCENT_TMP_FLOOR_SETTING as defined in nvml/nvml.h
FI_PWR_SMOOTHING_MIN_PERCENT_TMP_FLOOR_SETTING = 262
// FI_PWR_SMOOTHING_HW_CIRCUITRY_PERCENT_LIFETIME_REMAINING as defined in nvml/nvml.h
FI_PWR_SMOOTHING_HW_CIRCUITRY_PERCENT_LIFETIME_REMAINING = 263
// FI_PWR_SMOOTHING_MAX_NUM_PRESET_PROFILES as defined in nvml/nvml.h
FI_PWR_SMOOTHING_MAX_NUM_PRESET_PROFILES = 264
// FI_PWR_SMOOTHING_PROFILE_PERCENT_TMP_FLOOR as defined in nvml/nvml.h
FI_PWR_SMOOTHING_PROFILE_PERCENT_TMP_FLOOR = 265
// FI_PWR_SMOOTHING_PROFILE_RAMP_UP_RATE as defined in nvml/nvml.h
FI_PWR_SMOOTHING_PROFILE_RAMP_UP_RATE = 266
// FI_PWR_SMOOTHING_PROFILE_RAMP_DOWN_RATE as defined in nvml/nvml.h
FI_PWR_SMOOTHING_PROFILE_RAMP_DOWN_RATE = 267
// FI_PWR_SMOOTHING_PROFILE_RAMP_DOWN_HYST_VAL as defined in nvml/nvml.h
FI_PWR_SMOOTHING_PROFILE_RAMP_DOWN_HYST_VAL = 268
// FI_PWR_SMOOTHING_ACTIVE_PRESET_PROFILE as defined in nvml/nvml.h
FI_PWR_SMOOTHING_ACTIVE_PRESET_PROFILE = 269
// FI_PWR_SMOOTHING_ADMIN_OVERRIDE_PERCENT_TMP_FLOOR as defined in nvml/nvml.h
FI_PWR_SMOOTHING_ADMIN_OVERRIDE_PERCENT_TMP_FLOOR = 270
// FI_PWR_SMOOTHING_ADMIN_OVERRIDE_RAMP_UP_RATE as defined in nvml/nvml.h
FI_PWR_SMOOTHING_ADMIN_OVERRIDE_RAMP_UP_RATE = 271
// FI_PWR_SMOOTHING_ADMIN_OVERRIDE_RAMP_DOWN_RATE as defined in nvml/nvml.h
FI_PWR_SMOOTHING_ADMIN_OVERRIDE_RAMP_DOWN_RATE = 272
// FI_PWR_SMOOTHING_ADMIN_OVERRIDE_RAMP_DOWN_HYST_VAL as defined in nvml/nvml.h
FI_PWR_SMOOTHING_ADMIN_OVERRIDE_RAMP_DOWN_HYST_VAL = 273
// FI_MAX as defined in nvml/nvml.h // FI_MAX as defined in nvml/nvml.h
FI_MAX = 200 FI_MAX = 274
// NVLINK_LOW_POWER_THRESHOLD_UNIT_100US as defined in nvml/nvml.h
NVLINK_LOW_POWER_THRESHOLD_UNIT_100US = 0
// NVLINK_LOW_POWER_THRESHOLD_UNIT_50US as defined in nvml/nvml.h
NVLINK_LOW_POWER_THRESHOLD_UNIT_50US = 1
// NVLINK_POWER_STATE_HIGH_SPEED as defined in nvml/nvml.h
NVLINK_POWER_STATE_HIGH_SPEED = 0
// NVLINK_POWER_STATE_LOW as defined in nvml/nvml.h
NVLINK_POWER_STATE_LOW = 1
// NVLINK_LOW_POWER_THRESHOLD_MIN as defined in nvml/nvml.h
NVLINK_LOW_POWER_THRESHOLD_MIN = 1
// NVLINK_LOW_POWER_THRESHOLD_MAX as defined in nvml/nvml.h
NVLINK_LOW_POWER_THRESHOLD_MAX = 8191
// NVLINK_LOW_POWER_THRESHOLD_RESET as defined in nvml/nvml.h
NVLINK_LOW_POWER_THRESHOLD_RESET = 4294967295
// NVLINK_LOW_POWER_THRESHOLD_DEFAULT as defined in nvml/nvml.h
NVLINK_LOW_POWER_THRESHOLD_DEFAULT = 4294967295
// C2C_POWER_STATE_FULL_POWER as defined in nvml/nvml.h
C2C_POWER_STATE_FULL_POWER = 0
// C2C_POWER_STATE_LOW_POWER as defined in nvml/nvml.h
C2C_POWER_STATE_LOW_POWER = 1
// EventTypeNone as defined in nvml/nvml.h
EventTypeNone = 0
// EventTypeSingleBitEccError as defined in nvml/nvml.h // EventTypeSingleBitEccError as defined in nvml/nvml.h
EventTypeSingleBitEccError = 1 EventTypeSingleBitEccError = 1
// EventTypeDoubleBitEccError as defined in nvml/nvml.h // EventTypeDoubleBitEccError as defined in nvml/nvml.h
@@ -580,10 +796,28 @@ const (
EventTypePowerSourceChange = 128 EventTypePowerSourceChange = 128
// EventMigConfigChange as defined in nvml/nvml.h // EventMigConfigChange as defined in nvml/nvml.h
EventMigConfigChange = 256 EventMigConfigChange = 256
// EventTypeNone as defined in nvml/nvml.h // EventTypeSingleBitEccErrorStorm as defined in nvml/nvml.h
EventTypeNone = 0 EventTypeSingleBitEccErrorStorm = 512
// EventTypeDramRetirementEvent as defined in nvml/nvml.h
EventTypeDramRetirementEvent = 1024
// EventTypeDramRetirementFailure as defined in nvml/nvml.h
EventTypeDramRetirementFailure = 2048
// EventTypeNonFatalPoisonError as defined in nvml/nvml.h
EventTypeNonFatalPoisonError = 4096
// EventTypeFatalPoisonError as defined in nvml/nvml.h
EventTypeFatalPoisonError = 8192
// EventTypeGpuUnavailableError as defined in nvml/nvml.h
EventTypeGpuUnavailableError = 16384
// EventTypeGpuRecoveryAction as defined in nvml/nvml.h
EventTypeGpuRecoveryAction = 32768
// EventTypeAll as defined in nvml/nvml.h // EventTypeAll as defined in nvml/nvml.h
EventTypeAll = 415 EventTypeAll = 65439
// SystemEventTypeGpuDriverUnbind as defined in nvml/nvml.h
SystemEventTypeGpuDriverUnbind = 1
// SystemEventTypeGpuDriverBind as defined in nvml/nvml.h
SystemEventTypeGpuDriverBind = 2
// SystemEventTypeCount as defined in nvml/nvml.h
SystemEventTypeCount = 2
// ClocksEventReasonGpuIdle as defined in nvml/nvml.h // ClocksEventReasonGpuIdle as defined in nvml/nvml.h
ClocksEventReasonGpuIdle = 1 ClocksEventReasonGpuIdle = 1
// ClocksEventReasonApplicationsClocksSetting as defined in nvml/nvml.h // ClocksEventReasonApplicationsClocksSetting as defined in nvml/nvml.h
@@ -640,6 +874,10 @@ const (
CC_SYSTEM_CPU_CAPS_AMD_SEV = 1 CC_SYSTEM_CPU_CAPS_AMD_SEV = 1
// CC_SYSTEM_CPU_CAPS_INTEL_TDX as defined in nvml/nvml.h // CC_SYSTEM_CPU_CAPS_INTEL_TDX as defined in nvml/nvml.h
CC_SYSTEM_CPU_CAPS_INTEL_TDX = 2 CC_SYSTEM_CPU_CAPS_INTEL_TDX = 2
// CC_SYSTEM_CPU_CAPS_AMD_SEV_SNP as defined in nvml/nvml.h
CC_SYSTEM_CPU_CAPS_AMD_SEV_SNP = 3
// CC_SYSTEM_CPU_CAPS_AMD_SNP_VTOM as defined in nvml/nvml.h
CC_SYSTEM_CPU_CAPS_AMD_SNP_VTOM = 4
// CC_SYSTEM_GPUS_CC_NOT_CAPABLE as defined in nvml/nvml.h // CC_SYSTEM_GPUS_CC_NOT_CAPABLE as defined in nvml/nvml.h
CC_SYSTEM_GPUS_CC_NOT_CAPABLE = 0 CC_SYSTEM_GPUS_CC_NOT_CAPABLE = 0
// CC_SYSTEM_GPUS_CC_CAPABLE as defined in nvml/nvml.h // CC_SYSTEM_GPUS_CC_CAPABLE as defined in nvml/nvml.h
@@ -683,7 +921,7 @@ const (
// CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MIN as defined in nvml/nvml.h // CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MIN as defined in nvml/nvml.h
CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MIN = 50 CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MIN = 50
// CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MAX as defined in nvml/nvml.h // CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MAX as defined in nvml/nvml.h
CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MAX = 75 CC_KEY_ROTATION_THRESHOLD_ATTACKER_ADVANTAGE_MAX = 65
// GPU_FABRIC_UUID_LEN as defined in nvml/nvml.h // GPU_FABRIC_UUID_LEN as defined in nvml/nvml.h
GPU_FABRIC_UUID_LEN = 16 GPU_FABRIC_UUID_LEN = 16
// GPU_FABRIC_STATE_NOT_SUPPORTED as defined in nvml/nvml.h // GPU_FABRIC_STATE_NOT_SUPPORTED as defined in nvml/nvml.h
@@ -703,13 +941,37 @@ const (
// GPU_FABRIC_HEALTH_MASK_SHIFT_DEGRADED_BW as defined in nvml/nvml.h // GPU_FABRIC_HEALTH_MASK_SHIFT_DEGRADED_BW as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_SHIFT_DEGRADED_BW = 0 GPU_FABRIC_HEALTH_MASK_SHIFT_DEGRADED_BW = 0
// GPU_FABRIC_HEALTH_MASK_WIDTH_DEGRADED_BW as defined in nvml/nvml.h // GPU_FABRIC_HEALTH_MASK_WIDTH_DEGRADED_BW as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_WIDTH_DEGRADED_BW = 17 GPU_FABRIC_HEALTH_MASK_WIDTH_DEGRADED_BW = 3
// POWER_SCOPE_GPU as defined in nvml/nvml.h // GPU_FABRIC_HEALTH_MASK_ROUTE_RECOVERY_NOT_SUPPORTED as defined in nvml/nvml.h
POWER_SCOPE_GPU = 0 GPU_FABRIC_HEALTH_MASK_ROUTE_RECOVERY_NOT_SUPPORTED = 0
// POWER_SCOPE_MODULE as defined in nvml/nvml.h // GPU_FABRIC_HEALTH_MASK_ROUTE_RECOVERY_TRUE as defined in nvml/nvml.h
POWER_SCOPE_MODULE = 1 GPU_FABRIC_HEALTH_MASK_ROUTE_RECOVERY_TRUE = 1
// POWER_SCOPE_MEMORY as defined in nvml/nvml.h // GPU_FABRIC_HEALTH_MASK_ROUTE_RECOVERY_FALSE as defined in nvml/nvml.h
POWER_SCOPE_MEMORY = 2 GPU_FABRIC_HEALTH_MASK_ROUTE_RECOVERY_FALSE = 2
// GPU_FABRIC_HEALTH_MASK_SHIFT_ROUTE_RECOVERY as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_SHIFT_ROUTE_RECOVERY = 2
// GPU_FABRIC_HEALTH_MASK_WIDTH_ROUTE_RECOVERY as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_WIDTH_ROUTE_RECOVERY = 3
// GPU_FABRIC_HEALTH_MASK_ROUTE_UNHEALTHY_NOT_SUPPORTED as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_ROUTE_UNHEALTHY_NOT_SUPPORTED = 0
// GPU_FABRIC_HEALTH_MASK_ROUTE_UNHEALTHY_TRUE as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_ROUTE_UNHEALTHY_TRUE = 1
// GPU_FABRIC_HEALTH_MASK_ROUTE_UNHEALTHY_FALSE as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_ROUTE_UNHEALTHY_FALSE = 2
// GPU_FABRIC_HEALTH_MASK_SHIFT_ROUTE_UNHEALTHY as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_SHIFT_ROUTE_UNHEALTHY = 4
// GPU_FABRIC_HEALTH_MASK_WIDTH_ROUTE_UNHEALTHY as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_WIDTH_ROUTE_UNHEALTHY = 3
// GPU_FABRIC_HEALTH_MASK_ACCESS_TIMEOUT_RECOVERY_NOT_SUPPORTED as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_ACCESS_TIMEOUT_RECOVERY_NOT_SUPPORTED = 0
// GPU_FABRIC_HEALTH_MASK_ACCESS_TIMEOUT_RECOVERY_TRUE as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_ACCESS_TIMEOUT_RECOVERY_TRUE = 1
// GPU_FABRIC_HEALTH_MASK_ACCESS_TIMEOUT_RECOVERY_FALSE as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_ACCESS_TIMEOUT_RECOVERY_FALSE = 2
// GPU_FABRIC_HEALTH_MASK_SHIFT_ACCESS_TIMEOUT_RECOVERY as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_SHIFT_ACCESS_TIMEOUT_RECOVERY = 6
// GPU_FABRIC_HEALTH_MASK_WIDTH_ACCESS_TIMEOUT_RECOVERY as defined in nvml/nvml.h
GPU_FABRIC_HEALTH_MASK_WIDTH_ACCESS_TIMEOUT_RECOVERY = 3
// INIT_FLAG_NO_GPUS as defined in nvml/nvml.h // INIT_FLAG_NO_GPUS as defined in nvml/nvml.h
INIT_FLAG_NO_GPUS = 1 INIT_FLAG_NO_GPUS = 1
// INIT_FLAG_NO_ATTACH as defined in nvml/nvml.h // INIT_FLAG_NO_ATTACH as defined in nvml/nvml.h
@@ -738,6 +1000,22 @@ const (
AFFINITY_SCOPE_NODE = 0 AFFINITY_SCOPE_NODE = 0
// AFFINITY_SCOPE_SOCKET as defined in nvml/nvml.h // AFFINITY_SCOPE_SOCKET as defined in nvml/nvml.h
AFFINITY_SCOPE_SOCKET = 1 AFFINITY_SCOPE_SOCKET = 1
// NVLINK_BER_MANTISSA_SHIFT as defined in nvml/nvml.h
NVLINK_BER_MANTISSA_SHIFT = 8
// NVLINK_BER_MANTISSA_WIDTH as defined in nvml/nvml.h
NVLINK_BER_MANTISSA_WIDTH = 15
// NVLINK_BER_EXP_SHIFT as defined in nvml/nvml.h
NVLINK_BER_EXP_SHIFT = 0
// NVLINK_BER_EXP_WIDTH as defined in nvml/nvml.h
NVLINK_BER_EXP_WIDTH = 255
// NVLINK_STATE_INACTIVE as defined in nvml/nvml.h
NVLINK_STATE_INACTIVE = 0
// NVLINK_STATE_ACTIVE as defined in nvml/nvml.h
NVLINK_STATE_ACTIVE = 1
// NVLINK_STATE_SLEEP as defined in nvml/nvml.h
NVLINK_STATE_SLEEP = 2
// NVLINK_TOTAL_SUPPORTED_BW_MODES as defined in nvml/nvml.h
NVLINK_TOTAL_SUPPORTED_BW_MODES = 23
// DEVICE_MIG_DISABLE as defined in nvml/nvml.h // DEVICE_MIG_DISABLE as defined in nvml/nvml.h
DEVICE_MIG_DISABLE = 0 DEVICE_MIG_DISABLE = 0
// DEVICE_MIG_ENABLE as defined in nvml/nvml.h // DEVICE_MIG_ENABLE as defined in nvml/nvml.h
@@ -762,10 +1040,30 @@ const (
GPU_INSTANCE_PROFILE_2_SLICE_REV1 = 8 GPU_INSTANCE_PROFILE_2_SLICE_REV1 = 8
// GPU_INSTANCE_PROFILE_1_SLICE_REV2 as defined in nvml/nvml.h // GPU_INSTANCE_PROFILE_1_SLICE_REV2 as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_1_SLICE_REV2 = 9 GPU_INSTANCE_PROFILE_1_SLICE_REV2 = 9
// GPU_INSTANCE_PROFILE_1_SLICE_GFX as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_1_SLICE_GFX = 10
// GPU_INSTANCE_PROFILE_2_SLICE_GFX as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_2_SLICE_GFX = 11
// GPU_INSTANCE_PROFILE_4_SLICE_GFX as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_4_SLICE_GFX = 12
// GPU_INSTANCE_PROFILE_1_SLICE_NO_ME as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_1_SLICE_NO_ME = 13
// GPU_INSTANCE_PROFILE_2_SLICE_NO_ME as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_2_SLICE_NO_ME = 14
// GPU_INSTANCE_PROFILE_1_SLICE_ALL_ME as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_1_SLICE_ALL_ME = 15
// GPU_INSTANCE_PROFILE_2_SLICE_ALL_ME as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_2_SLICE_ALL_ME = 16
// GPU_INSTANCE_PROFILE_COUNT as defined in nvml/nvml.h // GPU_INSTANCE_PROFILE_COUNT as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_COUNT = 10 GPU_INSTANCE_PROFILE_COUNT = 17
// GPU_INSTANCE_PROFILE_CAPS_P2P as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_CAPS_P2P = 1
// GPU_INTSTANCE_PROFILE_CAPS_P2P as defined in nvml/nvml.h // GPU_INTSTANCE_PROFILE_CAPS_P2P as defined in nvml/nvml.h
GPU_INTSTANCE_PROFILE_CAPS_P2P = 1 GPU_INTSTANCE_PROFILE_CAPS_P2P = 1
// GPU_INSTANCE_PROFILE_CAPS_GFX as defined in nvml/nvml.h
GPU_INSTANCE_PROFILE_CAPS_GFX = 2
// COMPUTE_INSTANCE_PROFILE_CAPS_GFX as defined in nvml/nvml.h
COMPUTE_INSTANCE_PROFILE_CAPS_GFX = 1
// COMPUTE_INSTANCE_PROFILE_1_SLICE as defined in nvml/nvml.h // COMPUTE_INSTANCE_PROFILE_1_SLICE as defined in nvml/nvml.h
COMPUTE_INSTANCE_PROFILE_1_SLICE = 0 COMPUTE_INSTANCE_PROFILE_1_SLICE = 0
// COMPUTE_INSTANCE_PROFILE_2_SLICE as defined in nvml/nvml.h // COMPUTE_INSTANCE_PROFILE_2_SLICE as defined in nvml/nvml.h
@@ -792,16 +1090,24 @@ const (
GPM_METRICS_GET_VERSION = 1 GPM_METRICS_GET_VERSION = 1
// GPM_SUPPORT_VERSION as defined in nvml/nvml.h // GPM_SUPPORT_VERSION as defined in nvml/nvml.h
GPM_SUPPORT_VERSION = 1 GPM_SUPPORT_VERSION = 1
// NVLINK_POWER_STATE_HIGH_SPEED as defined in nvml/nvml.h // DEV_CAP_EGM as defined in nvml/nvml.h
NVLINK_POWER_STATE_HIGH_SPEED = 0 DEV_CAP_EGM = 1
// NVLINK_POWER_STATE_LOW as defined in nvml/nvml.h // WORKLOAD_POWER_MAX_PROFILES as defined in nvml/nvml.h
NVLINK_POWER_STATE_LOW = 1 WORKLOAD_POWER_MAX_PROFILES = 255
// NVLINK_LOW_POWER_THRESHOLD_MIN as defined in nvml/nvml.h // POWER_SMOOTHING_MAX_NUM_PROFILES as defined in nvml/nvml.h
NVLINK_LOW_POWER_THRESHOLD_MIN = 1 POWER_SMOOTHING_MAX_NUM_PROFILES = 5
// NVLINK_LOW_POWER_THRESHOLD_MAX as defined in nvml/nvml.h // POWER_SMOOTHING_NUM_PROFILE_PARAMS as defined in nvml/nvml.h
NVLINK_LOW_POWER_THRESHOLD_MAX = 8191 POWER_SMOOTHING_NUM_PROFILE_PARAMS = 4
// NVLINK_LOW_POWER_THRESHOLD_RESET as defined in nvml/nvml.h // POWER_SMOOTHING_ADMIN_OVERRIDE_NOT_SET as defined in nvml/nvml.h
NVLINK_LOW_POWER_THRESHOLD_RESET = 4294967295 POWER_SMOOTHING_ADMIN_OVERRIDE_NOT_SET = 4294967295
// POWER_SMOOTHING_PROFILE_PARAM_PERCENT_TMP_FLOOR as defined in nvml/nvml.h
POWER_SMOOTHING_PROFILE_PARAM_PERCENT_TMP_FLOOR = 0
// POWER_SMOOTHING_PROFILE_PARAM_RAMP_UP_RATE as defined in nvml/nvml.h
POWER_SMOOTHING_PROFILE_PARAM_RAMP_UP_RATE = 1
// POWER_SMOOTHING_PROFILE_PARAM_RAMP_DOWN_RATE as defined in nvml/nvml.h
POWER_SMOOTHING_PROFILE_PARAM_RAMP_DOWN_RATE = 2
// POWER_SMOOTHING_PROFILE_PARAM_RAMP_DOWN_HYSTERESIS as defined in nvml/nvml.h
POWER_SMOOTHING_PROFILE_PARAM_RAMP_DOWN_HYSTERESIS = 3
) )
// BridgeChipType as declared in nvml/nvml.h // BridgeChipType as declared in nvml/nvml.h
@@ -960,7 +1266,8 @@ const (
VALUE_TYPE_UNSIGNED_LONG_LONG ValueType = 3 VALUE_TYPE_UNSIGNED_LONG_LONG ValueType = 3
VALUE_TYPE_SIGNED_LONG_LONG ValueType = 4 VALUE_TYPE_SIGNED_LONG_LONG ValueType = 4
VALUE_TYPE_SIGNED_INT ValueType = 5 VALUE_TYPE_SIGNED_INT ValueType = 5
VALUE_TYPE_COUNT ValueType = 6 VALUE_TYPE_UNSIGNED_SHORT ValueType = 6
VALUE_TYPE_COUNT ValueType = 7
) )
// PerfPolicyType as declared in nvml/nvml.h // PerfPolicyType as declared in nvml/nvml.h
@@ -979,6 +1286,29 @@ const (
PERF_POLICY_COUNT PerfPolicyType = 12 PERF_POLICY_COUNT PerfPolicyType = 12
) )
// CoolerControl as declared in nvml/nvml.h
type CoolerControl int32
// CoolerControl enumeration from nvml/nvml.h
const (
THERMAL_COOLER_SIGNAL_NONE CoolerControl = iota
THERMAL_COOLER_SIGNAL_TOGGLE CoolerControl = 1
THERMAL_COOLER_SIGNAL_VARIABLE CoolerControl = 2
THERMAL_COOLER_SIGNAL_COUNT CoolerControl = 3
)
// CoolerTarget as declared in nvml/nvml.h
type CoolerTarget int32
// CoolerTarget enumeration from nvml/nvml.h
const (
THERMAL_COOLER_TARGET_NONE CoolerTarget = 1
THERMAL_COOLER_TARGET_GPU CoolerTarget = 2
THERMAL_COOLER_TARGET_MEMORY CoolerTarget = 4
THERMAL_COOLER_TARGET_POWER_SUPPLY CoolerTarget = 8
THERMAL_COOLER_TARGET_GPU_RELATED CoolerTarget = 14
)
// EnableState as declared in nvml/nvml.h // EnableState as declared in nvml/nvml.h
type EnableState int32 type EnableState int32
@@ -1026,7 +1356,8 @@ const (
TEMPERATURE_THRESHOLD_ACOUSTIC_MIN TemperatureThresholds = 4 TEMPERATURE_THRESHOLD_ACOUSTIC_MIN TemperatureThresholds = 4
TEMPERATURE_THRESHOLD_ACOUSTIC_CURR TemperatureThresholds = 5 TEMPERATURE_THRESHOLD_ACOUSTIC_CURR TemperatureThresholds = 5
TEMPERATURE_THRESHOLD_ACOUSTIC_MAX TemperatureThresholds = 6 TEMPERATURE_THRESHOLD_ACOUSTIC_MAX TemperatureThresholds = 6
TEMPERATURE_THRESHOLD_COUNT TemperatureThresholds = 7 TEMPERATURE_THRESHOLD_GPS_CURR TemperatureThresholds = 7
TEMPERATURE_THRESHOLD_COUNT TemperatureThresholds = 8
) )
// TemperatureSensors as declared in nvml/nvml.h // TemperatureSensors as declared in nvml/nvml.h
@@ -1060,6 +1391,21 @@ const (
MEMORY_ERROR_TYPE_COUNT MemoryErrorType = 2 MEMORY_ERROR_TYPE_COUNT MemoryErrorType = 2
) )
// NvlinkVersion as declared in nvml/nvml.h
type NvlinkVersion int32
// NvlinkVersion enumeration from nvml/nvml.h
const (
NVLINK_VERSION_INVALID NvlinkVersion = iota
NVLINK_VERSION_1_0 NvlinkVersion = 1
NVLINK_VERSION_2_0 NvlinkVersion = 2
NVLINK_VERSION_2_2 NvlinkVersion = 3
NVLINK_VERSION_3_0 NvlinkVersion = 4
NVLINK_VERSION_3_1 NvlinkVersion = 5
NVLINK_VERSION_4_0 NvlinkVersion = 6
NVLINK_VERSION_5_0 NvlinkVersion = 7
)
// EccCounterType as declared in nvml/nvml.h // EccCounterType as declared in nvml/nvml.h
type EccCounterType int32 type EccCounterType int32
@@ -1101,6 +1447,7 @@ type DriverModel int32
const ( const (
DRIVER_WDDM DriverModel = iota DRIVER_WDDM DriverModel = iota
DRIVER_WDM DriverModel = 1 DRIVER_WDM DriverModel = 1
DRIVER_MCDM DriverModel = 2
) )
// Pstates as declared in nvml/nvml.h // Pstates as declared in nvml/nvml.h
@@ -1145,7 +1492,8 @@ const (
INFOROM_OEM InforomObject = iota INFOROM_OEM InforomObject = iota
INFOROM_ECC InforomObject = 1 INFOROM_ECC InforomObject = 1
INFOROM_POWER InforomObject = 2 INFOROM_POWER InforomObject = 2
INFOROM_COUNT InforomObject = 3 INFOROM_DEN InforomObject = 3
INFOROM_COUNT InforomObject = 4
) )
// Return as declared in nvml/nvml.h // Return as declared in nvml/nvml.h
@@ -1223,6 +1571,17 @@ const (
RESTRICTED_API_COUNT RestrictedAPI = 2 RESTRICTED_API_COUNT RestrictedAPI = 2
) )
// GpuUtilizationDomainId as declared in nvml/nvml.h
type GpuUtilizationDomainId int32
// GpuUtilizationDomainId enumeration from nvml/nvml.h
const (
GPU_UTILIZATION_DOMAIN_GPU GpuUtilizationDomainId = iota
GPU_UTILIZATION_DOMAIN_FB GpuUtilizationDomainId = 1
GPU_UTILIZATION_DOMAIN_VID GpuUtilizationDomainId = 2
GPU_UTILIZATION_DOMAIN_BUS GpuUtilizationDomainId = 3
)
// GpuVirtualizationMode as declared in nvml/nvml.h // GpuVirtualizationMode as declared in nvml/nvml.h
type GpuVirtualizationMode int32 type GpuVirtualizationMode int32
@@ -1281,7 +1640,8 @@ type VgpuDriverCapability int32
// VgpuDriverCapability enumeration from nvml/nvml.h // VgpuDriverCapability enumeration from nvml/nvml.h
const ( const (
VGPU_DRIVER_CAP_HETEROGENEOUS_MULTI_VGPU VgpuDriverCapability = iota VGPU_DRIVER_CAP_HETEROGENEOUS_MULTI_VGPU VgpuDriverCapability = iota
VGPU_DRIVER_CAP_COUNT VgpuDriverCapability = 1 VGPU_DRIVER_CAP_WARM_UPDATE VgpuDriverCapability = 1
VGPU_DRIVER_CAP_COUNT VgpuDriverCapability = 2
) )
// DeviceVgpuCapability as declared in nvml/nvml.h // DeviceVgpuCapability as declared in nvml/nvml.h
@@ -1297,18 +1657,23 @@ const (
DEVICE_VGPU_CAP_DEVICE_STREAMING DeviceVgpuCapability = 5 DEVICE_VGPU_CAP_DEVICE_STREAMING DeviceVgpuCapability = 5
DEVICE_VGPU_CAP_MINI_QUARTER_GPU DeviceVgpuCapability = 6 DEVICE_VGPU_CAP_MINI_QUARTER_GPU DeviceVgpuCapability = 6
DEVICE_VGPU_CAP_COMPUTE_MEDIA_ENGINE_GPU DeviceVgpuCapability = 7 DEVICE_VGPU_CAP_COMPUTE_MEDIA_ENGINE_GPU DeviceVgpuCapability = 7
DEVICE_VGPU_CAP_COUNT DeviceVgpuCapability = 8 DEVICE_VGPU_CAP_WARM_UPDATE DeviceVgpuCapability = 8
DEVICE_VGPU_CAP_HOMOGENEOUS_PLACEMENTS DeviceVgpuCapability = 9
DEVICE_VGPU_CAP_MIG_TIMESLICING_SUPPORTED DeviceVgpuCapability = 10
DEVICE_VGPU_CAP_MIG_TIMESLICING_ENABLED DeviceVgpuCapability = 11
DEVICE_VGPU_CAP_COUNT DeviceVgpuCapability = 12
) )
// GpuUtilizationDomainId as declared in nvml/nvml.h // DeviceGpuRecoveryAction as declared in nvml/nvml.h
type GpuUtilizationDomainId int32 type DeviceGpuRecoveryAction int32
// GpuUtilizationDomainId enumeration from nvml/nvml.h // DeviceGpuRecoveryAction enumeration from nvml/nvml.h
const ( const (
GPU_UTILIZATION_DOMAIN_GPU GpuUtilizationDomainId = iota GPU_RECOVERY_ACTION_NONE DeviceGpuRecoveryAction = iota
GPU_UTILIZATION_DOMAIN_FB GpuUtilizationDomainId = 1 GPU_RECOVERY_ACTION_GPU_RESET DeviceGpuRecoveryAction = 1
GPU_UTILIZATION_DOMAIN_VID GpuUtilizationDomainId = 2 GPU_RECOVERY_ACTION_NODE_REBOOT DeviceGpuRecoveryAction = 2
GPU_UTILIZATION_DOMAIN_BUS GpuUtilizationDomainId = 3 GPU_RECOVERY_ACTION_DRAIN_P2P DeviceGpuRecoveryAction = 3
GPU_RECOVERY_ACTION_DRAIN_AND_RESET DeviceGpuRecoveryAction = 4
) )
// FanState as declared in nvml/nvml.h // FanState as declared in nvml/nvml.h
@@ -1447,6 +1812,16 @@ const (
THERMAL_CONTROLLER_UNKNOWN ThermalController = -1 THERMAL_CONTROLLER_UNKNOWN ThermalController = -1
) )
// UUIDType as declared in nvml/nvml.h
type UUIDType int32
// UUIDType enumeration from nvml/nvml.h
const (
UUID_TYPE_NONE UUIDType = iota
UUID_TYPE_ASCII UUIDType = 1
UUID_TYPE_BINARY UUIDType = 2
)
// GridLicenseFeatureCode as declared in nvml/nvml.h // GridLicenseFeatureCode as declared in nvml/nvml.h
type GridLicenseFeatureCode int32 type GridLicenseFeatureCode int32
@@ -1465,74 +1840,208 @@ type GpmMetricId int32
// GpmMetricId enumeration from nvml/nvml.h // GpmMetricId enumeration from nvml/nvml.h
const ( const (
GPM_METRIC_GRAPHICS_UTIL GpmMetricId = 1 GPM_METRIC_GRAPHICS_UTIL GpmMetricId = 1
GPM_METRIC_SM_UTIL GpmMetricId = 2 GPM_METRIC_SM_UTIL GpmMetricId = 2
GPM_METRIC_SM_OCCUPANCY GpmMetricId = 3 GPM_METRIC_SM_OCCUPANCY GpmMetricId = 3
GPM_METRIC_INTEGER_UTIL GpmMetricId = 4 GPM_METRIC_INTEGER_UTIL GpmMetricId = 4
GPM_METRIC_ANY_TENSOR_UTIL GpmMetricId = 5 GPM_METRIC_ANY_TENSOR_UTIL GpmMetricId = 5
GPM_METRIC_DFMA_TENSOR_UTIL GpmMetricId = 6 GPM_METRIC_DFMA_TENSOR_UTIL GpmMetricId = 6
GPM_METRIC_HMMA_TENSOR_UTIL GpmMetricId = 7 GPM_METRIC_HMMA_TENSOR_UTIL GpmMetricId = 7
GPM_METRIC_IMMA_TENSOR_UTIL GpmMetricId = 9 GPM_METRIC_IMMA_TENSOR_UTIL GpmMetricId = 9
GPM_METRIC_DRAM_BW_UTIL GpmMetricId = 10 GPM_METRIC_DRAM_BW_UTIL GpmMetricId = 10
GPM_METRIC_FP64_UTIL GpmMetricId = 11 GPM_METRIC_FP64_UTIL GpmMetricId = 11
GPM_METRIC_FP32_UTIL GpmMetricId = 12 GPM_METRIC_FP32_UTIL GpmMetricId = 12
GPM_METRIC_FP16_UTIL GpmMetricId = 13 GPM_METRIC_FP16_UTIL GpmMetricId = 13
GPM_METRIC_PCIE_TX_PER_SEC GpmMetricId = 20 GPM_METRIC_PCIE_TX_PER_SEC GpmMetricId = 20
GPM_METRIC_PCIE_RX_PER_SEC GpmMetricId = 21 GPM_METRIC_PCIE_RX_PER_SEC GpmMetricId = 21
GPM_METRIC_NVDEC_0_UTIL GpmMetricId = 30 GPM_METRIC_NVDEC_0_UTIL GpmMetricId = 30
GPM_METRIC_NVDEC_1_UTIL GpmMetricId = 31 GPM_METRIC_NVDEC_1_UTIL GpmMetricId = 31
GPM_METRIC_NVDEC_2_UTIL GpmMetricId = 32 GPM_METRIC_NVDEC_2_UTIL GpmMetricId = 32
GPM_METRIC_NVDEC_3_UTIL GpmMetricId = 33 GPM_METRIC_NVDEC_3_UTIL GpmMetricId = 33
GPM_METRIC_NVDEC_4_UTIL GpmMetricId = 34 GPM_METRIC_NVDEC_4_UTIL GpmMetricId = 34
GPM_METRIC_NVDEC_5_UTIL GpmMetricId = 35 GPM_METRIC_NVDEC_5_UTIL GpmMetricId = 35
GPM_METRIC_NVDEC_6_UTIL GpmMetricId = 36 GPM_METRIC_NVDEC_6_UTIL GpmMetricId = 36
GPM_METRIC_NVDEC_7_UTIL GpmMetricId = 37 GPM_METRIC_NVDEC_7_UTIL GpmMetricId = 37
GPM_METRIC_NVJPG_0_UTIL GpmMetricId = 40 GPM_METRIC_NVJPG_0_UTIL GpmMetricId = 40
GPM_METRIC_NVJPG_1_UTIL GpmMetricId = 41 GPM_METRIC_NVJPG_1_UTIL GpmMetricId = 41
GPM_METRIC_NVJPG_2_UTIL GpmMetricId = 42 GPM_METRIC_NVJPG_2_UTIL GpmMetricId = 42
GPM_METRIC_NVJPG_3_UTIL GpmMetricId = 43 GPM_METRIC_NVJPG_3_UTIL GpmMetricId = 43
GPM_METRIC_NVJPG_4_UTIL GpmMetricId = 44 GPM_METRIC_NVJPG_4_UTIL GpmMetricId = 44
GPM_METRIC_NVJPG_5_UTIL GpmMetricId = 45 GPM_METRIC_NVJPG_5_UTIL GpmMetricId = 45
GPM_METRIC_NVJPG_6_UTIL GpmMetricId = 46 GPM_METRIC_NVJPG_6_UTIL GpmMetricId = 46
GPM_METRIC_NVJPG_7_UTIL GpmMetricId = 47 GPM_METRIC_NVJPG_7_UTIL GpmMetricId = 47
GPM_METRIC_NVOFA_0_UTIL GpmMetricId = 50 GPM_METRIC_NVOFA_0_UTIL GpmMetricId = 50
GPM_METRIC_NVLINK_TOTAL_RX_PER_SEC GpmMetricId = 60 GPM_METRIC_NVOFA_1_UTIL GpmMetricId = 51
GPM_METRIC_NVLINK_TOTAL_TX_PER_SEC GpmMetricId = 61 GPM_METRIC_NVLINK_TOTAL_RX_PER_SEC GpmMetricId = 60
GPM_METRIC_NVLINK_L0_RX_PER_SEC GpmMetricId = 62 GPM_METRIC_NVLINK_TOTAL_TX_PER_SEC GpmMetricId = 61
GPM_METRIC_NVLINK_L0_TX_PER_SEC GpmMetricId = 63 GPM_METRIC_NVLINK_L0_RX_PER_SEC GpmMetricId = 62
GPM_METRIC_NVLINK_L1_RX_PER_SEC GpmMetricId = 64 GPM_METRIC_NVLINK_L0_TX_PER_SEC GpmMetricId = 63
GPM_METRIC_NVLINK_L1_TX_PER_SEC GpmMetricId = 65 GPM_METRIC_NVLINK_L1_RX_PER_SEC GpmMetricId = 64
GPM_METRIC_NVLINK_L2_RX_PER_SEC GpmMetricId = 66 GPM_METRIC_NVLINK_L1_TX_PER_SEC GpmMetricId = 65
GPM_METRIC_NVLINK_L2_TX_PER_SEC GpmMetricId = 67 GPM_METRIC_NVLINK_L2_RX_PER_SEC GpmMetricId = 66
GPM_METRIC_NVLINK_L3_RX_PER_SEC GpmMetricId = 68 GPM_METRIC_NVLINK_L2_TX_PER_SEC GpmMetricId = 67
GPM_METRIC_NVLINK_L3_TX_PER_SEC GpmMetricId = 69 GPM_METRIC_NVLINK_L3_RX_PER_SEC GpmMetricId = 68
GPM_METRIC_NVLINK_L4_RX_PER_SEC GpmMetricId = 70 GPM_METRIC_NVLINK_L3_TX_PER_SEC GpmMetricId = 69
GPM_METRIC_NVLINK_L4_TX_PER_SEC GpmMetricId = 71 GPM_METRIC_NVLINK_L4_RX_PER_SEC GpmMetricId = 70
GPM_METRIC_NVLINK_L5_RX_PER_SEC GpmMetricId = 72 GPM_METRIC_NVLINK_L4_TX_PER_SEC GpmMetricId = 71
GPM_METRIC_NVLINK_L5_TX_PER_SEC GpmMetricId = 73 GPM_METRIC_NVLINK_L5_RX_PER_SEC GpmMetricId = 72
GPM_METRIC_NVLINK_L6_RX_PER_SEC GpmMetricId = 74 GPM_METRIC_NVLINK_L5_TX_PER_SEC GpmMetricId = 73
GPM_METRIC_NVLINK_L6_TX_PER_SEC GpmMetricId = 75 GPM_METRIC_NVLINK_L6_RX_PER_SEC GpmMetricId = 74
GPM_METRIC_NVLINK_L7_RX_PER_SEC GpmMetricId = 76 GPM_METRIC_NVLINK_L6_TX_PER_SEC GpmMetricId = 75
GPM_METRIC_NVLINK_L7_TX_PER_SEC GpmMetricId = 77 GPM_METRIC_NVLINK_L7_RX_PER_SEC GpmMetricId = 76
GPM_METRIC_NVLINK_L8_RX_PER_SEC GpmMetricId = 78 GPM_METRIC_NVLINK_L7_TX_PER_SEC GpmMetricId = 77
GPM_METRIC_NVLINK_L8_TX_PER_SEC GpmMetricId = 79 GPM_METRIC_NVLINK_L8_RX_PER_SEC GpmMetricId = 78
GPM_METRIC_NVLINK_L9_RX_PER_SEC GpmMetricId = 80 GPM_METRIC_NVLINK_L8_TX_PER_SEC GpmMetricId = 79
GPM_METRIC_NVLINK_L9_TX_PER_SEC GpmMetricId = 81 GPM_METRIC_NVLINK_L9_RX_PER_SEC GpmMetricId = 80
GPM_METRIC_NVLINK_L10_RX_PER_SEC GpmMetricId = 82 GPM_METRIC_NVLINK_L9_TX_PER_SEC GpmMetricId = 81
GPM_METRIC_NVLINK_L10_TX_PER_SEC GpmMetricId = 83 GPM_METRIC_NVLINK_L10_RX_PER_SEC GpmMetricId = 82
GPM_METRIC_NVLINK_L11_RX_PER_SEC GpmMetricId = 84 GPM_METRIC_NVLINK_L10_TX_PER_SEC GpmMetricId = 83
GPM_METRIC_NVLINK_L11_TX_PER_SEC GpmMetricId = 85 GPM_METRIC_NVLINK_L11_RX_PER_SEC GpmMetricId = 84
GPM_METRIC_NVLINK_L12_RX_PER_SEC GpmMetricId = 86 GPM_METRIC_NVLINK_L11_TX_PER_SEC GpmMetricId = 85
GPM_METRIC_NVLINK_L12_TX_PER_SEC GpmMetricId = 87 GPM_METRIC_NVLINK_L12_RX_PER_SEC GpmMetricId = 86
GPM_METRIC_NVLINK_L13_RX_PER_SEC GpmMetricId = 88 GPM_METRIC_NVLINK_L12_TX_PER_SEC GpmMetricId = 87
GPM_METRIC_NVLINK_L13_TX_PER_SEC GpmMetricId = 89 GPM_METRIC_NVLINK_L13_RX_PER_SEC GpmMetricId = 88
GPM_METRIC_NVLINK_L14_RX_PER_SEC GpmMetricId = 90 GPM_METRIC_NVLINK_L13_TX_PER_SEC GpmMetricId = 89
GPM_METRIC_NVLINK_L14_TX_PER_SEC GpmMetricId = 91 GPM_METRIC_NVLINK_L14_RX_PER_SEC GpmMetricId = 90
GPM_METRIC_NVLINK_L15_RX_PER_SEC GpmMetricId = 92 GPM_METRIC_NVLINK_L14_TX_PER_SEC GpmMetricId = 91
GPM_METRIC_NVLINK_L15_TX_PER_SEC GpmMetricId = 93 GPM_METRIC_NVLINK_L15_RX_PER_SEC GpmMetricId = 92
GPM_METRIC_NVLINK_L16_RX_PER_SEC GpmMetricId = 94 GPM_METRIC_NVLINK_L15_TX_PER_SEC GpmMetricId = 93
GPM_METRIC_NVLINK_L16_TX_PER_SEC GpmMetricId = 95 GPM_METRIC_NVLINK_L16_RX_PER_SEC GpmMetricId = 94
GPM_METRIC_NVLINK_L17_RX_PER_SEC GpmMetricId = 96 GPM_METRIC_NVLINK_L16_TX_PER_SEC GpmMetricId = 95
GPM_METRIC_NVLINK_L17_TX_PER_SEC GpmMetricId = 97 GPM_METRIC_NVLINK_L17_RX_PER_SEC GpmMetricId = 96
GPM_METRIC_MAX GpmMetricId = 98 GPM_METRIC_NVLINK_L17_TX_PER_SEC GpmMetricId = 97
GPM_METRIC_C2C_TOTAL_TX_PER_SEC GpmMetricId = 100
GPM_METRIC_C2C_TOTAL_RX_PER_SEC GpmMetricId = 101
GPM_METRIC_C2C_DATA_TX_PER_SEC GpmMetricId = 102
GPM_METRIC_C2C_DATA_RX_PER_SEC GpmMetricId = 103
GPM_METRIC_C2C_LINK0_TOTAL_TX_PER_SEC GpmMetricId = 104
GPM_METRIC_C2C_LINK0_TOTAL_RX_PER_SEC GpmMetricId = 105
GPM_METRIC_C2C_LINK0_DATA_TX_PER_SEC GpmMetricId = 106
GPM_METRIC_C2C_LINK0_DATA_RX_PER_SEC GpmMetricId = 107
GPM_METRIC_C2C_LINK1_TOTAL_TX_PER_SEC GpmMetricId = 108
GPM_METRIC_C2C_LINK1_TOTAL_RX_PER_SEC GpmMetricId = 109
GPM_METRIC_C2C_LINK1_DATA_TX_PER_SEC GpmMetricId = 110
GPM_METRIC_C2C_LINK1_DATA_RX_PER_SEC GpmMetricId = 111
GPM_METRIC_C2C_LINK2_TOTAL_TX_PER_SEC GpmMetricId = 112
GPM_METRIC_C2C_LINK2_TOTAL_RX_PER_SEC GpmMetricId = 113
GPM_METRIC_C2C_LINK2_DATA_TX_PER_SEC GpmMetricId = 114
GPM_METRIC_C2C_LINK2_DATA_RX_PER_SEC GpmMetricId = 115
GPM_METRIC_C2C_LINK3_TOTAL_TX_PER_SEC GpmMetricId = 116
GPM_METRIC_C2C_LINK3_TOTAL_RX_PER_SEC GpmMetricId = 117
GPM_METRIC_C2C_LINK3_DATA_TX_PER_SEC GpmMetricId = 118
GPM_METRIC_C2C_LINK3_DATA_RX_PER_SEC GpmMetricId = 119
GPM_METRIC_C2C_LINK4_TOTAL_TX_PER_SEC GpmMetricId = 120
GPM_METRIC_C2C_LINK4_TOTAL_RX_PER_SEC GpmMetricId = 121
GPM_METRIC_C2C_LINK4_DATA_TX_PER_SEC GpmMetricId = 122
GPM_METRIC_C2C_LINK4_DATA_RX_PER_SEC GpmMetricId = 123
GPM_METRIC_C2C_LINK5_TOTAL_TX_PER_SEC GpmMetricId = 124
GPM_METRIC_C2C_LINK5_TOTAL_RX_PER_SEC GpmMetricId = 125
GPM_METRIC_C2C_LINK5_DATA_TX_PER_SEC GpmMetricId = 126
GPM_METRIC_C2C_LINK5_DATA_RX_PER_SEC GpmMetricId = 127
GPM_METRIC_C2C_LINK6_TOTAL_TX_PER_SEC GpmMetricId = 128
GPM_METRIC_C2C_LINK6_TOTAL_RX_PER_SEC GpmMetricId = 129
GPM_METRIC_C2C_LINK6_DATA_TX_PER_SEC GpmMetricId = 130
GPM_METRIC_C2C_LINK6_DATA_RX_PER_SEC GpmMetricId = 131
GPM_METRIC_C2C_LINK7_TOTAL_TX_PER_SEC GpmMetricId = 132
GPM_METRIC_C2C_LINK7_TOTAL_RX_PER_SEC GpmMetricId = 133
GPM_METRIC_C2C_LINK7_DATA_TX_PER_SEC GpmMetricId = 134
GPM_METRIC_C2C_LINK7_DATA_RX_PER_SEC GpmMetricId = 135
GPM_METRIC_C2C_LINK8_TOTAL_TX_PER_SEC GpmMetricId = 136
GPM_METRIC_C2C_LINK8_TOTAL_RX_PER_SEC GpmMetricId = 137
GPM_METRIC_C2C_LINK8_DATA_TX_PER_SEC GpmMetricId = 138
GPM_METRIC_C2C_LINK8_DATA_RX_PER_SEC GpmMetricId = 139
GPM_METRIC_C2C_LINK9_TOTAL_TX_PER_SEC GpmMetricId = 140
GPM_METRIC_C2C_LINK9_TOTAL_RX_PER_SEC GpmMetricId = 141
GPM_METRIC_C2C_LINK9_DATA_TX_PER_SEC GpmMetricId = 142
GPM_METRIC_C2C_LINK9_DATA_RX_PER_SEC GpmMetricId = 143
GPM_METRIC_C2C_LINK10_TOTAL_TX_PER_SEC GpmMetricId = 144
GPM_METRIC_C2C_LINK10_TOTAL_RX_PER_SEC GpmMetricId = 145
GPM_METRIC_C2C_LINK10_DATA_TX_PER_SEC GpmMetricId = 146
GPM_METRIC_C2C_LINK10_DATA_RX_PER_SEC GpmMetricId = 147
GPM_METRIC_C2C_LINK11_TOTAL_TX_PER_SEC GpmMetricId = 148
GPM_METRIC_C2C_LINK11_TOTAL_RX_PER_SEC GpmMetricId = 149
GPM_METRIC_C2C_LINK11_DATA_TX_PER_SEC GpmMetricId = 150
GPM_METRIC_C2C_LINK11_DATA_RX_PER_SEC GpmMetricId = 151
GPM_METRIC_C2C_LINK12_TOTAL_TX_PER_SEC GpmMetricId = 152
GPM_METRIC_C2C_LINK12_TOTAL_RX_PER_SEC GpmMetricId = 153
GPM_METRIC_C2C_LINK12_DATA_TX_PER_SEC GpmMetricId = 154
GPM_METRIC_C2C_LINK12_DATA_RX_PER_SEC GpmMetricId = 155
GPM_METRIC_C2C_LINK13_TOTAL_TX_PER_SEC GpmMetricId = 156
GPM_METRIC_C2C_LINK13_TOTAL_RX_PER_SEC GpmMetricId = 157
GPM_METRIC_C2C_LINK13_DATA_TX_PER_SEC GpmMetricId = 158
GPM_METRIC_C2C_LINK13_DATA_RX_PER_SEC GpmMetricId = 159
GPM_METRIC_HOSTMEM_CACHE_HIT GpmMetricId = 160
GPM_METRIC_HOSTMEM_CACHE_MISS GpmMetricId = 161
GPM_METRIC_PEERMEM_CACHE_HIT GpmMetricId = 162
GPM_METRIC_PEERMEM_CACHE_MISS GpmMetricId = 163
GPM_METRIC_DRAM_CACHE_HIT GpmMetricId = 164
GPM_METRIC_DRAM_CACHE_MISS GpmMetricId = 165
GPM_METRIC_NVENC_0_UTIL GpmMetricId = 166
GPM_METRIC_NVENC_1_UTIL GpmMetricId = 167
GPM_METRIC_NVENC_2_UTIL GpmMetricId = 168
GPM_METRIC_NVENC_3_UTIL GpmMetricId = 169
GPM_METRIC_GR0_CTXSW_CYCLES_ELAPSED GpmMetricId = 170
GPM_METRIC_GR0_CTXSW_CYCLES_ACTIVE GpmMetricId = 171
GPM_METRIC_GR0_CTXSW_REQUESTS GpmMetricId = 172
GPM_METRIC_GR0_CTXSW_CYCLES_PER_REQ GpmMetricId = 173
GPM_METRIC_GR0_CTXSW_ACTIVE_PCT GpmMetricId = 174
GPM_METRIC_GR1_CTXSW_CYCLES_ELAPSED GpmMetricId = 175
GPM_METRIC_GR1_CTXSW_CYCLES_ACTIVE GpmMetricId = 176
GPM_METRIC_GR1_CTXSW_REQUESTS GpmMetricId = 177
GPM_METRIC_GR1_CTXSW_CYCLES_PER_REQ GpmMetricId = 178
GPM_METRIC_GR1_CTXSW_ACTIVE_PCT GpmMetricId = 179
GPM_METRIC_GR2_CTXSW_CYCLES_ELAPSED GpmMetricId = 180
GPM_METRIC_GR2_CTXSW_CYCLES_ACTIVE GpmMetricId = 181
GPM_METRIC_GR2_CTXSW_REQUESTS GpmMetricId = 182
GPM_METRIC_GR2_CTXSW_CYCLES_PER_REQ GpmMetricId = 183
GPM_METRIC_GR2_CTXSW_ACTIVE_PCT GpmMetricId = 184
GPM_METRIC_GR3_CTXSW_CYCLES_ELAPSED GpmMetricId = 185
GPM_METRIC_GR3_CTXSW_CYCLES_ACTIVE GpmMetricId = 186
GPM_METRIC_GR3_CTXSW_REQUESTS GpmMetricId = 187
GPM_METRIC_GR3_CTXSW_CYCLES_PER_REQ GpmMetricId = 188
GPM_METRIC_GR3_CTXSW_ACTIVE_PCT GpmMetricId = 189
GPM_METRIC_GR4_CTXSW_CYCLES_ELAPSED GpmMetricId = 190
GPM_METRIC_GR4_CTXSW_CYCLES_ACTIVE GpmMetricId = 191
GPM_METRIC_GR4_CTXSW_REQUESTS GpmMetricId = 192
GPM_METRIC_GR4_CTXSW_CYCLES_PER_REQ GpmMetricId = 193
GPM_METRIC_GR4_CTXSW_ACTIVE_PCT GpmMetricId = 194
GPM_METRIC_GR5_CTXSW_CYCLES_ELAPSED GpmMetricId = 195
GPM_METRIC_GR5_CTXSW_CYCLES_ACTIVE GpmMetricId = 196
GPM_METRIC_GR5_CTXSW_REQUESTS GpmMetricId = 197
GPM_METRIC_GR5_CTXSW_CYCLES_PER_REQ GpmMetricId = 198
GPM_METRIC_GR5_CTXSW_ACTIVE_PCT GpmMetricId = 199
GPM_METRIC_GR6_CTXSW_CYCLES_ELAPSED GpmMetricId = 200
GPM_METRIC_GR6_CTXSW_CYCLES_ACTIVE GpmMetricId = 201
GPM_METRIC_GR6_CTXSW_REQUESTS GpmMetricId = 202
GPM_METRIC_GR6_CTXSW_CYCLES_PER_REQ GpmMetricId = 203
GPM_METRIC_GR6_CTXSW_ACTIVE_PCT GpmMetricId = 204
GPM_METRIC_GR7_CTXSW_CYCLES_ELAPSED GpmMetricId = 205
GPM_METRIC_GR7_CTXSW_CYCLES_ACTIVE GpmMetricId = 206
GPM_METRIC_GR7_CTXSW_REQUESTS GpmMetricId = 207
GPM_METRIC_GR7_CTXSW_CYCLES_PER_REQ GpmMetricId = 208
GPM_METRIC_GR7_CTXSW_ACTIVE_PCT GpmMetricId = 209
GPM_METRIC_MAX GpmMetricId = 210
)
// PowerProfileType as declared in nvml/nvml.h
type PowerProfileType int32
// PowerProfileType enumeration from nvml/nvml.h
const (
POWER_PROFILE_MAX_P PowerProfileType = iota
POWER_PROFILE_MAX_Q PowerProfileType = 1
POWER_PROFILE_COMPUTE PowerProfileType = 2
POWER_PROFILE_MEMORY_BOUND PowerProfileType = 3
POWER_PROFILE_NETWORK PowerProfileType = 4
POWER_PROFILE_BALANCED PowerProfileType = 5
POWER_PROFILE_LLM_INFERENCE PowerProfileType = 6
POWER_PROFILE_LLM_TRAINING PowerProfileType = 7
POWER_PROFILE_RBM PowerProfileType = 8
POWER_PROFILE_DCPCIE PowerProfileType = 9
POWER_PROFILE_HMMA_SPARSE PowerProfileType = 10
POWER_PROFILE_HMMA_DENSE PowerProfileType = 11
POWER_PROFILE_SYNC_BALANCED PowerProfileType = 12
POWER_PROFILE_HPC PowerProfileType = 13
POWER_PROFILE_MIG PowerProfileType = 14
POWER_PROFILE_MAX PowerProfileType = 15
) )

View File

@@ -68,16 +68,6 @@ type GpuInstanceInfo struct {
Placement GpuInstancePlacement Placement GpuInstancePlacement
} }
func (g GpuInstanceInfo) convert() nvmlGpuInstanceInfo {
out := nvmlGpuInstanceInfo{
Device: g.Device.(nvmlDevice),
Id: g.Id,
ProfileId: g.ProfileId,
Placement: g.Placement,
}
return out
}
func (g nvmlGpuInstanceInfo) convert() GpuInstanceInfo { func (g nvmlGpuInstanceInfo) convert() GpuInstanceInfo {
out := GpuInstanceInfo{ out := GpuInstanceInfo{
Device: g.Device, Device: g.Device,
@@ -97,17 +87,6 @@ type ComputeInstanceInfo struct {
Placement ComputeInstancePlacement Placement ComputeInstancePlacement
} }
func (c ComputeInstanceInfo) convert() nvmlComputeInstanceInfo {
out := nvmlComputeInstanceInfo{
Device: c.Device.(nvmlDevice),
GpuInstance: c.GpuInstance.(nvmlGpuInstance),
Id: c.Id,
ProfileId: c.ProfileId,
Placement: c.Placement,
}
return out
}
func (c nvmlComputeInstanceInfo) convert() ComputeInstanceInfo { func (c nvmlComputeInstanceInfo) convert() ComputeInstanceInfo {
out := ComputeInstanceInfo{ out := ComputeInstanceInfo{
Device: c.Device, Device: c.Device,
@@ -147,6 +126,13 @@ func (l *library) DeviceGetHandleByUUID(uuid string) (Device, Return) {
return device, ret return device, ret
} }
// nvml.DeviceGetHandleByUUIDV()
func (l *library) DeviceGetHandleByUUIDV(uuid *UUID) (Device, Return) {
var device nvmlDevice
ret := nvmlDeviceGetHandleByUUIDV(uuid, &device)
return device, ret
}
// nvml.DeviceGetHandleByPciBusId() // nvml.DeviceGetHandleByPciBusId()
func (l *library) DeviceGetHandleByPciBusId(pciBusId string) (Device, Return) { func (l *library) DeviceGetHandleByPciBusId(pciBusId string) (Device, Return) {
var device nvmlDevice var device nvmlDevice
@@ -2101,6 +2087,13 @@ func (handler GpuInstanceProfileInfoHandler) V2() (GpuInstanceProfileInfo_v2, Re
return info, ret return info, ret
} }
func (handler GpuInstanceProfileInfoHandler) V3() (GpuInstanceProfileInfo_v3, Return) {
var info GpuInstanceProfileInfo_v3
info.Version = STRUCT_VERSION(info, 3)
ret := nvmlDeviceGetGpuInstanceProfileInfoV(handler.device, uint32(handler.profile), (*GpuInstanceProfileInfo_v2)(unsafe.Pointer(&info)))
return info, ret
}
func (l *library) DeviceGetGpuInstanceProfileInfoV(device Device, profile int) GpuInstanceProfileInfoHandler { func (l *library) DeviceGetGpuInstanceProfileInfoV(device Device, profile int) GpuInstanceProfileInfoHandler {
return device.GetGpuInstanceProfileInfoV(profile) return device.GetGpuInstanceProfileInfoV(profile)
} }
@@ -2191,7 +2184,7 @@ func (device nvmlDevice) GetGpuInstances(info *GpuInstanceProfileInfo) ([]GpuIns
if info == nil { if info == nil {
return nil, ERROR_INVALID_ARGUMENT return nil, ERROR_INVALID_ARGUMENT
} }
var count uint32 = info.InstanceCount var count = info.InstanceCount
gpuInstances := make([]nvmlGpuInstance, count) gpuInstances := make([]nvmlGpuInstance, count)
ret := nvmlDeviceGetGpuInstances(device, info.Id, &gpuInstances[0], &count) ret := nvmlDeviceGetGpuInstances(device, info.Id, &gpuInstances[0], &count)
return convertSlice[nvmlGpuInstance, GpuInstance](gpuInstances[:count]), ret return convertSlice[nvmlGpuInstance, GpuInstance](gpuInstances[:count]), ret
@@ -2248,6 +2241,13 @@ func (handler ComputeInstanceProfileInfoHandler) V2() (ComputeInstanceProfileInf
return info, ret return info, ret
} }
func (handler ComputeInstanceProfileInfoHandler) V3() (ComputeInstanceProfileInfo_v3, Return) {
var info ComputeInstanceProfileInfo_v3
info.Version = STRUCT_VERSION(info, 3)
ret := nvmlGpuInstanceGetComputeInstanceProfileInfoV(handler.gpuInstance, uint32(handler.profile), uint32(handler.engProfile), (*ComputeInstanceProfileInfo_v2)(unsafe.Pointer(&info)))
return info, ret
}
func (l *library) GpuInstanceGetComputeInstanceProfileInfoV(gpuInstance GpuInstance, profile int, engProfile int) ComputeInstanceProfileInfoHandler { func (l *library) GpuInstanceGetComputeInstanceProfileInfoV(gpuInstance GpuInstance, profile int, engProfile int) ComputeInstanceProfileInfoHandler {
return gpuInstance.GetComputeInstanceProfileInfoV(profile, engProfile) return gpuInstance.GetComputeInstanceProfileInfoV(profile, engProfile)
} }
@@ -2302,7 +2302,7 @@ func (gpuInstance nvmlGpuInstance) GetComputeInstances(info *ComputeInstanceProf
if info == nil { if info == nil {
return nil, ERROR_INVALID_ARGUMENT return nil, ERROR_INVALID_ARGUMENT
} }
var count uint32 = info.InstanceCount var count = info.InstanceCount
computeInstances := make([]nvmlComputeInstance, count) computeInstances := make([]nvmlComputeInstance, count)
ret := nvmlGpuInstanceGetComputeInstances(gpuInstance, info.Id, &computeInstances[0], &count) ret := nvmlGpuInstanceGetComputeInstances(gpuInstance, info.Id, &computeInstances[0], &count)
return convertSlice[nvmlComputeInstance, ComputeInstance](computeInstances[:count]), ret return convertSlice[nvmlComputeInstance, ComputeInstance](computeInstances[:count]), ret
@@ -3062,3 +3062,353 @@ func (device nvmlDevice) GetSramEccErrorStatus() (EccSramErrorStatus, Return) {
ret := nvmlDeviceGetSramEccErrorStatus(device, &status) ret := nvmlDeviceGetSramEccErrorStatus(device, &status)
return status, ret return status, ret
} }
// nvml.DeviceGetClockOffsets()
func (l *library) DeviceGetClockOffsets(device Device) (ClockOffset, Return) {
return device.GetClockOffsets()
}
func (device nvmlDevice) GetClockOffsets() (ClockOffset, Return) {
var info ClockOffset
info.Version = STRUCT_VERSION(info, 1)
ret := nvmlDeviceGetClockOffsets(device, &info)
return info, ret
}
// nvml.DeviceSetClockOffsets()
func (l *library) DeviceSetClockOffsets(device Device, info ClockOffset) Return {
return device.SetClockOffsets(info)
}
func (device nvmlDevice) SetClockOffsets(info ClockOffset) Return {
return nvmlDeviceSetClockOffsets(device, &info)
}
// nvml.DeviceGetDriverModel_v2()
func (l *library) DeviceGetDriverModel_v2(device Device) (DriverModel, DriverModel, Return) {
return device.GetDriverModel_v2()
}
func (device nvmlDevice) GetDriverModel_v2() (DriverModel, DriverModel, Return) {
var current, pending DriverModel
ret := nvmlDeviceGetDriverModel_v2(device, &current, &pending)
return current, pending, ret
}
// nvml.DeviceGetCapabilities()
func (l *library) DeviceGetCapabilities(device Device) (DeviceCapabilities, Return) {
return device.GetCapabilities()
}
func (device nvmlDevice) GetCapabilities() (DeviceCapabilities, Return) {
var caps DeviceCapabilities
caps.Version = STRUCT_VERSION(caps, 1)
ret := nvmlDeviceGetCapabilities(device, &caps)
return caps, ret
}
// nvml.DeviceGetFanSpeedRPM()
func (l *library) DeviceGetFanSpeedRPM(device Device) (FanSpeedInfo, Return) {
return device.GetFanSpeedRPM()
}
func (device nvmlDevice) GetFanSpeedRPM() (FanSpeedInfo, Return) {
var fanSpeed FanSpeedInfo
fanSpeed.Version = STRUCT_VERSION(fanSpeed, 1)
ret := nvmlDeviceGetFanSpeedRPM(device, &fanSpeed)
return fanSpeed, ret
}
// nvml.DeviceGetCoolerInfo()
func (l *library) DeviceGetCoolerInfo(device Device) (CoolerInfo, Return) {
return device.GetCoolerInfo()
}
func (device nvmlDevice) GetCoolerInfo() (CoolerInfo, Return) {
var coolerInfo CoolerInfo
coolerInfo.Version = STRUCT_VERSION(coolerInfo, 1)
ret := nvmlDeviceGetCoolerInfo(device, &coolerInfo)
return coolerInfo, ret
}
// nvml.DeviceGetTemperatureV()
type TemperatureHandler struct {
device nvmlDevice
}
func (handler TemperatureHandler) V1() (Temperature, Return) {
var temperature Temperature
temperature.Version = STRUCT_VERSION(temperature, 1)
ret := nvmlDeviceGetTemperatureV(handler.device, &temperature)
return temperature, ret
}
func (l *library) DeviceGetTemperatureV(device Device) TemperatureHandler {
return device.GetTemperatureV()
}
func (device nvmlDevice) GetTemperatureV() TemperatureHandler {
return TemperatureHandler{device}
}
// nvml.DeviceGetMarginTemperature()
func (l *library) DeviceGetMarginTemperature(device Device) (MarginTemperature, Return) {
return device.GetMarginTemperature()
}
func (device nvmlDevice) GetMarginTemperature() (MarginTemperature, Return) {
var marginTemp MarginTemperature
marginTemp.Version = STRUCT_VERSION(marginTemp, 1)
ret := nvmlDeviceGetMarginTemperature(device, &marginTemp)
return marginTemp, ret
}
// nvml.DeviceGetPerformanceModes()
func (l *library) DeviceGetPerformanceModes(device Device) (DevicePerfModes, Return) {
return device.GetPerformanceModes()
}
func (device nvmlDevice) GetPerformanceModes() (DevicePerfModes, Return) {
var perfModes DevicePerfModes
perfModes.Version = STRUCT_VERSION(perfModes, 1)
ret := nvmlDeviceGetPerformanceModes(device, &perfModes)
return perfModes, ret
}
// nvml.DeviceGetCurrentClockFreqs()
func (l *library) DeviceGetCurrentClockFreqs(device Device) (DeviceCurrentClockFreqs, Return) {
return device.GetCurrentClockFreqs()
}
func (device nvmlDevice) GetCurrentClockFreqs() (DeviceCurrentClockFreqs, Return) {
var currentClockFreqs DeviceCurrentClockFreqs
currentClockFreqs.Version = STRUCT_VERSION(currentClockFreqs, 1)
ret := nvmlDeviceGetCurrentClockFreqs(device, &currentClockFreqs)
return currentClockFreqs, ret
}
// nvml.DeviceGetDramEncryptionMode()
func (l *library) DeviceGetDramEncryptionMode(device Device) (DramEncryptionInfo, DramEncryptionInfo, Return) {
return device.GetDramEncryptionMode()
}
func (device nvmlDevice) GetDramEncryptionMode() (DramEncryptionInfo, DramEncryptionInfo, Return) {
var current, pending DramEncryptionInfo
current.Version = STRUCT_VERSION(current, 1)
pending.Version = STRUCT_VERSION(pending, 1)
ret := nvmlDeviceGetDramEncryptionMode(device, &current, &pending)
return current, pending, ret
}
// nvml.DeviceSetDramEncryptionMode()
func (l *library) DeviceSetDramEncryptionMode(device Device, dramEncryption *DramEncryptionInfo) Return {
return device.SetDramEncryptionMode(dramEncryption)
}
func (device nvmlDevice) SetDramEncryptionMode(dramEncryption *DramEncryptionInfo) Return {
return nvmlDeviceSetDramEncryptionMode(device, dramEncryption)
}
// nvml.DeviceGetPlatformInfo()
func (l *library) DeviceGetPlatformInfo(device Device) (PlatformInfo, Return) {
return device.GetPlatformInfo()
}
func (device nvmlDevice) GetPlatformInfo() (PlatformInfo, Return) {
var platformInfo PlatformInfo
platformInfo.Version = STRUCT_VERSION(platformInfo, 1)
ret := nvmlDeviceGetPlatformInfo(device, &platformInfo)
return platformInfo, ret
}
// nvml.DeviceGetNvlinkSupportedBwModes()
func (l *library) DeviceGetNvlinkSupportedBwModes(device Device) (NvlinkSupportedBwModes, Return) {
return device.GetNvlinkSupportedBwModes()
}
func (device nvmlDevice) GetNvlinkSupportedBwModes() (NvlinkSupportedBwModes, Return) {
var supportedBwMode NvlinkSupportedBwModes
supportedBwMode.Version = STRUCT_VERSION(supportedBwMode, 1)
ret := nvmlDeviceGetNvlinkSupportedBwModes(device, &supportedBwMode)
return supportedBwMode, ret
}
// nvml.DeviceGetNvlinkBwMode()
func (l *library) DeviceGetNvlinkBwMode(device Device) (NvlinkGetBwMode, Return) {
return device.GetNvlinkBwMode()
}
func (device nvmlDevice) GetNvlinkBwMode() (NvlinkGetBwMode, Return) {
var getBwMode NvlinkGetBwMode
getBwMode.Version = STRUCT_VERSION(getBwMode, 1)
ret := nvmlDeviceGetNvlinkBwMode(device, &getBwMode)
return getBwMode, ret
}
// nvml.DeviceSetNvlinkBwMode()
func (l *library) DeviceSetNvlinkBwMode(device Device, setBwMode *NvlinkSetBwMode) Return {
return device.SetNvlinkBwMode(setBwMode)
}
func (device nvmlDevice) SetNvlinkBwMode(setBwMode *NvlinkSetBwMode) Return {
return nvmlDeviceSetNvlinkBwMode(device, setBwMode)
}
// nvml.DeviceWorkloadPowerProfileGetProfilesInfo()
func (l *library) DeviceWorkloadPowerProfileGetProfilesInfo(device Device) (WorkloadPowerProfileProfilesInfo, Return) {
return device.WorkloadPowerProfileGetProfilesInfo()
}
func (device nvmlDevice) WorkloadPowerProfileGetProfilesInfo() (WorkloadPowerProfileProfilesInfo, Return) {
var profilesInfo WorkloadPowerProfileProfilesInfo
profilesInfo.Version = STRUCT_VERSION(profilesInfo, 1)
ret := nvmlDeviceWorkloadPowerProfileGetProfilesInfo(device, &profilesInfo)
return profilesInfo, ret
}
// nvml.DeviceWorkloadPowerProfileGetCurrentProfiles()
func (l *library) DeviceWorkloadPowerProfileGetCurrentProfiles(device Device) (WorkloadPowerProfileCurrentProfiles, Return) {
return device.WorkloadPowerProfileGetCurrentProfiles()
}
func (device nvmlDevice) WorkloadPowerProfileGetCurrentProfiles() (WorkloadPowerProfileCurrentProfiles, Return) {
var currentProfiles WorkloadPowerProfileCurrentProfiles
currentProfiles.Version = STRUCT_VERSION(currentProfiles, 1)
ret := nvmlDeviceWorkloadPowerProfileGetCurrentProfiles(device, &currentProfiles)
return currentProfiles, ret
}
// nvml.DeviceWorkloadPowerProfileSetRequestedProfiles()
func (l *library) DeviceWorkloadPowerProfileSetRequestedProfiles(device Device, requestedProfiles *WorkloadPowerProfileRequestedProfiles) Return {
return device.WorkloadPowerProfileSetRequestedProfiles(requestedProfiles)
}
func (device nvmlDevice) WorkloadPowerProfileSetRequestedProfiles(requestedProfiles *WorkloadPowerProfileRequestedProfiles) Return {
return nvmlDeviceWorkloadPowerProfileSetRequestedProfiles(device, requestedProfiles)
}
// nvml.DeviceWorkloadPowerProfileClearRequestedProfiles()
func (l *library) DeviceWorkloadPowerProfileClearRequestedProfiles(device Device, requestedProfiles *WorkloadPowerProfileRequestedProfiles) Return {
return device.WorkloadPowerProfileClearRequestedProfiles(requestedProfiles)
}
func (device nvmlDevice) WorkloadPowerProfileClearRequestedProfiles(requestedProfiles *WorkloadPowerProfileRequestedProfiles) Return {
return nvmlDeviceWorkloadPowerProfileClearRequestedProfiles(device, requestedProfiles)
}
// nvml.DevicePowerSmoothingActivatePresetProfile()
func (l *library) DevicePowerSmoothingActivatePresetProfile(device Device, profile *PowerSmoothingProfile) Return {
return device.PowerSmoothingActivatePresetProfile(profile)
}
func (device nvmlDevice) PowerSmoothingActivatePresetProfile(profile *PowerSmoothingProfile) Return {
return nvmlDevicePowerSmoothingActivatePresetProfile(device, profile)
}
// nvml.DevicePowerSmoothingUpdatePresetProfileParam()
func (l *library) DevicePowerSmoothingUpdatePresetProfileParam(device Device, profile *PowerSmoothingProfile) Return {
return device.PowerSmoothingUpdatePresetProfileParam(profile)
}
func (device nvmlDevice) PowerSmoothingUpdatePresetProfileParam(profile *PowerSmoothingProfile) Return {
return nvmlDevicePowerSmoothingUpdatePresetProfileParam(device, profile)
}
// nvml.DevicePowerSmoothingSetState()
func (l *library) DevicePowerSmoothingSetState(device Device, state *PowerSmoothingState) Return {
return device.PowerSmoothingSetState(state)
}
func (device nvmlDevice) PowerSmoothingSetState(state *PowerSmoothingState) Return {
return nvmlDevicePowerSmoothingSetState(device, state)
}
// nvml.GpuInstanceGetCreatableVgpus()
func (l *library) GpuInstanceGetCreatableVgpus(gpuInstance GpuInstance) (VgpuTypeIdInfo, Return) {
return gpuInstance.GetCreatableVgpus()
}
func (gpuInstance nvmlGpuInstance) GetCreatableVgpus() (VgpuTypeIdInfo, Return) {
var vgpuTypeIdInfo VgpuTypeIdInfo
vgpuTypeIdInfo.Version = STRUCT_VERSION(vgpuTypeIdInfo, 1)
ret := nvmlGpuInstanceGetCreatableVgpus(gpuInstance, &vgpuTypeIdInfo)
return vgpuTypeIdInfo, ret
}
// nvml.GpuInstanceGetActiveVgpus()
func (l *library) GpuInstanceGetActiveVgpus(gpuInstance GpuInstance) (ActiveVgpuInstanceInfo, Return) {
return gpuInstance.GetActiveVgpus()
}
func (gpuInstance nvmlGpuInstance) GetActiveVgpus() (ActiveVgpuInstanceInfo, Return) {
var activeVgpuInstanceInfo ActiveVgpuInstanceInfo
activeVgpuInstanceInfo.Version = STRUCT_VERSION(activeVgpuInstanceInfo, 1)
ret := nvmlGpuInstanceGetActiveVgpus(gpuInstance, &activeVgpuInstanceInfo)
return activeVgpuInstanceInfo, ret
}
// nvml.GpuInstanceSetVgpuSchedulerState()
func (l *library) GpuInstanceSetVgpuSchedulerState(gpuInstance GpuInstance, scheduler *VgpuSchedulerState) Return {
return gpuInstance.SetVgpuSchedulerState(scheduler)
}
func (gpuInstance nvmlGpuInstance) SetVgpuSchedulerState(scheduler *VgpuSchedulerState) Return {
return nvmlGpuInstanceSetVgpuSchedulerState(gpuInstance, scheduler)
}
// nvml.GpuInstanceGetVgpuSchedulerState()
func (l *library) GpuInstanceGetVgpuSchedulerState(gpuInstance GpuInstance) (VgpuSchedulerStateInfo, Return) {
return gpuInstance.GetVgpuSchedulerState()
}
func (gpuInstance nvmlGpuInstance) GetVgpuSchedulerState() (VgpuSchedulerStateInfo, Return) {
var schedulerStateInfo VgpuSchedulerStateInfo
schedulerStateInfo.Version = STRUCT_VERSION(schedulerStateInfo, 1)
ret := nvmlGpuInstanceGetVgpuSchedulerState(gpuInstance, &schedulerStateInfo)
return schedulerStateInfo, ret
}
// nvml.GpuInstanceGetVgpuSchedulerLog()
func (l *library) GpuInstanceGetVgpuSchedulerLog(gpuInstance GpuInstance) (VgpuSchedulerLogInfo, Return) {
return gpuInstance.GetVgpuSchedulerLog()
}
func (gpuInstance nvmlGpuInstance) GetVgpuSchedulerLog() (VgpuSchedulerLogInfo, Return) {
var schedulerLogInfo VgpuSchedulerLogInfo
schedulerLogInfo.Version = STRUCT_VERSION(schedulerLogInfo, 1)
ret := nvmlGpuInstanceGetVgpuSchedulerLog(gpuInstance, &schedulerLogInfo)
return schedulerLogInfo, ret
}
// nvml.GpuInstanceGetVgpuTypeCreatablePlacements()
func (l *library) GpuInstanceGetVgpuTypeCreatablePlacements(gpuInstance GpuInstance) (VgpuCreatablePlacementInfo, Return) {
return gpuInstance.GetVgpuTypeCreatablePlacements()
}
func (gpuInstance nvmlGpuInstance) GetVgpuTypeCreatablePlacements() (VgpuCreatablePlacementInfo, Return) {
var creatablePlacementInfo VgpuCreatablePlacementInfo
creatablePlacementInfo.Version = STRUCT_VERSION(creatablePlacementInfo, 1)
ret := nvmlGpuInstanceGetVgpuTypeCreatablePlacements(gpuInstance, &creatablePlacementInfo)
return creatablePlacementInfo, ret
}
// nvml.GpuInstanceGetVgpuHeterogeneousMode()
func (l *library) GpuInstanceGetVgpuHeterogeneousMode(gpuInstance GpuInstance) (VgpuHeterogeneousMode, Return) {
return gpuInstance.GetVgpuHeterogeneousMode()
}
func (gpuInstance nvmlGpuInstance) GetVgpuHeterogeneousMode() (VgpuHeterogeneousMode, Return) {
var heterogeneousMode VgpuHeterogeneousMode
heterogeneousMode.Version = STRUCT_VERSION(heterogeneousMode, 1)
ret := nvmlGpuInstanceGetVgpuHeterogeneousMode(gpuInstance, &heterogeneousMode)
return heterogeneousMode, ret
}
// nvml.GpuInstanceSetVgpuHeterogeneousMode()
func (l *library) GpuInstanceSetVgpuHeterogeneousMode(gpuInstance GpuInstance, heterogeneousMode *VgpuHeterogeneousMode) Return {
return gpuInstance.SetVgpuHeterogeneousMode(heterogeneousMode)
}
func (gpuInstance nvmlGpuInstance) SetVgpuHeterogeneousMode(heterogeneousMode *VgpuHeterogeneousMode) Return {
return nvmlGpuInstanceSetVgpuHeterogeneousMode(gpuInstance, heterogeneousMode)
}

View File

@@ -23,17 +23,6 @@ type EventData struct {
ComputeInstanceId uint32 ComputeInstanceId uint32
} }
func (e EventData) convert() nvmlEventData {
out := nvmlEventData{
Device: e.Device.(nvmlDevice),
EventType: e.EventType,
EventData: e.EventData,
GpuInstanceId: e.GpuInstanceId,
ComputeInstanceId: e.ComputeInstanceId,
}
return out
}
func (e nvmlEventData) convert() EventData { func (e nvmlEventData) convert() EventData {
out := EventData{ out := EventData{
Device: e.Device, Device: e.Device,
@@ -71,3 +60,23 @@ func (l *library) EventSetFree(set EventSet) Return {
func (set nvmlEventSet) Free() Return { func (set nvmlEventSet) Free() Return {
return nvmlEventSetFree(set) return nvmlEventSetFree(set)
} }
// nvml.SystemEventSetCreate()
func (l *library) SystemEventSetCreate(request *SystemEventSetCreateRequest) Return {
return nvmlSystemEventSetCreate(request)
}
// nvml.SystemEventSetFree()
func (l *library) SystemEventSetFree(request *SystemEventSetFreeRequest) Return {
return nvmlSystemEventSetFree(request)
}
// nvml.SystemRegisterEvents()
func (l *library) SystemRegisterEvents(request *SystemRegisterEventRequest) Return {
return nvmlSystemRegisterEvents(request)
}
// nvml.SystemEventSetWait()
func (l *library) SystemEventSetWait(request *SystemEventSetWaitRequest) Return {
return nvmlSystemEventSetWait(request)
}

View File

@@ -20,7 +20,7 @@ type GpmMetricsGetType struct {
NumMetrics uint32 NumMetrics uint32
Sample1 GpmSample Sample1 GpmSample
Sample2 GpmSample Sample2 GpmSample
Metrics [98]GpmMetric Metrics [210]GpmMetric
} }
func (g *GpmMetricsGetType) convert() *nvmlGpmMetricsGetType { func (g *GpmMetricsGetType) convert() *nvmlGpmMetricsGetType {
@@ -30,9 +30,8 @@ func (g *GpmMetricsGetType) convert() *nvmlGpmMetricsGetType {
Sample1: g.Sample1.(nvmlGpmSample), Sample1: g.Sample1.(nvmlGpmSample),
Sample2: g.Sample2.(nvmlGpmSample), Sample2: g.Sample2.(nvmlGpmSample),
} }
for i := range g.Metrics { copy(out.Metrics[:], g.Metrics[:])
out.Metrics[i] = g.Metrics[i]
}
return out return out
} }
@@ -43,9 +42,8 @@ func (g *nvmlGpmMetricsGetType) convert() *GpmMetricsGetType {
Sample1: g.Sample1, Sample1: g.Sample1,
Sample2: g.Sample2, Sample2: g.Sample2,
} }
for i := range g.Metrics { copy(out.Metrics[:], g.Metrics[:])
out.Metrics[i] = g.Metrics[i]
}
return out return out
} }

View File

@@ -163,6 +163,7 @@ var GetBlacklistDeviceCount = GetExcludedDeviceCount
var GetBlacklistDeviceInfoByIndex = GetExcludedDeviceInfoByIndex var GetBlacklistDeviceInfoByIndex = GetExcludedDeviceInfoByIndex
var nvmlDeviceGetGpuInstancePossiblePlacements = nvmlDeviceGetGpuInstancePossiblePlacements_v1 var nvmlDeviceGetGpuInstancePossiblePlacements = nvmlDeviceGetGpuInstancePossiblePlacements_v1
var nvmlVgpuInstanceGetLicenseInfo = nvmlVgpuInstanceGetLicenseInfo_v1 var nvmlVgpuInstanceGetLicenseInfo = nvmlVgpuInstanceGetLicenseInfo_v1
var nvmlDeviceGetDriverModel = nvmlDeviceGetDriverModel_v1
// BlacklistDeviceInfo was replaced by ExcludedDeviceInfo // BlacklistDeviceInfo was replaced by ExcludedDeviceInfo
type BlacklistDeviceInfo = ExcludedDeviceInfo type BlacklistDeviceInfo = ExcludedDeviceInfo
@@ -288,4 +289,8 @@ func (l *library) updateVersionedSymbols() {
if err == nil { if err == nil {
nvmlVgpuInstanceGetLicenseInfo = nvmlVgpuInstanceGetLicenseInfo_v2 nvmlVgpuInstanceGetLicenseInfo = nvmlVgpuInstanceGetLicenseInfo_v2
} }
err = l.dl.Lookup("nvmlDeviceGetDriverModel_v2")
if err == nil {
nvmlDeviceGetDriverModel = nvmlDeviceGetDriverModel_v2
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -20,9 +20,10 @@ import (
"fmt" "fmt"
"sync" "sync"
"github.com/google/uuid"
"github.com/NVIDIA/go-nvml/pkg/nvml" "github.com/NVIDIA/go-nvml/pkg/nvml"
"github.com/NVIDIA/go-nvml/pkg/nvml/mock" "github.com/NVIDIA/go-nvml/pkg/nvml/mock"
"github.com/google/uuid"
) )
type Server struct { type Server struct {
@@ -108,7 +109,7 @@ func NewDevice(index int) *Device {
}, },
GpuInstances: make(map[*GpuInstance]struct{}), GpuInstances: make(map[*GpuInstance]struct{}),
GpuInstanceCounter: 0, GpuInstanceCounter: 0,
MemoryInfo: nvml.Memory{42949672960, 0, 0}, MemoryInfo: nvml.Memory{Total: 42949672960, Free: 0, Used: 0},
} }
device.setMockFuncs() device.setMockFuncs()
return device return device

View File

@@ -27,6 +27,9 @@ var _ nvml.GpuInstance = &GpuInstance{}
// DestroyFunc: func() nvml.Return { // DestroyFunc: func() nvml.Return {
// panic("mock out the Destroy method") // panic("mock out the Destroy method")
// }, // },
// GetActiveVgpusFunc: func() (nvml.ActiveVgpuInstanceInfo, nvml.Return) {
// panic("mock out the GetActiveVgpus method")
// },
// GetComputeInstanceByIdFunc: func(n int) (nvml.ComputeInstance, nvml.Return) { // GetComputeInstanceByIdFunc: func(n int) (nvml.ComputeInstance, nvml.Return) {
// panic("mock out the GetComputeInstanceById method") // panic("mock out the GetComputeInstanceById method")
// }, // },
@@ -45,9 +48,30 @@ var _ nvml.GpuInstance = &GpuInstance{}
// GetComputeInstancesFunc: func(computeInstanceProfileInfo *nvml.ComputeInstanceProfileInfo) ([]nvml.ComputeInstance, nvml.Return) { // GetComputeInstancesFunc: func(computeInstanceProfileInfo *nvml.ComputeInstanceProfileInfo) ([]nvml.ComputeInstance, nvml.Return) {
// panic("mock out the GetComputeInstances method") // panic("mock out the GetComputeInstances method")
// }, // },
// GetCreatableVgpusFunc: func() (nvml.VgpuTypeIdInfo, nvml.Return) {
// panic("mock out the GetCreatableVgpus method")
// },
// GetInfoFunc: func() (nvml.GpuInstanceInfo, nvml.Return) { // GetInfoFunc: func() (nvml.GpuInstanceInfo, nvml.Return) {
// panic("mock out the GetInfo method") // panic("mock out the GetInfo method")
// }, // },
// GetVgpuHeterogeneousModeFunc: func() (nvml.VgpuHeterogeneousMode, nvml.Return) {
// panic("mock out the GetVgpuHeterogeneousMode method")
// },
// GetVgpuSchedulerLogFunc: func() (nvml.VgpuSchedulerLogInfo, nvml.Return) {
// panic("mock out the GetVgpuSchedulerLog method")
// },
// GetVgpuSchedulerStateFunc: func() (nvml.VgpuSchedulerStateInfo, nvml.Return) {
// panic("mock out the GetVgpuSchedulerState method")
// },
// GetVgpuTypeCreatablePlacementsFunc: func() (nvml.VgpuCreatablePlacementInfo, nvml.Return) {
// panic("mock out the GetVgpuTypeCreatablePlacements method")
// },
// SetVgpuHeterogeneousModeFunc: func(vgpuHeterogeneousMode *nvml.VgpuHeterogeneousMode) nvml.Return {
// panic("mock out the SetVgpuHeterogeneousMode method")
// },
// SetVgpuSchedulerStateFunc: func(vgpuSchedulerState *nvml.VgpuSchedulerState) nvml.Return {
// panic("mock out the SetVgpuSchedulerState method")
// },
// } // }
// //
// // use mockedGpuInstance in code that requires nvml.GpuInstance // // use mockedGpuInstance in code that requires nvml.GpuInstance
@@ -64,6 +88,9 @@ type GpuInstance struct {
// DestroyFunc mocks the Destroy method. // DestroyFunc mocks the Destroy method.
DestroyFunc func() nvml.Return DestroyFunc func() nvml.Return
// GetActiveVgpusFunc mocks the GetActiveVgpus method.
GetActiveVgpusFunc func() (nvml.ActiveVgpuInstanceInfo, nvml.Return)
// GetComputeInstanceByIdFunc mocks the GetComputeInstanceById method. // GetComputeInstanceByIdFunc mocks the GetComputeInstanceById method.
GetComputeInstanceByIdFunc func(n int) (nvml.ComputeInstance, nvml.Return) GetComputeInstanceByIdFunc func(n int) (nvml.ComputeInstance, nvml.Return)
@@ -82,9 +109,30 @@ type GpuInstance struct {
// GetComputeInstancesFunc mocks the GetComputeInstances method. // GetComputeInstancesFunc mocks the GetComputeInstances method.
GetComputeInstancesFunc func(computeInstanceProfileInfo *nvml.ComputeInstanceProfileInfo) ([]nvml.ComputeInstance, nvml.Return) GetComputeInstancesFunc func(computeInstanceProfileInfo *nvml.ComputeInstanceProfileInfo) ([]nvml.ComputeInstance, nvml.Return)
// GetCreatableVgpusFunc mocks the GetCreatableVgpus method.
GetCreatableVgpusFunc func() (nvml.VgpuTypeIdInfo, nvml.Return)
// GetInfoFunc mocks the GetInfo method. // GetInfoFunc mocks the GetInfo method.
GetInfoFunc func() (nvml.GpuInstanceInfo, nvml.Return) GetInfoFunc func() (nvml.GpuInstanceInfo, nvml.Return)
// GetVgpuHeterogeneousModeFunc mocks the GetVgpuHeterogeneousMode method.
GetVgpuHeterogeneousModeFunc func() (nvml.VgpuHeterogeneousMode, nvml.Return)
// GetVgpuSchedulerLogFunc mocks the GetVgpuSchedulerLog method.
GetVgpuSchedulerLogFunc func() (nvml.VgpuSchedulerLogInfo, nvml.Return)
// GetVgpuSchedulerStateFunc mocks the GetVgpuSchedulerState method.
GetVgpuSchedulerStateFunc func() (nvml.VgpuSchedulerStateInfo, nvml.Return)
// GetVgpuTypeCreatablePlacementsFunc mocks the GetVgpuTypeCreatablePlacements method.
GetVgpuTypeCreatablePlacementsFunc func() (nvml.VgpuCreatablePlacementInfo, nvml.Return)
// SetVgpuHeterogeneousModeFunc mocks the SetVgpuHeterogeneousMode method.
SetVgpuHeterogeneousModeFunc func(vgpuHeterogeneousMode *nvml.VgpuHeterogeneousMode) nvml.Return
// SetVgpuSchedulerStateFunc mocks the SetVgpuSchedulerState method.
SetVgpuSchedulerStateFunc func(vgpuSchedulerState *nvml.VgpuSchedulerState) nvml.Return
// calls tracks calls to the methods. // calls tracks calls to the methods.
calls struct { calls struct {
// CreateComputeInstance holds details about calls to the CreateComputeInstance method. // CreateComputeInstance holds details about calls to the CreateComputeInstance method.
@@ -102,6 +150,9 @@ type GpuInstance struct {
// Destroy holds details about calls to the Destroy method. // Destroy holds details about calls to the Destroy method.
Destroy []struct { Destroy []struct {
} }
// GetActiveVgpus holds details about calls to the GetActiveVgpus method.
GetActiveVgpus []struct {
}
// GetComputeInstanceById holds details about calls to the GetComputeInstanceById method. // GetComputeInstanceById holds details about calls to the GetComputeInstanceById method.
GetComputeInstanceById []struct { GetComputeInstanceById []struct {
// N is the n argument value. // N is the n argument value.
@@ -136,20 +187,53 @@ type GpuInstance struct {
// ComputeInstanceProfileInfo is the computeInstanceProfileInfo argument value. // ComputeInstanceProfileInfo is the computeInstanceProfileInfo argument value.
ComputeInstanceProfileInfo *nvml.ComputeInstanceProfileInfo ComputeInstanceProfileInfo *nvml.ComputeInstanceProfileInfo
} }
// GetCreatableVgpus holds details about calls to the GetCreatableVgpus method.
GetCreatableVgpus []struct {
}
// GetInfo holds details about calls to the GetInfo method. // GetInfo holds details about calls to the GetInfo method.
GetInfo []struct { GetInfo []struct {
} }
// GetVgpuHeterogeneousMode holds details about calls to the GetVgpuHeterogeneousMode method.
GetVgpuHeterogeneousMode []struct {
}
// GetVgpuSchedulerLog holds details about calls to the GetVgpuSchedulerLog method.
GetVgpuSchedulerLog []struct {
}
// GetVgpuSchedulerState holds details about calls to the GetVgpuSchedulerState method.
GetVgpuSchedulerState []struct {
}
// GetVgpuTypeCreatablePlacements holds details about calls to the GetVgpuTypeCreatablePlacements method.
GetVgpuTypeCreatablePlacements []struct {
}
// SetVgpuHeterogeneousMode holds details about calls to the SetVgpuHeterogeneousMode method.
SetVgpuHeterogeneousMode []struct {
// VgpuHeterogeneousMode is the vgpuHeterogeneousMode argument value.
VgpuHeterogeneousMode *nvml.VgpuHeterogeneousMode
}
// SetVgpuSchedulerState holds details about calls to the SetVgpuSchedulerState method.
SetVgpuSchedulerState []struct {
// VgpuSchedulerState is the vgpuSchedulerState argument value.
VgpuSchedulerState *nvml.VgpuSchedulerState
}
} }
lockCreateComputeInstance sync.RWMutex lockCreateComputeInstance sync.RWMutex
lockCreateComputeInstanceWithPlacement sync.RWMutex lockCreateComputeInstanceWithPlacement sync.RWMutex
lockDestroy sync.RWMutex lockDestroy sync.RWMutex
lockGetActiveVgpus sync.RWMutex
lockGetComputeInstanceById sync.RWMutex lockGetComputeInstanceById sync.RWMutex
lockGetComputeInstancePossiblePlacements sync.RWMutex lockGetComputeInstancePossiblePlacements sync.RWMutex
lockGetComputeInstanceProfileInfo sync.RWMutex lockGetComputeInstanceProfileInfo sync.RWMutex
lockGetComputeInstanceProfileInfoV sync.RWMutex lockGetComputeInstanceProfileInfoV sync.RWMutex
lockGetComputeInstanceRemainingCapacity sync.RWMutex lockGetComputeInstanceRemainingCapacity sync.RWMutex
lockGetComputeInstances sync.RWMutex lockGetComputeInstances sync.RWMutex
lockGetCreatableVgpus sync.RWMutex
lockGetInfo sync.RWMutex lockGetInfo sync.RWMutex
lockGetVgpuHeterogeneousMode sync.RWMutex
lockGetVgpuSchedulerLog sync.RWMutex
lockGetVgpuSchedulerState sync.RWMutex
lockGetVgpuTypeCreatablePlacements sync.RWMutex
lockSetVgpuHeterogeneousMode sync.RWMutex
lockSetVgpuSchedulerState sync.RWMutex
} }
// CreateComputeInstance calls CreateComputeInstanceFunc. // CreateComputeInstance calls CreateComputeInstanceFunc.
@@ -247,6 +331,33 @@ func (mock *GpuInstance) DestroyCalls() []struct {
return calls return calls
} }
// GetActiveVgpus calls GetActiveVgpusFunc.
func (mock *GpuInstance) GetActiveVgpus() (nvml.ActiveVgpuInstanceInfo, nvml.Return) {
if mock.GetActiveVgpusFunc == nil {
panic("GpuInstance.GetActiveVgpusFunc: method is nil but GpuInstance.GetActiveVgpus was just called")
}
callInfo := struct {
}{}
mock.lockGetActiveVgpus.Lock()
mock.calls.GetActiveVgpus = append(mock.calls.GetActiveVgpus, callInfo)
mock.lockGetActiveVgpus.Unlock()
return mock.GetActiveVgpusFunc()
}
// GetActiveVgpusCalls gets all the calls that were made to GetActiveVgpus.
// Check the length with:
//
// len(mockedGpuInstance.GetActiveVgpusCalls())
func (mock *GpuInstance) GetActiveVgpusCalls() []struct {
} {
var calls []struct {
}
mock.lockGetActiveVgpus.RLock()
calls = mock.calls.GetActiveVgpus
mock.lockGetActiveVgpus.RUnlock()
return calls
}
// GetComputeInstanceById calls GetComputeInstanceByIdFunc. // GetComputeInstanceById calls GetComputeInstanceByIdFunc.
func (mock *GpuInstance) GetComputeInstanceById(n int) (nvml.ComputeInstance, nvml.Return) { func (mock *GpuInstance) GetComputeInstanceById(n int) (nvml.ComputeInstance, nvml.Return) {
if mock.GetComputeInstanceByIdFunc == nil { if mock.GetComputeInstanceByIdFunc == nil {
@@ -447,6 +558,33 @@ func (mock *GpuInstance) GetComputeInstancesCalls() []struct {
return calls return calls
} }
// GetCreatableVgpus calls GetCreatableVgpusFunc.
func (mock *GpuInstance) GetCreatableVgpus() (nvml.VgpuTypeIdInfo, nvml.Return) {
if mock.GetCreatableVgpusFunc == nil {
panic("GpuInstance.GetCreatableVgpusFunc: method is nil but GpuInstance.GetCreatableVgpus was just called")
}
callInfo := struct {
}{}
mock.lockGetCreatableVgpus.Lock()
mock.calls.GetCreatableVgpus = append(mock.calls.GetCreatableVgpus, callInfo)
mock.lockGetCreatableVgpus.Unlock()
return mock.GetCreatableVgpusFunc()
}
// GetCreatableVgpusCalls gets all the calls that were made to GetCreatableVgpus.
// Check the length with:
//
// len(mockedGpuInstance.GetCreatableVgpusCalls())
func (mock *GpuInstance) GetCreatableVgpusCalls() []struct {
} {
var calls []struct {
}
mock.lockGetCreatableVgpus.RLock()
calls = mock.calls.GetCreatableVgpus
mock.lockGetCreatableVgpus.RUnlock()
return calls
}
// GetInfo calls GetInfoFunc. // GetInfo calls GetInfoFunc.
func (mock *GpuInstance) GetInfo() (nvml.GpuInstanceInfo, nvml.Return) { func (mock *GpuInstance) GetInfo() (nvml.GpuInstanceInfo, nvml.Return) {
if mock.GetInfoFunc == nil { if mock.GetInfoFunc == nil {
@@ -473,3 +611,175 @@ func (mock *GpuInstance) GetInfoCalls() []struct {
mock.lockGetInfo.RUnlock() mock.lockGetInfo.RUnlock()
return calls return calls
} }
// GetVgpuHeterogeneousMode calls GetVgpuHeterogeneousModeFunc.
func (mock *GpuInstance) GetVgpuHeterogeneousMode() (nvml.VgpuHeterogeneousMode, nvml.Return) {
if mock.GetVgpuHeterogeneousModeFunc == nil {
panic("GpuInstance.GetVgpuHeterogeneousModeFunc: method is nil but GpuInstance.GetVgpuHeterogeneousMode was just called")
}
callInfo := struct {
}{}
mock.lockGetVgpuHeterogeneousMode.Lock()
mock.calls.GetVgpuHeterogeneousMode = append(mock.calls.GetVgpuHeterogeneousMode, callInfo)
mock.lockGetVgpuHeterogeneousMode.Unlock()
return mock.GetVgpuHeterogeneousModeFunc()
}
// GetVgpuHeterogeneousModeCalls gets all the calls that were made to GetVgpuHeterogeneousMode.
// Check the length with:
//
// len(mockedGpuInstance.GetVgpuHeterogeneousModeCalls())
func (mock *GpuInstance) GetVgpuHeterogeneousModeCalls() []struct {
} {
var calls []struct {
}
mock.lockGetVgpuHeterogeneousMode.RLock()
calls = mock.calls.GetVgpuHeterogeneousMode
mock.lockGetVgpuHeterogeneousMode.RUnlock()
return calls
}
// GetVgpuSchedulerLog calls GetVgpuSchedulerLogFunc.
func (mock *GpuInstance) GetVgpuSchedulerLog() (nvml.VgpuSchedulerLogInfo, nvml.Return) {
if mock.GetVgpuSchedulerLogFunc == nil {
panic("GpuInstance.GetVgpuSchedulerLogFunc: method is nil but GpuInstance.GetVgpuSchedulerLog was just called")
}
callInfo := struct {
}{}
mock.lockGetVgpuSchedulerLog.Lock()
mock.calls.GetVgpuSchedulerLog = append(mock.calls.GetVgpuSchedulerLog, callInfo)
mock.lockGetVgpuSchedulerLog.Unlock()
return mock.GetVgpuSchedulerLogFunc()
}
// GetVgpuSchedulerLogCalls gets all the calls that were made to GetVgpuSchedulerLog.
// Check the length with:
//
// len(mockedGpuInstance.GetVgpuSchedulerLogCalls())
func (mock *GpuInstance) GetVgpuSchedulerLogCalls() []struct {
} {
var calls []struct {
}
mock.lockGetVgpuSchedulerLog.RLock()
calls = mock.calls.GetVgpuSchedulerLog
mock.lockGetVgpuSchedulerLog.RUnlock()
return calls
}
// GetVgpuSchedulerState calls GetVgpuSchedulerStateFunc.
func (mock *GpuInstance) GetVgpuSchedulerState() (nvml.VgpuSchedulerStateInfo, nvml.Return) {
if mock.GetVgpuSchedulerStateFunc == nil {
panic("GpuInstance.GetVgpuSchedulerStateFunc: method is nil but GpuInstance.GetVgpuSchedulerState was just called")
}
callInfo := struct {
}{}
mock.lockGetVgpuSchedulerState.Lock()
mock.calls.GetVgpuSchedulerState = append(mock.calls.GetVgpuSchedulerState, callInfo)
mock.lockGetVgpuSchedulerState.Unlock()
return mock.GetVgpuSchedulerStateFunc()
}
// GetVgpuSchedulerStateCalls gets all the calls that were made to GetVgpuSchedulerState.
// Check the length with:
//
// len(mockedGpuInstance.GetVgpuSchedulerStateCalls())
func (mock *GpuInstance) GetVgpuSchedulerStateCalls() []struct {
} {
var calls []struct {
}
mock.lockGetVgpuSchedulerState.RLock()
calls = mock.calls.GetVgpuSchedulerState
mock.lockGetVgpuSchedulerState.RUnlock()
return calls
}
// GetVgpuTypeCreatablePlacements calls GetVgpuTypeCreatablePlacementsFunc.
func (mock *GpuInstance) GetVgpuTypeCreatablePlacements() (nvml.VgpuCreatablePlacementInfo, nvml.Return) {
if mock.GetVgpuTypeCreatablePlacementsFunc == nil {
panic("GpuInstance.GetVgpuTypeCreatablePlacementsFunc: method is nil but GpuInstance.GetVgpuTypeCreatablePlacements was just called")
}
callInfo := struct {
}{}
mock.lockGetVgpuTypeCreatablePlacements.Lock()
mock.calls.GetVgpuTypeCreatablePlacements = append(mock.calls.GetVgpuTypeCreatablePlacements, callInfo)
mock.lockGetVgpuTypeCreatablePlacements.Unlock()
return mock.GetVgpuTypeCreatablePlacementsFunc()
}
// GetVgpuTypeCreatablePlacementsCalls gets all the calls that were made to GetVgpuTypeCreatablePlacements.
// Check the length with:
//
// len(mockedGpuInstance.GetVgpuTypeCreatablePlacementsCalls())
func (mock *GpuInstance) GetVgpuTypeCreatablePlacementsCalls() []struct {
} {
var calls []struct {
}
mock.lockGetVgpuTypeCreatablePlacements.RLock()
calls = mock.calls.GetVgpuTypeCreatablePlacements
mock.lockGetVgpuTypeCreatablePlacements.RUnlock()
return calls
}
// SetVgpuHeterogeneousMode calls SetVgpuHeterogeneousModeFunc.
func (mock *GpuInstance) SetVgpuHeterogeneousMode(vgpuHeterogeneousMode *nvml.VgpuHeterogeneousMode) nvml.Return {
if mock.SetVgpuHeterogeneousModeFunc == nil {
panic("GpuInstance.SetVgpuHeterogeneousModeFunc: method is nil but GpuInstance.SetVgpuHeterogeneousMode was just called")
}
callInfo := struct {
VgpuHeterogeneousMode *nvml.VgpuHeterogeneousMode
}{
VgpuHeterogeneousMode: vgpuHeterogeneousMode,
}
mock.lockSetVgpuHeterogeneousMode.Lock()
mock.calls.SetVgpuHeterogeneousMode = append(mock.calls.SetVgpuHeterogeneousMode, callInfo)
mock.lockSetVgpuHeterogeneousMode.Unlock()
return mock.SetVgpuHeterogeneousModeFunc(vgpuHeterogeneousMode)
}
// SetVgpuHeterogeneousModeCalls gets all the calls that were made to SetVgpuHeterogeneousMode.
// Check the length with:
//
// len(mockedGpuInstance.SetVgpuHeterogeneousModeCalls())
func (mock *GpuInstance) SetVgpuHeterogeneousModeCalls() []struct {
VgpuHeterogeneousMode *nvml.VgpuHeterogeneousMode
} {
var calls []struct {
VgpuHeterogeneousMode *nvml.VgpuHeterogeneousMode
}
mock.lockSetVgpuHeterogeneousMode.RLock()
calls = mock.calls.SetVgpuHeterogeneousMode
mock.lockSetVgpuHeterogeneousMode.RUnlock()
return calls
}
// SetVgpuSchedulerState calls SetVgpuSchedulerStateFunc.
func (mock *GpuInstance) SetVgpuSchedulerState(vgpuSchedulerState *nvml.VgpuSchedulerState) nvml.Return {
if mock.SetVgpuSchedulerStateFunc == nil {
panic("GpuInstance.SetVgpuSchedulerStateFunc: method is nil but GpuInstance.SetVgpuSchedulerState was just called")
}
callInfo := struct {
VgpuSchedulerState *nvml.VgpuSchedulerState
}{
VgpuSchedulerState: vgpuSchedulerState,
}
mock.lockSetVgpuSchedulerState.Lock()
mock.calls.SetVgpuSchedulerState = append(mock.calls.SetVgpuSchedulerState, callInfo)
mock.lockSetVgpuSchedulerState.Unlock()
return mock.SetVgpuSchedulerStateFunc(vgpuSchedulerState)
}
// SetVgpuSchedulerStateCalls gets all the calls that were made to SetVgpuSchedulerState.
// Check the length with:
//
// len(mockedGpuInstance.SetVgpuSchedulerStateCalls())
func (mock *GpuInstance) SetVgpuSchedulerStateCalls() []struct {
VgpuSchedulerState *nvml.VgpuSchedulerState
} {
var calls []struct {
VgpuSchedulerState *nvml.VgpuSchedulerState
}
mock.lockSetVgpuSchedulerState.RLock()
calls = mock.calls.SetVgpuSchedulerState
mock.lockSetVgpuSchedulerState.RUnlock()
return calls
}

File diff suppressed because it is too large Load Diff

View File

@@ -72,6 +72,9 @@ var _ nvml.VgpuInstance = &VgpuInstance{}
// GetMetadataFunc: func() (nvml.VgpuMetadata, nvml.Return) { // GetMetadataFunc: func() (nvml.VgpuMetadata, nvml.Return) {
// panic("mock out the GetMetadata method") // panic("mock out the GetMetadata method")
// }, // },
// GetRuntimeStateSizeFunc: func() (nvml.VgpuRuntimeState, nvml.Return) {
// panic("mock out the GetRuntimeStateSize method")
// },
// GetTypeFunc: func() (nvml.VgpuTypeId, nvml.Return) { // GetTypeFunc: func() (nvml.VgpuTypeId, nvml.Return) {
// panic("mock out the GetType method") // panic("mock out the GetType method")
// }, // },
@@ -148,6 +151,9 @@ type VgpuInstance struct {
// GetMetadataFunc mocks the GetMetadata method. // GetMetadataFunc mocks the GetMetadata method.
GetMetadataFunc func() (nvml.VgpuMetadata, nvml.Return) GetMetadataFunc func() (nvml.VgpuMetadata, nvml.Return)
// GetRuntimeStateSizeFunc mocks the GetRuntimeStateSize method.
GetRuntimeStateSizeFunc func() (nvml.VgpuRuntimeState, nvml.Return)
// GetTypeFunc mocks the GetType method. // GetTypeFunc mocks the GetType method.
GetTypeFunc func() (nvml.VgpuTypeId, nvml.Return) GetTypeFunc func() (nvml.VgpuTypeId, nvml.Return)
@@ -221,6 +227,9 @@ type VgpuInstance struct {
// GetMetadata holds details about calls to the GetMetadata method. // GetMetadata holds details about calls to the GetMetadata method.
GetMetadata []struct { GetMetadata []struct {
} }
// GetRuntimeStateSize holds details about calls to the GetRuntimeStateSize method.
GetRuntimeStateSize []struct {
}
// GetType holds details about calls to the GetType method. // GetType holds details about calls to the GetType method.
GetType []struct { GetType []struct {
} }
@@ -257,6 +266,7 @@ type VgpuInstance struct {
lockGetLicenseStatus sync.RWMutex lockGetLicenseStatus sync.RWMutex
lockGetMdevUUID sync.RWMutex lockGetMdevUUID sync.RWMutex
lockGetMetadata sync.RWMutex lockGetMetadata sync.RWMutex
lockGetRuntimeStateSize sync.RWMutex
lockGetType sync.RWMutex lockGetType sync.RWMutex
lockGetUUID sync.RWMutex lockGetUUID sync.RWMutex
lockGetVmDriverVersion sync.RWMutex lockGetVmDriverVersion sync.RWMutex
@@ -755,6 +765,33 @@ func (mock *VgpuInstance) GetMetadataCalls() []struct {
return calls return calls
} }
// GetRuntimeStateSize calls GetRuntimeStateSizeFunc.
func (mock *VgpuInstance) GetRuntimeStateSize() (nvml.VgpuRuntimeState, nvml.Return) {
if mock.GetRuntimeStateSizeFunc == nil {
panic("VgpuInstance.GetRuntimeStateSizeFunc: method is nil but VgpuInstance.GetRuntimeStateSize was just called")
}
callInfo := struct {
}{}
mock.lockGetRuntimeStateSize.Lock()
mock.calls.GetRuntimeStateSize = append(mock.calls.GetRuntimeStateSize, callInfo)
mock.lockGetRuntimeStateSize.Unlock()
return mock.GetRuntimeStateSizeFunc()
}
// GetRuntimeStateSizeCalls gets all the calls that were made to GetRuntimeStateSize.
// Check the length with:
//
// len(mockedVgpuInstance.GetRuntimeStateSizeCalls())
func (mock *VgpuInstance) GetRuntimeStateSizeCalls() []struct {
} {
var calls []struct {
}
mock.lockGetRuntimeStateSize.RLock()
calls = mock.calls.GetRuntimeStateSize
mock.lockGetRuntimeStateSize.RUnlock()
return calls
}
// GetType calls GetTypeFunc. // GetType calls GetTypeFunc.
func (mock *VgpuInstance) GetType() (nvml.VgpuTypeId, nvml.Return) { func (mock *VgpuInstance) GetType() (nvml.VgpuTypeId, nvml.Return) {
if mock.GetTypeFunc == nil { if mock.GetTypeFunc == nil {

View File

@@ -18,6 +18,9 @@ var _ nvml.VgpuTypeId = &VgpuTypeId{}
// //
// // make and configure a mocked nvml.VgpuTypeId // // make and configure a mocked nvml.VgpuTypeId
// mockedVgpuTypeId := &VgpuTypeId{ // mockedVgpuTypeId := &VgpuTypeId{
// GetBAR1InfoFunc: func() (nvml.VgpuTypeBar1Info, nvml.Return) {
// panic("mock out the GetBAR1Info method")
// },
// GetCapabilitiesFunc: func(vgpuCapability nvml.VgpuCapability) (bool, nvml.Return) { // GetCapabilitiesFunc: func(vgpuCapability nvml.VgpuCapability) (bool, nvml.Return) {
// panic("mock out the GetCapabilities method") // panic("mock out the GetCapabilities method")
// }, // },
@@ -67,6 +70,9 @@ var _ nvml.VgpuTypeId = &VgpuTypeId{}
// //
// } // }
type VgpuTypeId struct { type VgpuTypeId struct {
// GetBAR1InfoFunc mocks the GetBAR1Info method.
GetBAR1InfoFunc func() (nvml.VgpuTypeBar1Info, nvml.Return)
// GetCapabilitiesFunc mocks the GetCapabilities method. // GetCapabilitiesFunc mocks the GetCapabilities method.
GetCapabilitiesFunc func(vgpuCapability nvml.VgpuCapability) (bool, nvml.Return) GetCapabilitiesFunc func(vgpuCapability nvml.VgpuCapability) (bool, nvml.Return)
@@ -111,6 +117,9 @@ type VgpuTypeId struct {
// calls tracks calls to the methods. // calls tracks calls to the methods.
calls struct { calls struct {
// GetBAR1Info holds details about calls to the GetBAR1Info method.
GetBAR1Info []struct {
}
// GetCapabilities holds details about calls to the GetCapabilities method. // GetCapabilities holds details about calls to the GetCapabilities method.
GetCapabilities []struct { GetCapabilities []struct {
// VgpuCapability is the vgpuCapability argument value. // VgpuCapability is the vgpuCapability argument value.
@@ -164,6 +173,7 @@ type VgpuTypeId struct {
Device nvml.Device Device nvml.Device
} }
} }
lockGetBAR1Info sync.RWMutex
lockGetCapabilities sync.RWMutex lockGetCapabilities sync.RWMutex
lockGetClass sync.RWMutex lockGetClass sync.RWMutex
lockGetCreatablePlacements sync.RWMutex lockGetCreatablePlacements sync.RWMutex
@@ -180,6 +190,33 @@ type VgpuTypeId struct {
lockGetSupportedPlacements sync.RWMutex lockGetSupportedPlacements sync.RWMutex
} }
// GetBAR1Info calls GetBAR1InfoFunc.
func (mock *VgpuTypeId) GetBAR1Info() (nvml.VgpuTypeBar1Info, nvml.Return) {
if mock.GetBAR1InfoFunc == nil {
panic("VgpuTypeId.GetBAR1InfoFunc: method is nil but VgpuTypeId.GetBAR1Info was just called")
}
callInfo := struct {
}{}
mock.lockGetBAR1Info.Lock()
mock.calls.GetBAR1Info = append(mock.calls.GetBAR1Info, callInfo)
mock.lockGetBAR1Info.Unlock()
return mock.GetBAR1InfoFunc()
}
// GetBAR1InfoCalls gets all the calls that were made to GetBAR1Info.
// Check the length with:
//
// len(mockedVgpuTypeId.GetBAR1InfoCalls())
func (mock *VgpuTypeId) GetBAR1InfoCalls() []struct {
} {
var calls []struct {
}
mock.lockGetBAR1Info.RLock()
calls = mock.calls.GetBAR1Info
mock.lockGetBAR1Info.RUnlock()
return calls
}
// GetCapabilities calls GetCapabilitiesFunc. // GetCapabilities calls GetCapabilitiesFunc.
func (mock *VgpuTypeId) GetCapabilities(vgpuCapability nvml.VgpuCapability) (bool, nvml.Return) { func (mock *VgpuTypeId) GetCapabilities(vgpuCapability nvml.VgpuCapability) (bool, nvml.Return) {
if mock.GetCapabilitiesFunc == nil { if mock.GetCapabilitiesFunc == nil {

View File

@@ -121,6 +121,15 @@ func nvmlSystemGetTopologyGpuSet(CpuNumber uint32, Count *uint32, DeviceArray *n
return __v return __v
} }
// nvmlSystemGetDriverBranch function as declared in nvml/nvml.h
func nvmlSystemGetDriverBranch(BranchInfo *SystemDriverBranchInfo, Length uint32) Return {
cBranchInfo, _ := (*C.nvmlSystemDriverBranchInfo_t)(unsafe.Pointer(BranchInfo)), cgoAllocsUnknown
cLength, _ := (C.uint)(Length), cgoAllocsUnknown
__ret := C.nvmlSystemGetDriverBranch(cBranchInfo, cLength)
__v := (Return)(__ret)
return __v
}
// nvmlUnitGetCount function as declared in nvml/nvml.h // nvmlUnitGetCount function as declared in nvml/nvml.h
func nvmlUnitGetCount(UnitCount *uint32) Return { func nvmlUnitGetCount(UnitCount *uint32) Return {
cUnitCount, _ := (*C.uint)(unsafe.Pointer(UnitCount)), cgoAllocsUnknown cUnitCount, _ := (*C.uint)(unsafe.Pointer(UnitCount)), cgoAllocsUnknown
@@ -238,6 +247,15 @@ func nvmlDeviceGetHandleByUUID(Uuid string, nvmlDevice *nvmlDevice) Return {
return __v return __v
} }
// nvmlDeviceGetHandleByUUIDV function as declared in nvml/nvml.h
func nvmlDeviceGetHandleByUUIDV(Uuid *UUID, nvmlDevice *nvmlDevice) Return {
cUuid, _ := (*C.nvmlUUID_t)(unsafe.Pointer(Uuid)), cgoAllocsUnknown
cnvmlDevice, _ := (*C.nvmlDevice_t)(unsafe.Pointer(nvmlDevice)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetHandleByUUIDV(cUuid, cnvmlDevice)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetHandleByPciBusId_v2 function as declared in nvml/nvml.h // nvmlDeviceGetHandleByPciBusId_v2 function as declared in nvml/nvml.h
func nvmlDeviceGetHandleByPciBusId_v2(PciBusId string, nvmlDevice *nvmlDevice) Return { func nvmlDeviceGetHandleByPciBusId_v2(PciBusId string, nvmlDevice *nvmlDevice) Return {
cPciBusId, _ := unpackPCharString(PciBusId) cPciBusId, _ := unpackPCharString(PciBusId)
@@ -698,6 +716,15 @@ func nvmlDeviceGetFanSpeed_v2(nvmlDevice nvmlDevice, Fan uint32, Speed *uint32)
return __v return __v
} }
// nvmlDeviceGetFanSpeedRPM function as declared in nvml/nvml.h
func nvmlDeviceGetFanSpeedRPM(nvmlDevice nvmlDevice, FanSpeed *FanSpeedInfo) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cFanSpeed, _ := (*C.nvmlFanSpeedInfo_t)(unsafe.Pointer(FanSpeed)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetFanSpeedRPM(cnvmlDevice, cFanSpeed)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetTargetFanSpeed function as declared in nvml/nvml.h // nvmlDeviceGetTargetFanSpeed function as declared in nvml/nvml.h
func nvmlDeviceGetTargetFanSpeed(nvmlDevice nvmlDevice, Fan uint32, TargetSpeed *uint32) Return { func nvmlDeviceGetTargetFanSpeed(nvmlDevice nvmlDevice, Fan uint32, TargetSpeed *uint32) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
@@ -747,6 +774,24 @@ func nvmlDeviceGetTemperature(nvmlDevice nvmlDevice, SensorType TemperatureSenso
return __v return __v
} }
// nvmlDeviceGetCoolerInfo function as declared in nvml/nvml.h
func nvmlDeviceGetCoolerInfo(nvmlDevice nvmlDevice, CoolerInfo *CoolerInfo) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cCoolerInfo, _ := (*C.nvmlCoolerInfo_t)(unsafe.Pointer(CoolerInfo)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetCoolerInfo(cnvmlDevice, cCoolerInfo)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetTemperatureV function as declared in nvml/nvml.h
func nvmlDeviceGetTemperatureV(nvmlDevice nvmlDevice, Temperature *Temperature) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cTemperature, _ := (*C.nvmlTemperature_t)(unsafe.Pointer(Temperature)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetTemperatureV(cnvmlDevice, cTemperature)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetTemperatureThreshold function as declared in nvml/nvml.h // nvmlDeviceGetTemperatureThreshold function as declared in nvml/nvml.h
func nvmlDeviceGetTemperatureThreshold(nvmlDevice nvmlDevice, ThresholdType TemperatureThresholds, Temp *uint32) Return { func nvmlDeviceGetTemperatureThreshold(nvmlDevice nvmlDevice, ThresholdType TemperatureThresholds, Temp *uint32) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
@@ -757,6 +802,15 @@ func nvmlDeviceGetTemperatureThreshold(nvmlDevice nvmlDevice, ThresholdType Temp
return __v return __v
} }
// nvmlDeviceGetMarginTemperature function as declared in nvml/nvml.h
func nvmlDeviceGetMarginTemperature(nvmlDevice nvmlDevice, MarginTempInfo *MarginTemperature) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cMarginTempInfo, _ := (*C.nvmlMarginTemperature_t)(unsafe.Pointer(MarginTempInfo)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetMarginTemperature(cnvmlDevice, cMarginTempInfo)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetThermalSettings function as declared in nvml/nvml.h // nvmlDeviceGetThermalSettings function as declared in nvml/nvml.h
func nvmlDeviceGetThermalSettings(nvmlDevice nvmlDevice, SensorIndex uint32, PThermalSettings *GpuThermalSettings) Return { func nvmlDeviceGetThermalSettings(nvmlDevice nvmlDevice, SensorIndex uint32, PThermalSettings *GpuThermalSettings) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
@@ -881,6 +935,42 @@ func nvmlDeviceGetMemClkMinMaxVfOffset(nvmlDevice nvmlDevice, MinOffset *int32,
return __v return __v
} }
// nvmlDeviceGetClockOffsets function as declared in nvml/nvml.h
func nvmlDeviceGetClockOffsets(nvmlDevice nvmlDevice, Info *ClockOffset) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cInfo, _ := (*C.nvmlClockOffset_t)(unsafe.Pointer(Info)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetClockOffsets(cnvmlDevice, cInfo)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceSetClockOffsets function as declared in nvml/nvml.h
func nvmlDeviceSetClockOffsets(nvmlDevice nvmlDevice, Info *ClockOffset) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cInfo, _ := (*C.nvmlClockOffset_t)(unsafe.Pointer(Info)), cgoAllocsUnknown
__ret := C.nvmlDeviceSetClockOffsets(cnvmlDevice, cInfo)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetPerformanceModes function as declared in nvml/nvml.h
func nvmlDeviceGetPerformanceModes(nvmlDevice nvmlDevice, PerfModes *DevicePerfModes) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cPerfModes, _ := (*C.nvmlDevicePerfModes_t)(unsafe.Pointer(PerfModes)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetPerformanceModes(cnvmlDevice, cPerfModes)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetCurrentClockFreqs function as declared in nvml/nvml.h
func nvmlDeviceGetCurrentClockFreqs(nvmlDevice nvmlDevice, CurrentClockFreqs *DeviceCurrentClockFreqs) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cCurrentClockFreqs, _ := (*C.nvmlDeviceCurrentClockFreqs_t)(unsafe.Pointer(CurrentClockFreqs)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetCurrentClockFreqs(cnvmlDevice, cCurrentClockFreqs)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetPowerManagementMode function as declared in nvml/nvml.h // nvmlDeviceGetPowerManagementMode function as declared in nvml/nvml.h
func nvmlDeviceGetPowerManagementMode(nvmlDevice nvmlDevice, Mode *EnableState) Return { func nvmlDeviceGetPowerManagementMode(nvmlDevice nvmlDevice, Mode *EnableState) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
@@ -992,6 +1082,25 @@ func nvmlDeviceGetCudaComputeCapability(nvmlDevice nvmlDevice, Major *int32, Min
return __v return __v
} }
// nvmlDeviceGetDramEncryptionMode function as declared in nvml/nvml.h
func nvmlDeviceGetDramEncryptionMode(nvmlDevice nvmlDevice, Current *DramEncryptionInfo, Pending *DramEncryptionInfo) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cCurrent, _ := (*C.nvmlDramEncryptionInfo_t)(unsafe.Pointer(Current)), cgoAllocsUnknown
cPending, _ := (*C.nvmlDramEncryptionInfo_t)(unsafe.Pointer(Pending)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetDramEncryptionMode(cnvmlDevice, cCurrent, cPending)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceSetDramEncryptionMode function as declared in nvml/nvml.h
func nvmlDeviceSetDramEncryptionMode(nvmlDevice nvmlDevice, DramEncryption *DramEncryptionInfo) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cDramEncryption, _ := (*C.nvmlDramEncryptionInfo_t)(unsafe.Pointer(DramEncryption)), cgoAllocsUnknown
__ret := C.nvmlDeviceSetDramEncryptionMode(cnvmlDevice, cDramEncryption)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetEccMode function as declared in nvml/nvml.h // nvmlDeviceGetEccMode function as declared in nvml/nvml.h
func nvmlDeviceGetEccMode(nvmlDevice nvmlDevice, Current *EnableState, Pending *EnableState) Return { func nvmlDeviceGetEccMode(nvmlDevice nvmlDevice, Current *EnableState, Pending *EnableState) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
@@ -1162,12 +1271,12 @@ func nvmlDeviceGetFBCSessions(nvmlDevice nvmlDevice, SessionCount *uint32, Sessi
return __v return __v
} }
// nvmlDeviceGetDriverModel function as declared in nvml/nvml.h // nvmlDeviceGetDriverModel_v2 function as declared in nvml/nvml.h
func nvmlDeviceGetDriverModel(nvmlDevice nvmlDevice, Current *DriverModel, Pending *DriverModel) Return { func nvmlDeviceGetDriverModel_v2(nvmlDevice nvmlDevice, Current *DriverModel, Pending *DriverModel) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cCurrent, _ := (*C.nvmlDriverModel_t)(unsafe.Pointer(Current)), cgoAllocsUnknown cCurrent, _ := (*C.nvmlDriverModel_t)(unsafe.Pointer(Current)), cgoAllocsUnknown
cPending, _ := (*C.nvmlDriverModel_t)(unsafe.Pointer(Pending)), cgoAllocsUnknown cPending, _ := (*C.nvmlDriverModel_t)(unsafe.Pointer(Pending)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetDriverModel(cnvmlDevice, cCurrent, cPending) __ret := C.nvmlDeviceGetDriverModel_v2(cnvmlDevice, cCurrent, cPending)
__v := (Return)(__ret) __v := (Return)(__ret)
return __v return __v
} }
@@ -1440,6 +1549,31 @@ func nvmlSystemGetConfComputeKeyRotationThresholdInfo(PKeyRotationThrInfo *ConfC
return __v return __v
} }
// nvmlDeviceSetConfComputeUnprotectedMemSize function as declared in nvml/nvml.h
func nvmlDeviceSetConfComputeUnprotectedMemSize(nvmlDevice nvmlDevice, SizeKiB uint64) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cSizeKiB, _ := (C.ulonglong)(SizeKiB), cgoAllocsUnknown
__ret := C.nvmlDeviceSetConfComputeUnprotectedMemSize(cnvmlDevice, cSizeKiB)
__v := (Return)(__ret)
return __v
}
// nvmlSystemSetConfComputeGpusReadyState function as declared in nvml/nvml.h
func nvmlSystemSetConfComputeGpusReadyState(IsAcceptingWork uint32) Return {
cIsAcceptingWork, _ := (C.uint)(IsAcceptingWork), cgoAllocsUnknown
__ret := C.nvmlSystemSetConfComputeGpusReadyState(cIsAcceptingWork)
__v := (Return)(__ret)
return __v
}
// nvmlSystemSetConfComputeKeyRotationThresholdInfo function as declared in nvml/nvml.h
func nvmlSystemSetConfComputeKeyRotationThresholdInfo(PKeyRotationThrInfo *ConfComputeSetKeyRotationThresholdInfo) Return {
cPKeyRotationThrInfo, _ := (*C.nvmlConfComputeSetKeyRotationThresholdInfo_t)(unsafe.Pointer(PKeyRotationThrInfo)), cgoAllocsUnknown
__ret := C.nvmlSystemSetConfComputeKeyRotationThresholdInfo(cPKeyRotationThrInfo)
__v := (Return)(__ret)
return __v
}
// nvmlSystemGetConfComputeSettings function as declared in nvml/nvml.h // nvmlSystemGetConfComputeSettings function as declared in nvml/nvml.h
func nvmlSystemGetConfComputeSettings(Settings *SystemConfComputeSettings) Return { func nvmlSystemGetConfComputeSettings(Settings *SystemConfComputeSettings) Return {
cSettings, _ := (*C.nvmlSystemConfComputeSettings_t)(unsafe.Pointer(Settings)), cgoAllocsUnknown cSettings, _ := (*C.nvmlSystemConfComputeSettings_t)(unsafe.Pointer(Settings)), cgoAllocsUnknown
@@ -1467,6 +1601,15 @@ func nvmlDeviceGetGspFirmwareMode(nvmlDevice nvmlDevice, IsEnabled *uint32, Defa
return __v return __v
} }
// nvmlDeviceGetSramEccErrorStatus function as declared in nvml/nvml.h
func nvmlDeviceGetSramEccErrorStatus(nvmlDevice nvmlDevice, Status *EccSramErrorStatus) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cStatus, _ := (*C.nvmlEccSramErrorStatus_t)(unsafe.Pointer(Status)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetSramEccErrorStatus(cnvmlDevice, cStatus)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetAccountingMode function as declared in nvml/nvml.h // nvmlDeviceGetAccountingMode function as declared in nvml/nvml.h
func nvmlDeviceGetAccountingMode(nvmlDevice nvmlDevice, Mode *EnableState) Return { func nvmlDeviceGetAccountingMode(nvmlDevice nvmlDevice, Mode *EnableState) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
@@ -1596,6 +1739,15 @@ func nvmlDeviceGetProcessesUtilizationInfo(nvmlDevice nvmlDevice, ProcesesUtilIn
return __v return __v
} }
// nvmlDeviceGetPlatformInfo function as declared in nvml/nvml.h
func nvmlDeviceGetPlatformInfo(nvmlDevice nvmlDevice, PlatformInfo *PlatformInfo) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cPlatformInfo, _ := (*C.nvmlPlatformInfo_t)(unsafe.Pointer(PlatformInfo)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetPlatformInfo(cnvmlDevice, cPlatformInfo)
__v := (Return)(__ret)
return __v
}
// nvmlUnitSetLedState function as declared in nvml/nvml.h // nvmlUnitSetLedState function as declared in nvml/nvml.h
func nvmlUnitSetLedState(nvmlUnit nvmlUnit, Color LedColor) Return { func nvmlUnitSetLedState(nvmlUnit nvmlUnit, Color LedColor) Return {
cnvmlUnit, _ := *(*C.nvmlUnit_t)(unsafe.Pointer(&nvmlUnit)), cgoAllocsUnknown cnvmlUnit, _ := *(*C.nvmlUnit_t)(unsafe.Pointer(&nvmlUnit)), cgoAllocsUnknown
@@ -1809,31 +1961,6 @@ func nvmlDeviceSetMemClkVfOffset(nvmlDevice nvmlDevice, Offset int32) Return {
return __v return __v
} }
// nvmlDeviceSetConfComputeUnprotectedMemSize function as declared in nvml/nvml.h
func nvmlDeviceSetConfComputeUnprotectedMemSize(nvmlDevice nvmlDevice, SizeKiB uint64) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cSizeKiB, _ := (C.ulonglong)(SizeKiB), cgoAllocsUnknown
__ret := C.nvmlDeviceSetConfComputeUnprotectedMemSize(cnvmlDevice, cSizeKiB)
__v := (Return)(__ret)
return __v
}
// nvmlSystemSetConfComputeGpusReadyState function as declared in nvml/nvml.h
func nvmlSystemSetConfComputeGpusReadyState(IsAcceptingWork uint32) Return {
cIsAcceptingWork, _ := (C.uint)(IsAcceptingWork), cgoAllocsUnknown
__ret := C.nvmlSystemSetConfComputeGpusReadyState(cIsAcceptingWork)
__v := (Return)(__ret)
return __v
}
// nvmlSystemSetConfComputeKeyRotationThresholdInfo function as declared in nvml/nvml.h
func nvmlSystemSetConfComputeKeyRotationThresholdInfo(PKeyRotationThrInfo *ConfComputeSetKeyRotationThresholdInfo) Return {
cPKeyRotationThrInfo, _ := (*C.nvmlConfComputeSetKeyRotationThresholdInfo_t)(unsafe.Pointer(PKeyRotationThrInfo)), cgoAllocsUnknown
__ret := C.nvmlSystemSetConfComputeKeyRotationThresholdInfo(cPKeyRotationThrInfo)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceSetAccountingMode function as declared in nvml/nvml.h // nvmlDeviceSetAccountingMode function as declared in nvml/nvml.h
func nvmlDeviceSetAccountingMode(nvmlDevice nvmlDevice, Mode EnableState) Return { func nvmlDeviceSetAccountingMode(nvmlDevice nvmlDevice, Mode EnableState) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
@@ -1851,6 +1978,15 @@ func nvmlDeviceClearAccountingPids(nvmlDevice nvmlDevice) Return {
return __v return __v
} }
// nvmlDeviceSetPowerManagementLimit_v2 function as declared in nvml/nvml.h
func nvmlDeviceSetPowerManagementLimit_v2(nvmlDevice nvmlDevice, PowerValue *PowerValue_v2) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cPowerValue, _ := (*C.nvmlPowerValue_v2_t)(unsafe.Pointer(PowerValue)), cgoAllocsUnknown
__ret := C.nvmlDeviceSetPowerManagementLimit_v2(cnvmlDevice, cPowerValue)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetNvLinkState function as declared in nvml/nvml.h // nvmlDeviceGetNvLinkState function as declared in nvml/nvml.h
func nvmlDeviceGetNvLinkState(nvmlDevice nvmlDevice, Link uint32, IsActive *EnableState) Return { func nvmlDeviceGetNvLinkState(nvmlDevice nvmlDevice, Link uint32, IsActive *EnableState) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
@@ -1978,6 +2114,58 @@ func nvmlDeviceGetNvLinkRemoteDeviceType(nvmlDevice nvmlDevice, Link uint32, PNv
return __v return __v
} }
// nvmlDeviceSetNvLinkDeviceLowPowerThreshold function as declared in nvml/nvml.h
func nvmlDeviceSetNvLinkDeviceLowPowerThreshold(nvmlDevice nvmlDevice, Info *NvLinkPowerThres) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cInfo, _ := (*C.nvmlNvLinkPowerThres_t)(unsafe.Pointer(Info)), cgoAllocsUnknown
__ret := C.nvmlDeviceSetNvLinkDeviceLowPowerThreshold(cnvmlDevice, cInfo)
__v := (Return)(__ret)
return __v
}
// nvmlSystemSetNvlinkBwMode function as declared in nvml/nvml.h
func nvmlSystemSetNvlinkBwMode(NvlinkBwMode uint32) Return {
cNvlinkBwMode, _ := (C.uint)(NvlinkBwMode), cgoAllocsUnknown
__ret := C.nvmlSystemSetNvlinkBwMode(cNvlinkBwMode)
__v := (Return)(__ret)
return __v
}
// nvmlSystemGetNvlinkBwMode function as declared in nvml/nvml.h
func nvmlSystemGetNvlinkBwMode(NvlinkBwMode *uint32) Return {
cNvlinkBwMode, _ := (*C.uint)(unsafe.Pointer(NvlinkBwMode)), cgoAllocsUnknown
__ret := C.nvmlSystemGetNvlinkBwMode(cNvlinkBwMode)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetNvlinkSupportedBwModes function as declared in nvml/nvml.h
func nvmlDeviceGetNvlinkSupportedBwModes(nvmlDevice nvmlDevice, SupportedBwMode *NvlinkSupportedBwModes) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cSupportedBwMode, _ := (*C.nvmlNvlinkSupportedBwModes_t)(unsafe.Pointer(SupportedBwMode)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetNvlinkSupportedBwModes(cnvmlDevice, cSupportedBwMode)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetNvlinkBwMode function as declared in nvml/nvml.h
func nvmlDeviceGetNvlinkBwMode(nvmlDevice nvmlDevice, GetBwMode *NvlinkGetBwMode) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cGetBwMode, _ := (*C.nvmlNvlinkGetBwMode_t)(unsafe.Pointer(GetBwMode)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetNvlinkBwMode(cnvmlDevice, cGetBwMode)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceSetNvlinkBwMode function as declared in nvml/nvml.h
func nvmlDeviceSetNvlinkBwMode(nvmlDevice nvmlDevice, SetBwMode *NvlinkSetBwMode) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cSetBwMode, _ := (*C.nvmlNvlinkSetBwMode_t)(unsafe.Pointer(SetBwMode)), cgoAllocsUnknown
__ret := C.nvmlDeviceSetNvlinkBwMode(cnvmlDevice, cSetBwMode)
__v := (Return)(__ret)
return __v
}
// nvmlEventSetCreate function as declared in nvml/nvml.h // nvmlEventSetCreate function as declared in nvml/nvml.h
func nvmlEventSetCreate(Set *nvmlEventSet) Return { func nvmlEventSetCreate(Set *nvmlEventSet) Return {
cSet, _ := (*C.nvmlEventSet_t)(unsafe.Pointer(Set)), cgoAllocsUnknown cSet, _ := (*C.nvmlEventSet_t)(unsafe.Pointer(Set)), cgoAllocsUnknown
@@ -2023,6 +2211,38 @@ func nvmlEventSetFree(Set nvmlEventSet) Return {
return __v return __v
} }
// nvmlSystemEventSetCreate function as declared in nvml/nvml.h
func nvmlSystemEventSetCreate(Request *SystemEventSetCreateRequest) Return {
cRequest, _ := (*C.nvmlSystemEventSetCreateRequest_t)(unsafe.Pointer(Request)), cgoAllocsUnknown
__ret := C.nvmlSystemEventSetCreate(cRequest)
__v := (Return)(__ret)
return __v
}
// nvmlSystemEventSetFree function as declared in nvml/nvml.h
func nvmlSystemEventSetFree(Request *SystemEventSetFreeRequest) Return {
cRequest, _ := (*C.nvmlSystemEventSetFreeRequest_t)(unsafe.Pointer(Request)), cgoAllocsUnknown
__ret := C.nvmlSystemEventSetFree(cRequest)
__v := (Return)(__ret)
return __v
}
// nvmlSystemRegisterEvents function as declared in nvml/nvml.h
func nvmlSystemRegisterEvents(Request *SystemRegisterEventRequest) Return {
cRequest, _ := (*C.nvmlSystemRegisterEventRequest_t)(unsafe.Pointer(Request)), cgoAllocsUnknown
__ret := C.nvmlSystemRegisterEvents(cRequest)
__v := (Return)(__ret)
return __v
}
// nvmlSystemEventSetWait function as declared in nvml/nvml.h
func nvmlSystemEventSetWait(Request *SystemEventSetWaitRequest) Return {
cRequest, _ := (*C.nvmlSystemEventSetWaitRequest_t)(unsafe.Pointer(Request)), cgoAllocsUnknown
__ret := C.nvmlSystemEventSetWait(cRequest)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceModifyDrainState function as declared in nvml/nvml.h // nvmlDeviceModifyDrainState function as declared in nvml/nvml.h
func nvmlDeviceModifyDrainState(PciInfo *PciInfo, NewState EnableState) Return { func nvmlDeviceModifyDrainState(PciInfo *PciInfo, NewState EnableState) Return {
cPciInfo, _ := (*C.nvmlPciInfo_t)(unsafe.Pointer(PciInfo)), cgoAllocsUnknown cPciInfo, _ := (*C.nvmlPciInfo_t)(unsafe.Pointer(PciInfo)), cgoAllocsUnknown
@@ -2171,6 +2391,15 @@ func nvmlVgpuTypeGetFbReservation(nvmlVgpuTypeId nvmlVgpuTypeId, FbReservation *
return __v return __v
} }
// nvmlVgpuInstanceGetRuntimeStateSize function as declared in nvml/nvml.h
func nvmlVgpuInstanceGetRuntimeStateSize(nvmlVgpuInstance nvmlVgpuInstance, PState *VgpuRuntimeState) Return {
cnvmlVgpuInstance, _ := (C.nvmlVgpuInstance_t)(nvmlVgpuInstance), cgoAllocsUnknown
cPState, _ := (*C.nvmlVgpuRuntimeState_t)(unsafe.Pointer(PState)), cgoAllocsUnknown
__ret := C.nvmlVgpuInstanceGetRuntimeStateSize(cnvmlVgpuInstance, cPState)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceSetVgpuCapabilities function as declared in nvml/nvml.h // nvmlDeviceSetVgpuCapabilities function as declared in nvml/nvml.h
func nvmlDeviceSetVgpuCapabilities(nvmlDevice nvmlDevice, Capability DeviceVgpuCapability, State EnableState) Return { func nvmlDeviceSetVgpuCapabilities(nvmlDevice nvmlDevice, Capability DeviceVgpuCapability, State EnableState) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
@@ -2335,6 +2564,15 @@ func nvmlVgpuTypeGetMaxInstancesPerVm(nvmlVgpuTypeId nvmlVgpuTypeId, VgpuInstanc
return __v return __v
} }
// nvmlVgpuTypeGetBAR1Info function as declared in nvml/nvml.h
func nvmlVgpuTypeGetBAR1Info(nvmlVgpuTypeId nvmlVgpuTypeId, Bar1Info *VgpuTypeBar1Info) Return {
cnvmlVgpuTypeId, _ := (C.nvmlVgpuTypeId_t)(nvmlVgpuTypeId), cgoAllocsUnknown
cBar1Info, _ := (*C.nvmlVgpuTypeBar1Info_t)(unsafe.Pointer(Bar1Info)), cgoAllocsUnknown
__ret := C.nvmlVgpuTypeGetBAR1Info(cnvmlVgpuTypeId, cBar1Info)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceGetActiveVgpus function as declared in nvml/nvml.h // nvmlDeviceGetActiveVgpus function as declared in nvml/nvml.h
func nvmlDeviceGetActiveVgpus(nvmlDevice nvmlDevice, VgpuCount *uint32, VgpuInstances *nvmlVgpuInstance) Return { func nvmlDeviceGetActiveVgpus(nvmlDevice nvmlDevice, VgpuCount *uint32, VgpuInstances *nvmlVgpuInstance) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
@@ -2518,6 +2756,86 @@ func nvmlVgpuInstanceGetMdevUUID(nvmlVgpuInstance nvmlVgpuInstance, MdevUuid *by
return __v return __v
} }
// nvmlGpuInstanceGetCreatableVgpus function as declared in nvml/nvml.h
func nvmlGpuInstanceGetCreatableVgpus(nvmlGpuInstance nvmlGpuInstance, PVgpus *VgpuTypeIdInfo) Return {
cnvmlGpuInstance, _ := *(*C.nvmlGpuInstance_t)(unsafe.Pointer(&nvmlGpuInstance)), cgoAllocsUnknown
cPVgpus, _ := (*C.nvmlVgpuTypeIdInfo_t)(unsafe.Pointer(PVgpus)), cgoAllocsUnknown
__ret := C.nvmlGpuInstanceGetCreatableVgpus(cnvmlGpuInstance, cPVgpus)
__v := (Return)(__ret)
return __v
}
// nvmlVgpuTypeGetMaxInstancesPerGpuInstance function as declared in nvml/nvml.h
func nvmlVgpuTypeGetMaxInstancesPerGpuInstance(PMaxInstance *VgpuTypeMaxInstance) Return {
cPMaxInstance, _ := (*C.nvmlVgpuTypeMaxInstance_t)(unsafe.Pointer(PMaxInstance)), cgoAllocsUnknown
__ret := C.nvmlVgpuTypeGetMaxInstancesPerGpuInstance(cPMaxInstance)
__v := (Return)(__ret)
return __v
}
// nvmlGpuInstanceGetActiveVgpus function as declared in nvml/nvml.h
func nvmlGpuInstanceGetActiveVgpus(nvmlGpuInstance nvmlGpuInstance, PVgpuInstanceInfo *ActiveVgpuInstanceInfo) Return {
cnvmlGpuInstance, _ := *(*C.nvmlGpuInstance_t)(unsafe.Pointer(&nvmlGpuInstance)), cgoAllocsUnknown
cPVgpuInstanceInfo, _ := (*C.nvmlActiveVgpuInstanceInfo_t)(unsafe.Pointer(PVgpuInstanceInfo)), cgoAllocsUnknown
__ret := C.nvmlGpuInstanceGetActiveVgpus(cnvmlGpuInstance, cPVgpuInstanceInfo)
__v := (Return)(__ret)
return __v
}
// nvmlGpuInstanceSetVgpuSchedulerState function as declared in nvml/nvml.h
func nvmlGpuInstanceSetVgpuSchedulerState(nvmlGpuInstance nvmlGpuInstance, PScheduler *VgpuSchedulerState) Return {
cnvmlGpuInstance, _ := *(*C.nvmlGpuInstance_t)(unsafe.Pointer(&nvmlGpuInstance)), cgoAllocsUnknown
cPScheduler, _ := (*C.nvmlVgpuSchedulerState_t)(unsafe.Pointer(PScheduler)), cgoAllocsUnknown
__ret := C.nvmlGpuInstanceSetVgpuSchedulerState(cnvmlGpuInstance, cPScheduler)
__v := (Return)(__ret)
return __v
}
// nvmlGpuInstanceGetVgpuSchedulerState function as declared in nvml/nvml.h
func nvmlGpuInstanceGetVgpuSchedulerState(nvmlGpuInstance nvmlGpuInstance, PSchedulerStateInfo *VgpuSchedulerStateInfo) Return {
cnvmlGpuInstance, _ := *(*C.nvmlGpuInstance_t)(unsafe.Pointer(&nvmlGpuInstance)), cgoAllocsUnknown
cPSchedulerStateInfo, _ := (*C.nvmlVgpuSchedulerStateInfo_t)(unsafe.Pointer(PSchedulerStateInfo)), cgoAllocsUnknown
__ret := C.nvmlGpuInstanceGetVgpuSchedulerState(cnvmlGpuInstance, cPSchedulerStateInfo)
__v := (Return)(__ret)
return __v
}
// nvmlGpuInstanceGetVgpuSchedulerLog function as declared in nvml/nvml.h
func nvmlGpuInstanceGetVgpuSchedulerLog(nvmlGpuInstance nvmlGpuInstance, PSchedulerLogInfo *VgpuSchedulerLogInfo) Return {
cnvmlGpuInstance, _ := *(*C.nvmlGpuInstance_t)(unsafe.Pointer(&nvmlGpuInstance)), cgoAllocsUnknown
cPSchedulerLogInfo, _ := (*C.nvmlVgpuSchedulerLogInfo_t)(unsafe.Pointer(PSchedulerLogInfo)), cgoAllocsUnknown
__ret := C.nvmlGpuInstanceGetVgpuSchedulerLog(cnvmlGpuInstance, cPSchedulerLogInfo)
__v := (Return)(__ret)
return __v
}
// nvmlGpuInstanceGetVgpuTypeCreatablePlacements function as declared in nvml/nvml.h
func nvmlGpuInstanceGetVgpuTypeCreatablePlacements(nvmlGpuInstance nvmlGpuInstance, PCreatablePlacementInfo *VgpuCreatablePlacementInfo) Return {
cnvmlGpuInstance, _ := *(*C.nvmlGpuInstance_t)(unsafe.Pointer(&nvmlGpuInstance)), cgoAllocsUnknown
cPCreatablePlacementInfo, _ := (*C.nvmlVgpuCreatablePlacementInfo_t)(unsafe.Pointer(PCreatablePlacementInfo)), cgoAllocsUnknown
__ret := C.nvmlGpuInstanceGetVgpuTypeCreatablePlacements(cnvmlGpuInstance, cPCreatablePlacementInfo)
__v := (Return)(__ret)
return __v
}
// nvmlGpuInstanceGetVgpuHeterogeneousMode function as declared in nvml/nvml.h
func nvmlGpuInstanceGetVgpuHeterogeneousMode(nvmlGpuInstance nvmlGpuInstance, PHeterogeneousMode *VgpuHeterogeneousMode) Return {
cnvmlGpuInstance, _ := *(*C.nvmlGpuInstance_t)(unsafe.Pointer(&nvmlGpuInstance)), cgoAllocsUnknown
cPHeterogeneousMode, _ := (*C.nvmlVgpuHeterogeneousMode_t)(unsafe.Pointer(PHeterogeneousMode)), cgoAllocsUnknown
__ret := C.nvmlGpuInstanceGetVgpuHeterogeneousMode(cnvmlGpuInstance, cPHeterogeneousMode)
__v := (Return)(__ret)
return __v
}
// nvmlGpuInstanceSetVgpuHeterogeneousMode function as declared in nvml/nvml.h
func nvmlGpuInstanceSetVgpuHeterogeneousMode(nvmlGpuInstance nvmlGpuInstance, PHeterogeneousMode *VgpuHeterogeneousMode) Return {
cnvmlGpuInstance, _ := *(*C.nvmlGpuInstance_t)(unsafe.Pointer(&nvmlGpuInstance)), cgoAllocsUnknown
cPHeterogeneousMode, _ := (*C.nvmlVgpuHeterogeneousMode_t)(unsafe.Pointer(PHeterogeneousMode)), cgoAllocsUnknown
__ret := C.nvmlGpuInstanceSetVgpuHeterogeneousMode(cnvmlGpuInstance, cPHeterogeneousMode)
__v := (Return)(__ret)
return __v
}
// nvmlVgpuInstanceGetMetadata function as declared in nvml/nvml.h // nvmlVgpuInstanceGetMetadata function as declared in nvml/nvml.h
func nvmlVgpuInstanceGetMetadata(nvmlVgpuInstance nvmlVgpuInstance, nvmlVgpuMetadata *nvmlVgpuMetadata, BufferSize *uint32) Return { func nvmlVgpuInstanceGetMetadata(nvmlVgpuInstance nvmlVgpuInstance, nvmlVgpuMetadata *nvmlVgpuMetadata, BufferSize *uint32) Return {
cnvmlVgpuInstance, _ := (C.nvmlVgpuInstance_t)(nvmlVgpuInstance), cgoAllocsUnknown cnvmlVgpuInstance, _ := (C.nvmlVgpuInstance_t)(nvmlVgpuInstance), cgoAllocsUnknown
@@ -3062,45 +3380,74 @@ func nvmlGpmSetStreamingEnabled(nvmlDevice nvmlDevice, State uint32) Return {
return __v return __v
} }
// nvmlDeviceSetNvLinkDeviceLowPowerThreshold function as declared in nvml/nvml.h // nvmlDeviceGetCapabilities function as declared in nvml/nvml.h
func nvmlDeviceSetNvLinkDeviceLowPowerThreshold(nvmlDevice nvmlDevice, Info *NvLinkPowerThres) Return { func nvmlDeviceGetCapabilities(nvmlDevice nvmlDevice, Caps *DeviceCapabilities) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cInfo, _ := (*C.nvmlNvLinkPowerThres_t)(unsafe.Pointer(Info)), cgoAllocsUnknown cCaps, _ := (*C.nvmlDeviceCapabilities_t)(unsafe.Pointer(Caps)), cgoAllocsUnknown
__ret := C.nvmlDeviceSetNvLinkDeviceLowPowerThreshold(cnvmlDevice, cInfo) __ret := C.nvmlDeviceGetCapabilities(cnvmlDevice, cCaps)
__v := (Return)(__ret) __v := (Return)(__ret)
return __v return __v
} }
// nvmlSystemSetNvlinkBwMode function as declared in nvml/nvml.h // nvmlDeviceWorkloadPowerProfileGetProfilesInfo function as declared in nvml/nvml.h
func nvmlSystemSetNvlinkBwMode(NvlinkBwMode uint32) Return { func nvmlDeviceWorkloadPowerProfileGetProfilesInfo(nvmlDevice nvmlDevice, ProfilesInfo *WorkloadPowerProfileProfilesInfo) Return {
cNvlinkBwMode, _ := (C.uint)(NvlinkBwMode), cgoAllocsUnknown
__ret := C.nvmlSystemSetNvlinkBwMode(cNvlinkBwMode)
__v := (Return)(__ret)
return __v
}
// nvmlSystemGetNvlinkBwMode function as declared in nvml/nvml.h
func nvmlSystemGetNvlinkBwMode(NvlinkBwMode *uint32) Return {
cNvlinkBwMode, _ := (*C.uint)(unsafe.Pointer(NvlinkBwMode)), cgoAllocsUnknown
__ret := C.nvmlSystemGetNvlinkBwMode(cNvlinkBwMode)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceSetPowerManagementLimit_v2 function as declared in nvml/nvml.h
func nvmlDeviceSetPowerManagementLimit_v2(nvmlDevice nvmlDevice, PowerValue *PowerValue_v2) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cPowerValue, _ := (*C.nvmlPowerValue_v2_t)(unsafe.Pointer(PowerValue)), cgoAllocsUnknown cProfilesInfo, _ := (*C.nvmlWorkloadPowerProfileProfilesInfo_t)(unsafe.Pointer(ProfilesInfo)), cgoAllocsUnknown
__ret := C.nvmlDeviceSetPowerManagementLimit_v2(cnvmlDevice, cPowerValue) __ret := C.nvmlDeviceWorkloadPowerProfileGetProfilesInfo(cnvmlDevice, cProfilesInfo)
__v := (Return)(__ret) __v := (Return)(__ret)
return __v return __v
} }
// nvmlDeviceGetSramEccErrorStatus function as declared in nvml/nvml.h // nvmlDeviceWorkloadPowerProfileGetCurrentProfiles function as declared in nvml/nvml.h
func nvmlDeviceGetSramEccErrorStatus(nvmlDevice nvmlDevice, Status *EccSramErrorStatus) Return { func nvmlDeviceWorkloadPowerProfileGetCurrentProfiles(nvmlDevice nvmlDevice, CurrentProfiles *WorkloadPowerProfileCurrentProfiles) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cStatus, _ := (*C.nvmlEccSramErrorStatus_t)(unsafe.Pointer(Status)), cgoAllocsUnknown cCurrentProfiles, _ := (*C.nvmlWorkloadPowerProfileCurrentProfiles_t)(unsafe.Pointer(CurrentProfiles)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetSramEccErrorStatus(cnvmlDevice, cStatus) __ret := C.nvmlDeviceWorkloadPowerProfileGetCurrentProfiles(cnvmlDevice, cCurrentProfiles)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceWorkloadPowerProfileSetRequestedProfiles function as declared in nvml/nvml.h
func nvmlDeviceWorkloadPowerProfileSetRequestedProfiles(nvmlDevice nvmlDevice, RequestedProfiles *WorkloadPowerProfileRequestedProfiles) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cRequestedProfiles, _ := (*C.nvmlWorkloadPowerProfileRequestedProfiles_t)(unsafe.Pointer(RequestedProfiles)), cgoAllocsUnknown
__ret := C.nvmlDeviceWorkloadPowerProfileSetRequestedProfiles(cnvmlDevice, cRequestedProfiles)
__v := (Return)(__ret)
return __v
}
// nvmlDeviceWorkloadPowerProfileClearRequestedProfiles function as declared in nvml/nvml.h
func nvmlDeviceWorkloadPowerProfileClearRequestedProfiles(nvmlDevice nvmlDevice, RequestedProfiles *WorkloadPowerProfileRequestedProfiles) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cRequestedProfiles, _ := (*C.nvmlWorkloadPowerProfileRequestedProfiles_t)(unsafe.Pointer(RequestedProfiles)), cgoAllocsUnknown
__ret := C.nvmlDeviceWorkloadPowerProfileClearRequestedProfiles(cnvmlDevice, cRequestedProfiles)
__v := (Return)(__ret)
return __v
}
// nvmlDevicePowerSmoothingActivatePresetProfile function as declared in nvml/nvml.h
func nvmlDevicePowerSmoothingActivatePresetProfile(nvmlDevice nvmlDevice, Profile *PowerSmoothingProfile) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cProfile, _ := (*C.nvmlPowerSmoothingProfile_t)(unsafe.Pointer(Profile)), cgoAllocsUnknown
__ret := C.nvmlDevicePowerSmoothingActivatePresetProfile(cnvmlDevice, cProfile)
__v := (Return)(__ret)
return __v
}
// nvmlDevicePowerSmoothingUpdatePresetProfileParam function as declared in nvml/nvml.h
func nvmlDevicePowerSmoothingUpdatePresetProfileParam(nvmlDevice nvmlDevice, Profile *PowerSmoothingProfile) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cProfile, _ := (*C.nvmlPowerSmoothingProfile_t)(unsafe.Pointer(Profile)), cgoAllocsUnknown
__ret := C.nvmlDevicePowerSmoothingUpdatePresetProfileParam(cnvmlDevice, cProfile)
__v := (Return)(__ret)
return __v
}
// nvmlDevicePowerSmoothingSetState function as declared in nvml/nvml.h
func nvmlDevicePowerSmoothingSetState(nvmlDevice nvmlDevice, State *PowerSmoothingState) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cState, _ := (*C.nvmlPowerSmoothingState_t)(unsafe.Pointer(State)), cgoAllocsUnknown
__ret := C.nvmlDevicePowerSmoothingSetState(cnvmlDevice, cState)
__v := (Return)(__ret) __v := (Return)(__ret)
return __v return __v
} }
@@ -3308,3 +3655,13 @@ func nvmlVgpuInstanceGetLicenseInfo_v1(nvmlVgpuInstance nvmlVgpuInstance, Licens
__v := (Return)(__ret) __v := (Return)(__ret)
return __v return __v
} }
// nvmlDeviceGetDriverModel_v1 function as declared in nvml/nvml.h
func nvmlDeviceGetDriverModel_v1(nvmlDevice nvmlDevice, Current *DriverModel, Pending *DriverModel) Return {
cnvmlDevice, _ := *(*C.nvmlDevice_t)(unsafe.Pointer(&nvmlDevice)), cgoAllocsUnknown
cCurrent, _ := (*C.nvmlDriverModel_t)(unsafe.Pointer(Current)), cgoAllocsUnknown
cPending, _ := (*C.nvmlDriverModel_t)(unsafe.Pointer(Pending)), cgoAllocsUnknown
__ret := C.nvmlDeviceGetDriverModel(cnvmlDevice, cCurrent, cPending)
__v := (Return)(__ret)
return __v
}

Some files were not shown because too many files have changed in this diff Show More