Skip to content
Open
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
63 changes: 28 additions & 35 deletions deviceplugin/ccdevice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,16 @@ func TestDiscoverTDX(t *testing.T) {
Resource: "intel.com/tdx",
Type: HardwareAttestation,
DevicePaths: []string{"dev/tdx-guest"},
DeviceLimit: 1,
DeviceLimit: 256,
}
cdp := constructTestPlugin(t, spec)
devices, err := cdp.discoverCcDevices()
if err != nil {
t.Fatalf("discoverCcDevices failed: %v", err)
}

if len(devices) != 1 {
t.Fatalf("Expected 1 device, got %d", len(devices))
if len(devices) != 256 {
t.Fatalf("Expected 256 devices, got %d", len(devices))
}
// Hardware-based should NOT have mounts
if len(devices[0].Mounts) != 0 {
Expand All @@ -138,16 +138,16 @@ func TestDiscoverSEVSNP(t *testing.T) {
Resource: "amd.com/sev-snp",
Type: HardwareAttestation,
DevicePaths: []string{"dev/sev-guest"},
DeviceLimit: 1,
DeviceLimit: 256,
}
cdp := constructTestPlugin(t, spec)
devices, err := cdp.discoverCcDevices()
if err != nil {
t.Fatalf("discoverCcDevices failed: %v", err)
}

if len(devices) != 1 {
t.Fatalf("Expected 1 device, got %d", len(devices))
if len(devices) != 256 {
t.Fatalf("Expected 256 devices, got %d", len(devices))
}
if len(devices[0].Mounts) != 0 {
t.Errorf("SEV-SNP should have 0 mounts, got %d", len(devices[0].Mounts))
Expand Down Expand Up @@ -188,25 +188,20 @@ func TestRefreshDevices(t *testing.T) {
Resource: "intel.com/tdx",
Type: HardwareAttestation,
DevicePaths: []string{"dev/tdx-guest"},
DeviceLimit: 1,
DeviceLimit: 256,
}
cdp := constructTestPlugin(t, spec)
devPath := spec.DevicePaths[0]

// 1. Initial Refresh
changed, err := cdp.refreshDevices()
if err != nil || changed {
t.Errorf("First refresh: err=%v, changed=%v (want false)", err, changed)
}

// 2. Second Refresh (No change)
changed, err = cdp.refreshDevices()
if err != nil || !changed {
t.Errorf("Second refresh: err=%v, changed=%v (want true)", err, changed)
// 2. Remove all devices and refresh
for _, path := range spec.DevicePaths {
os.Remove(path)
}

// 3. Remove device and refresh
os.Remove(devPath)
changed, err = cdp.refreshDevices()
if err != nil || changed {
t.Errorf("Third refresh (removed): err=%v, changed=%v (want false)", err, changed)
Expand All @@ -217,39 +212,37 @@ func TestRefreshDevices(t *testing.T) {
}

func TestAllocate(t *testing.T) {
limit := 2
spec := &CcDeviceSpec{
Resource: "google.com/cc",
Type: SoftwareAttestation,
DevicePaths: []string{"dev/tpmrm0"},
MeasurementPaths: []string{"sys/binary_bios_measurements"},
DeviceLimit: 2,
DeviceLimit: limit,
}
cdp := constructTestPlugin(t, spec)
if _, err := cdp.refreshDevices(); err != nil {
t.Fatalf("refreshDevices failed: %v", err)
}

ctx := context.Background()
expectedID := getExpectedID(spec.Resource, spec.DeviceLimit, 0)

req := &v1beta1.AllocateRequest{
ContainerRequests: []*v1beta1.ContainerAllocateRequest{{
DevicesIDs: []string{expectedID},
}},
}

resp, err := cdp.Allocate(ctx, req)
if err != nil {
t.Fatalf("Allocate failed: %v", err)
}
// Test allocation for index 0 and 1
for i := 0; i < limit; i++ {
expectedID := getExpectedID(spec.Resource, limit, i)
req := &v1beta1.AllocateRequest{
ContainerRequests: []*v1beta1.ContainerAllocateRequest{{
DevicesIDs: []string{expectedID},
}},
}

if len(resp.ContainerResponses) != 1 {
t.Fatalf("Expected 1 response, got %d", len(resp.ContainerResponses))
}
resp, err := cdp.Allocate(ctx, req)
if err != nil {
t.Fatalf("Allocate failed for ID %s: %v", expectedID, err)
}

// Verify the response contains the mount for software attestation
if len(resp.ContainerResponses[0].Mounts) == 0 {
t.Errorf("Expected mount in AllocateResponse for software attestation")
if len(resp.ContainerResponses) != 1 {
t.Fatalf("Expected 1 response, got %d", len(resp.ContainerResponses))
}
}
}

Expand Down Expand Up @@ -292,7 +285,7 @@ func TestListAndWatch(t *testing.T) {
Resource: "intel.com/tdx",
Type: HardwareAttestation,
DevicePaths: []string{"dev/tdx-guest"},
DeviceLimit: 1,
DeviceLimit: 256,
}
cdp := constructTestPlugin(t, spec)
stream := listAndWatchServerStub{}
Expand Down
8 changes: 5 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ const (
logLevelWarn = "warn"
logLevelError = "error"
logLevelNone = "none"
// By default, GKE allows up to 110 Pods per node on Standard clusters. Standard clusters can be configured to allow up to 256 Pods per node.
workloadSharedLimit = 256
)

var (
Expand All @@ -68,7 +70,7 @@ func Main() error {
Type: deviceplugin.SoftwareAttestation, // Explicitly marked as software
DevicePaths: []string{"/dev/tpmrm0"},
MeasurementPaths: []string{"/sys/kernel/security/tpm0/binary_bios_measurements"},
DeviceLimit: 256, // Allow multiple pods to share the vTPM
DeviceLimit: workloadSharedLimit,
},
{
// Intel TDX
Expand All @@ -77,7 +79,7 @@ func Main() error {
DevicePaths: []string{"/dev/tdx-guest", "/dev/tdx_guest"}, // Some kernels use different names
// TDX does not have a separate measurement file, attestation is done via ioctl.
MeasurementPaths: []string{},
DeviceLimit: 1, // Only one container can use the TDX device at a time per node
DeviceLimit: workloadSharedLimit,
},
{
// AMD SEV-SNP
Expand All @@ -86,7 +88,7 @@ func Main() error {
DevicePaths: []string{"/dev/sev-guest"},
// SEV-SNP also uses ioctl for attestation.
MeasurementPaths: []string{},
DeviceLimit: 1, // Only one container can use the SEV-SNP device at a time per node
DeviceLimit: workloadSharedLimit,
},
}

Expand Down
Loading