Skip to content
This repository was archived by the owner on May 6, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pkg/driver/nri_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
metav1apply "k8s.io/client-go/applyconfigurations/meta/v1"
resourceapply "k8s.io/client-go/applyconfigurations/resource/v1beta1"
"k8s.io/klog/v2"
"k8s.io/utils/set"
)

// NRI hooks into the container runtime, the lifecycle of the Pod seen here is local to the runtime
Expand Down Expand Up @@ -66,9 +67,15 @@ func (np *NetworkDriver) CreateContainer(_ context.Context, pod *api.PodSandbox,
return nil, nil, nil
}
// Containers only cares about the RDMA char devices
devPaths := set.Set[string]{}
adjust := &api.ContainerAdjustment{}
for _, config := range podConfig {
for _, dev := range config.RDMADevice.DevChars {
// do not insert the same path multiple times
if devPaths.Has(dev.Path) {
continue
}
devPaths.Insert(dev.Path)
// TODO check the file permissions and uid and gid fields
adjust.AddDevice(&api.LinuxDevice{
Path: dev.Path,
Expand Down
62 changes: 62 additions & 0 deletions pkg/driver/nri_hooks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
Copyright 2024 Google LLC

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

https://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 driver

import (
"context"
"testing"

"github.com/containerd/nri/pkg/api"
"k8s.io/apimachinery/pkg/types"
)

func TestCreateContainerNoDuplicateDevices(t *testing.T) {
np := &NetworkDriver{
podConfigStore: NewPodConfigStore(),
}

podUID := types.UID("test-pod")
pod := &api.PodSandbox{
Uid: string(podUID),
Name: "test-pod",
Namespace: "test-ns",
}
ctr := &api.Container{
Name: "test-container",
}

// Setup pod config with duplicate RDMA devices
rdmaDevChars := []LinuxDevice{
{Path: "/dev/infiniband/uverbs0", Type: "c", Major: 231, Minor: 192},
}
podConfig := PodConfig{
RDMADevice: RDMAConfig{
DevChars: rdmaDevChars,
},
}
np.podConfigStore.Set(podUID, "eth0", podConfig)
np.podConfigStore.Set(podUID, "eth1", podConfig)

adjust, _, err := np.CreateContainer(context.Background(), pod, ctr)
if err != nil {
t.Fatalf("CreateContainer failed: %v", err)
}

if len(adjust.Linux.Devices) != 1 {
t.Errorf("CreateContainer should not adjust the same device multiple times\n%v", adjust.Linux.Devices)
}
}
54 changes: 54 additions & 0 deletions pkg/driver/pod_device_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,57 @@ func TestPodConfigStore_DeleteClaim(t *testing.T) {
})
}
}

func TestPodConfigStore_NoDuplicateDevices(t *testing.T) {
store := NewPodConfigStore()
podUID := types.UID("test-pod-uid-1")
deviceName1 := "eth0"
config1 := PodConfig{
Network: apis.NetworkConfig{
Interface: apis.InterfaceConfig{Name: "eth0-pod"},
},
RDMADevice: RDMAConfig{
LinkDev: "mlx5_0",
DevChars: []LinuxDevice{{
Path: "/dev/infiniband/rdma_cm",
}, {
Path: "/dev/infiniband/uverbs1",
}},
},
}
deviceName2 := "eth1"
config2 := PodConfig{
Network: apis.NetworkConfig{
Interface: apis.InterfaceConfig{Name: "eth2-pod"},
},
RDMADevice: RDMAConfig{
LinkDev: "mlx5_1",
DevChars: []LinuxDevice{{
Path: "/dev/infiniband/rdma_cm",
}, {
Path: "/dev/infiniband/uverbs2",
}},
},
}

// Set the same device config multiple times
store.Set(podUID, deviceName1, config1)
store.Set(podUID, deviceName2, config2)
store.Set(podUID, deviceName1, config1)

podConfigs, found := store.GetPodConfigs(podUID)
if !found {
t.Fatalf("GetPodConfigs() did not find configs for podUID, expected found")
}

if len(podConfigs) != 2 {
t.Errorf("Expected 2 device config, but got %d", len(podConfigs))
}

if _, ok := podConfigs[deviceName1]; !ok {
t.Errorf("Device %s not found in pod configs", deviceName2)
}
if _, ok := podConfigs[deviceName2]; !ok {
t.Errorf("Device %s not found in pod configs", deviceName2)
}
}
Loading