Skip to content

Commit f594c41

Browse files
committed
specs-go,cdi: implement NetDevice injection.
Implement OCI Spec (Linux) NetDevice injection. Signed-off-by: Krisztian Litkey <[email protected]>
1 parent 94c73af commit f594c41

File tree

3 files changed

+93
-6
lines changed

3 files changed

+93
-6
lines changed

pkg/cdi/container-edits.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ func (e *ContainerEdits) Apply(spec *oci.Spec) error {
113113
}
114114
}
115115

116+
if e.NetDevices != nil {
117+
// specgen is currently missing functionality to set Linux NetDevices,
118+
// so we use a locally rolled function for now.
119+
for _, dev := range e.NetDevices {
120+
specgenAddLinuxNetDevice(&specgen, dev.HostIf, (&LinuxNetDevice{dev}).toOCI())
121+
}
122+
}
123+
116124
if len(e.Mounts) > 0 {
117125
for _, m := range e.Mounts {
118126
specgen.RemoveMount(m.ContainerPath)
@@ -162,6 +170,24 @@ func (e *ContainerEdits) Apply(spec *oci.Spec) error {
162170
return nil
163171
}
164172

173+
func specgenAddLinuxNetDevice(specgen *ocigen.Generator, hostIf string, netDev *oci.LinuxNetDevice) {
174+
if specgen == nil || netDev == nil {
175+
return
176+
}
177+
ensureLinuxNetDevices(specgen.Config)
178+
specgen.Config.Linux.NetDevices[hostIf] = *netDev
179+
}
180+
181+
// Ensure OCI Spec Linux NetDevices map is not nil.
182+
func ensureLinuxNetDevices(spec *oci.Spec) {
183+
if spec.Linux == nil {
184+
spec.Linux = &oci.Linux{}
185+
}
186+
if spec.Linux.NetDevices == nil {
187+
spec.Linux.NetDevices = map[string]oci.LinuxNetDevice{}
188+
}
189+
}
190+
165191
// Validate container edits.
166192
func (e *ContainerEdits) Validate() error {
167193
if e == nil || e.ContainerEdits == nil {
@@ -191,6 +217,9 @@ func (e *ContainerEdits) Validate() error {
191217
return err
192218
}
193219
}
220+
if err := ValidateNetDevices(e.NetDevices); err != nil {
221+
return err
222+
}
194223

195224
return nil
196225
}
@@ -210,6 +239,7 @@ func (e *ContainerEdits) Append(o *ContainerEdits) *ContainerEdits {
210239

211240
e.Env = append(e.Env, o.Env...)
212241
e.DeviceNodes = append(e.DeviceNodes, o.DeviceNodes...)
242+
e.NetDevices = append(e.NetDevices, o.NetDevices...)
213243
e.Hooks = append(e.Hooks, o.Hooks...)
214244
e.Mounts = append(e.Mounts, o.Mounts...)
215245
if o.IntelRdt != nil {
@@ -244,6 +274,9 @@ func (e *ContainerEdits) isEmpty() bool {
244274
if e.IntelRdt != nil {
245275
return false
246276
}
277+
if e.NetDevices != nil {
278+
return false
279+
}
247280
return true
248281
}
249282

@@ -257,6 +290,46 @@ func ValidateEnv(env []string) error {
257290
return nil
258291
}
259292

293+
// ValidateNetDevices validates the given net devices.
294+
func ValidateNetDevices(devices []*cdi.LinuxNetDevice) error {
295+
var (
296+
hostSeen = map[string]string{}
297+
nameSeen = map[string]string{}
298+
)
299+
300+
for _, dev := range devices {
301+
if other, ok := hostSeen[dev.HostIf]; ok {
302+
return fmt.Errorf("invalid linux net device, duplicate HostIf %q with names %q and %q",
303+
dev.HostIf, dev.Name, other)
304+
}
305+
hostSeen[dev.HostIf] = dev.Name
306+
307+
if other, ok := nameSeen[dev.Name]; ok {
308+
return fmt.Errorf("invalid linux net device, duplicate Name %q with HostIf %q and %q",
309+
dev.Name, dev.HostIf, other)
310+
}
311+
nameSeen[dev.Name] = dev.HostIf
312+
}
313+
314+
return nil
315+
}
316+
317+
// LinuxNetDevice is a CDI Spec LinuxNetDevice wrapper, used for OCI conversion and validating.
318+
type LinuxNetDevice struct {
319+
*cdi.LinuxNetDevice
320+
}
321+
322+
// Validate LinuxNetDevice.
323+
func (d *LinuxNetDevice) Validate() error {
324+
if d.HostIf == "" {
325+
return errors.New("invalid linux net device, empty HostIf")
326+
}
327+
if d.Name == "" {
328+
return errors.New("invalid linux net device, empty Name")
329+
}
330+
return nil
331+
}
332+
260333
// DeviceNode is a CDI Spec DeviceNode wrapper, used for validating DeviceNodes.
261334
type DeviceNode struct {
262335
*cdi.DeviceNode

pkg/cdi/oci.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,10 @@ func (i *IntelRdt) toOCI() *spec.LinuxIntelRdt {
6363
EnableMBM: i.EnableMBM,
6464
}
6565
}
66+
67+
// toOCI returns the opencontainers runtime Spec LinuxNetDevice for this LinuxNetDevice.
68+
func (d *LinuxNetDevice) toOCI() *spec.LinuxNetDevice {
69+
return &spec.LinuxNetDevice{
70+
Name: d.Name,
71+
}
72+
}

specs-go/config.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ type Device struct {
2424

2525
// ContainerEdits are edits a container runtime must make to the OCI spec to expose the device.
2626
type ContainerEdits struct {
27-
Env []string `json:"env,omitempty" yaml:"env,omitempty"`
28-
DeviceNodes []*DeviceNode `json:"deviceNodes,omitempty" yaml:"deviceNodes,omitempty"`
29-
Hooks []*Hook `json:"hooks,omitempty" yaml:"hooks,omitempty"`
30-
Mounts []*Mount `json:"mounts,omitempty" yaml:"mounts,omitempty"`
31-
IntelRdt *IntelRdt `json:"intelRdt,omitempty" yaml:"intelRdt,omitempty"` // Added in v0.7.0
32-
AdditionalGIDs []uint32 `json:"additionalGids,omitempty" yaml:"additionalGids,omitempty"` // Added in v0.7.0
27+
Env []string `json:"env,omitempty" yaml:"env,omitempty"`
28+
DeviceNodes []*DeviceNode `json:"deviceNodes,omitempty" yaml:"deviceNodes,omitempty"`
29+
NetDevices []*LinuxNetDevice `json:"netDevices,omitempty" yaml:"netDevices,omitempty"` // Added in v1.1.0
30+
Hooks []*Hook `json:"hooks,omitempty" yaml:"hooks,omitempty"`
31+
Mounts []*Mount `json:"mounts,omitempty" yaml:"mounts,omitempty"`
32+
IntelRdt *IntelRdt `json:"intelRdt,omitempty" yaml:"intelRdt,omitempty"` // Added in v0.7.0
33+
AdditionalGIDs []uint32 `json:"additionalGids,omitempty" yaml:"additionalGids,omitempty"` // Added in v0.7.0
3334
}
3435

3536
// DeviceNode represents a device node that needs to be added to the OCI spec.
@@ -70,3 +71,9 @@ type IntelRdt struct {
7071
EnableCMT bool `json:"enableCMT,omitempty" yaml:"enableCMT,omitempty"`
7172
EnableMBM bool `json:"enableMBM,omitempty" yaml:"enableMBM,omitempty"`
7273
}
74+
75+
// LinuxNetDevice represents an OCI LinuxNetDevice to be added to the OCI Spec.
76+
type LinuxNetDevice struct {
77+
HostIf string `json:"hostIf" yaml:"hostIf"`
78+
Name string `json:"name" yaml:"name"`
79+
}

0 commit comments

Comments
 (0)