@@ -113,6 +113,16 @@ 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 , & oci.LinuxNetDevice {
121+ Name : dev .Name ,
122+ })
123+ }
124+ }
125+
116126 if len (e .Mounts ) > 0 {
117127 for _ , m := range e .Mounts {
118128 specgen .RemoveMount (m .ContainerPath )
@@ -162,6 +172,14 @@ func (e *ContainerEdits) Apply(spec *oci.Spec) error {
162172 return nil
163173}
164174
175+ func specgenAddLinuxNetDevice (specgen * ocigen.Generator , hostIf string , netDev * oci.LinuxNetDevice ) {
176+ if specgen == nil || netDev == nil {
177+ return
178+ }
179+ ensureLinuxNetDevices (specgen .Config )
180+ specgen .Config .Linux .NetDevices [hostIf ] = * netDev
181+ }
182+
165183// Validate container edits.
166184func (e * ContainerEdits ) Validate () error {
167185 if e == nil || e .ContainerEdits == nil {
@@ -191,6 +209,9 @@ func (e *ContainerEdits) Validate() error {
191209 return err
192210 }
193211 }
212+ if err := ValidateNetDevices (e .NetDevices ); err != nil {
213+ return err
214+ }
194215
195216 return nil
196217}
@@ -210,6 +231,7 @@ func (e *ContainerEdits) Append(o *ContainerEdits) *ContainerEdits {
210231
211232 e .Env = append (e .Env , o .Env ... )
212233 e .DeviceNodes = append (e .DeviceNodes , o .DeviceNodes ... )
234+ e .NetDevices = append (e .NetDevices , o .NetDevices ... )
213235 e .Hooks = append (e .Hooks , o .Hooks ... )
214236 e .Mounts = append (e .Mounts , o .Mounts ... )
215237 if o .IntelRdt != nil {
@@ -244,6 +266,9 @@ func (e *ContainerEdits) isEmpty() bool {
244266 if e .IntelRdt != nil {
245267 return false
246268 }
269+ if e .NetDevices != nil {
270+ return false
271+ }
247272 return true
248273}
249274
@@ -257,6 +282,37 @@ func ValidateEnv(env []string) error {
257282 return nil
258283}
259284
285+ // ValidateNetDevices validates the given net devices.
286+ func ValidateNetDevices (devices []* cdi.NetDevice ) error {
287+ var (
288+ hostSeen = map [string ]string {}
289+ nameSeen = map [string ]string {}
290+ )
291+
292+ for _ , dev := range devices {
293+ if dev .HostIf == "" {
294+ return errors .New ("invalid net device, empty HostIf" )
295+ }
296+ if dev .Name == "" {
297+ return errors .New ("invalid net device, empty Name" )
298+ }
299+
300+ if other , ok := hostSeen [dev .HostIf ]; ok {
301+ return fmt .Errorf ("invalid net device, duplicate HostIf %q with names %q and %q" ,
302+ dev .HostIf , dev .Name , other )
303+ }
304+ hostSeen [dev .HostIf ] = dev .Name
305+
306+ if other , ok := nameSeen [dev .Name ]; ok {
307+ return fmt .Errorf ("invalid net device, duplicate Name %q with HostIf %q and %q" ,
308+ dev .Name , dev .HostIf , other )
309+ }
310+ nameSeen [dev .Name ] = dev .HostIf
311+ }
312+
313+ return nil
314+ }
315+
260316// DeviceNode is a CDI Spec DeviceNode wrapper, used for validating DeviceNodes.
261317type DeviceNode struct {
262318 * cdi.DeviceNode
@@ -351,6 +407,16 @@ func ensureOCIHooks(spec *oci.Spec) {
351407 }
352408}
353409
410+ // Ensure OCI Spec Linux NetDevices map is not nil.
411+ func ensureLinuxNetDevices (spec * oci.Spec ) {
412+ if spec .Linux == nil {
413+ spec .Linux = & oci.Linux {}
414+ }
415+ if spec .Linux .NetDevices == nil {
416+ spec .Linux .NetDevices = map [string ]oci.LinuxNetDevice {}
417+ }
418+ }
419+
354420// sortMounts sorts the mounts in the given OCI Spec.
355421func sortMounts (specgen * ocigen.Generator ) {
356422 mounts := specgen .Mounts ()
0 commit comments