@@ -66,82 +66,100 @@ func NewSriovManager() Manager {
6666// SetupVF sets up a VF in Pod netns
6767func (s * sriovManager ) SetupVF (conf * sriovtypes.NetConf , podifName string , netns ns.NetNS ) error {
6868 linkName := conf .OrigVfState .HostIFName
69+ // Save the original NS in case we need to restore it
70+ // after an error occurs
71+ initns , err := ns .GetCurrentNS ()
72+ if err != nil {
73+ return fmt .Errorf ("failed to get current NS: %v" , err )
74+ }
75+ tempNS , err := ns .TempNetNS ()
76+ if err != nil {
77+ return fmt .Errorf ("failed to create tempNS: %v" , err )
78+ }
79+
80+ defer func () {
81+ if cerr := tempNS .Close (); cerr != nil {
82+ logging .Warning ("failed to close temporary netns; VF may remain accessible in temp namespace" ,
83+ "func" , "SetupVF" ,
84+ "linkName" , linkName ,
85+ "error" , cerr )
86+ }
87+ }()
6988
7089 linkObj , err := s .nLink .LinkByName (linkName )
7190 if err != nil {
72- return fmt .Errorf ("error getting VF netdevice with name %s" , linkName )
91+ return fmt .Errorf ("error: %v. Failed to get VF netdevice with name %s" , err , linkName )
7392 }
7493
7594 // Save the original effective MAC address before overriding it
7695 conf .OrigVfState .EffectiveMAC = linkObj .Attrs ().HardwareAddr .String ()
7796
78- // tempName used as intermediary name to avoid name conflicts
79- tempName := fmt .Sprintf ("%s%d" , "temp_" , linkObj .Attrs ().Index )
80-
81- // 1. Set link down
82- logging .Debug ("1. Set link down" ,
97+ // 1.Move interface to tempNS
98+ logging .Debug ("1. Move the interface to tempNS" ,
8399 "func" , "SetupVF" ,
84100 "linkObj" , linkObj )
85- if err := s .nLink .LinkSetDown (linkObj ); err != nil {
86- return fmt .Errorf ("failed to down vf device %q: %v" , linkName , err )
87- }
88-
89- // 2. Set temp name
90- logging .Debug ("2. Set temp name" ,
91- "func" , "SetupVF" ,
92- "linkObj" , linkObj ,
93- "tempName" , tempName )
94- if err := s .nLink .LinkSetName (linkObj , tempName ); err != nil {
95- return fmt .Errorf ("error setting temp IF name %s for %s" , tempName , linkName )
101+ if err = s .nLink .LinkSetNsFd (linkObj , int (tempNS .Fd ())); err != nil {
102+ return fmt .Errorf ("failed to move %q to tempNS: %v" , linkName , err )
96103 }
104+ err = tempNS .Do (func (linkNS ns.NetNS ) error {
105+ // lookup the device in tempNS (index might have changed)
106+ tempNSLinkObj , err := s .nLink .LinkByName (linkName )
107+ if err != nil {
108+ return fmt .Errorf ("failed to find %q in tempNS: %v" , linkName , err )
109+ }
110+ // Rename the interface to pod interface name
111+ if err = s .nLink .LinkSetName (tempNSLinkObj , podifName ); err != nil {
112+ return fmt .Errorf ("failed to rename host device %q to %q: %v" , linkName , podifName , err )
113+ }
97114
98- // 3. Remove alt name from the nic
99- logging .Debug ("3. Remove interface original name from alt names" ,
100- "func" , "SetupVF" ,
101- "linkObj" , linkObj ,
102- "OriginalLinkName" , linkName ,
103- "tempName" , tempName )
104- linkObj , err = s .nLink .LinkByName (tempName )
105- if err != nil {
106- return fmt .Errorf ("error getting VF netdevice with name %s: %v" , tempName , err )
107- }
108- for _ , altName := range linkObj .Attrs ().AltNames {
109- if altName == linkName {
110- if err := s .nLink .LinkDelAltName (linkObj , linkName ); err != nil {
111- return fmt .Errorf ("error removing VF altname %s: %v" , linkName , err )
115+ // 3. Remove alt name from the nic
116+ logging .Debug ("3. Remove interface original name from alt names" ,
117+ "func" , "SetupVF" ,
118+ "tempNSObj" , tempNSLinkObj ,
119+ "OriginalLinkName" , linkName )
120+ for _ , altName := range tempNSLinkObj .Attrs ().AltNames {
121+ if altName == linkName {
122+ if err = s .nLink .LinkDelAltName (tempNSLinkObj , linkName ); err != nil {
123+ return fmt .Errorf ("error removing VF altname %s: %v" , linkName , err )
124+ }
112125 }
113126 }
114- }
115127
116- // 4. Change netns
117- logging .Debug ("4. Change netns" ,
118- "func" , "SetupVF" ,
119- "linkObj" , linkObj ,
120- "netns.Fd()" , int (netns .Fd ()))
121- if err := s .nLink .LinkSetNsFd (linkObj , int (netns .Fd ())); err != nil {
122- return fmt .Errorf ("failed to move IF %s to netns: %q" , tempName , err )
128+ // 4. Change netns
129+ logging .Debug ("4. Change netns" ,
130+ "func" , "SetupVF" ,
131+ "tempNSObj" , tempNSLinkObj ,
132+ "netns.Fd()" , int (netns .Fd ()))
133+ if err = s .nLink .LinkSetNsFd (tempNSLinkObj , int (netns .Fd ())); err != nil {
134+ return fmt .Errorf ("failed to move IF %s to netns: %w" , podifName , err )
135+ }
136+ return nil
137+ })
138+ if err != nil {
139+ logging .Error ("Move the interface back to initNS because of " , "error" , err )
140+ renameAndMoveLinkErr := s .renameAndMoveLink (tempNS , initns , []string {podifName , linkName }, linkName )
141+ if renameAndMoveLinkErr != nil {
142+ return fmt .Errorf ("setupVF failed: %v; rollback failed: %v" , err , renameAndMoveLinkErr )
143+ }
144+ return fmt .Errorf ("setupVF failed: %v" , err )
123145 }
124146
125- if err := netns .Do (func (_ ns.NetNS ) error {
126- // 5. Set Pod IF name
127- logging .Debug ("5. Set Pod IF name" ,
128- "func" , "SetupVF" ,
129- "linkObj" , linkObj ,
130- "podifName" , podifName )
131- if err := s .nLink .LinkSetName (linkObj , podifName ); err != nil {
132- return fmt .Errorf ("error setting container interface name %s for %s" , linkName , tempName )
147+ err = netns .Do (func (_ ns.NetNS ) error {
148+ netNSLinkObj , err := s .nLink .LinkByName (podifName )
149+ if err != nil {
150+ return fmt .Errorf ("error: %v. Failed to get VF netdevice with name %s" , err , podifName )
133151 }
134152
135- // 6 . Enable IPv4 ARP notify and IPv6 Network Discovery notify
153+ // 5 . Enable IPv4 ARP notify and IPv6 Network Discovery notify
136154 // Error is ignored here because enabling this feature is only a performance enhancement.
137- logging .Debug ("6 . Enable IPv4 ARP notify and IPv6 Network Discovery notify" ,
155+ logging .Debug ("5 . Enable IPv4 ARP notify and IPv6 Network Discovery notify" ,
138156 "func" , "SetupVF" ,
139157 "podifName" , podifName )
140158 _ = s .utils .EnableArpAndNdiscNotify (podifName )
141159
142- // 7 . Set MAC address
160+ // 6 . Set MAC address
143161 if conf .MAC != "" {
144- logging .Debug ("7 . Set MAC address" ,
162+ logging .Debug ("6 . Set MAC address" ,
145163 "func" , "SetupVF" ,
146164 "s.nLink" , s .nLink ,
147165 "podifName" , podifName ,
@@ -152,31 +170,79 @@ func (s *sriovManager) SetupVF(conf *sriovtypes.NetConf, podifName string, netns
152170 }
153171 }
154172
155- logging .Debug ("8 . Enable Optimistic DAD for IPv6 addresses" , "func" , "SetupVF" ,
156- "linkObj" , linkObj )
173+ logging .Debug ("7 . Enable Optimistic DAD for IPv6 addresses" , "func" , "SetupVF" ,
174+ "linkObj" , netNSLinkObj )
157175 _ = s .utils .EnableOptimisticDad (podifName )
158176
159- // 9 . Bring IF up in Pod netns
160- logging .Debug ("9 . Bring IF up in Pod netns" ,
177+ // 8 . Bring IF up in Pod netns
178+ logging .Debug ("8 . Bring IF up in Pod netns" ,
161179 "func" , "SetupVF" ,
162- "linkObj" , linkObj )
163- if err : = s .nLink .LinkSetUp (linkObj ); err != nil {
180+ "linkObj" , netNSLinkObj )
181+ if err = s .nLink .LinkSetUp (netNSLinkObj ); err != nil {
164182 return fmt .Errorf ("error bringing interface up in container ns: %q" , err )
165183 }
166184
167185 return nil
168- }); err != nil {
186+ })
187+ if err != nil {
169188 return fmt .Errorf ("error setting up interface in container namespace: %q" , err )
170189 }
171190
172191 // Copy the MTU value to a new variable
173192 // and use it as a pointer
174193 vfMTU := linkObj .Attrs ().MTU
175194 conf .MTU = & vfMTU
176-
177195 return nil
178196}
179197
198+ // renameAndMoveLink finds a link by iterating over possible names, renames it if needed, and moves it to target namespace
199+ func (s * sriovManager ) renameAndMoveLink (source , target ns.NetNS , possibleIfNames []string , targetIfname string ) error {
200+ return source .Do (func (_ ns.NetNS ) error {
201+ var linkObj netlink.Link
202+ var currentName string
203+ var err error
204+
205+ // Iterate over possible interface names to find the link
206+ for _ , name := range possibleIfNames {
207+ linkObj , err = s .nLink .LinkByName (name )
208+ if err == nil {
209+ currentName = name
210+ logging .Debug ("Found interface" ,
211+ "func" , "renameAndMoveLink" ,
212+ "currentName" , currentName )
213+ break
214+ }
215+ }
216+
217+ if linkObj == nil {
218+ return fmt .Errorf ("failed to find interface with any of the possible names: %v" , possibleIfNames )
219+ }
220+
221+ // Rename the interface if its current name is different from target name
222+ if currentName != targetIfname {
223+ logging .Debug ("Renaming interface" ,
224+ "func" , "renameAndMoveLink" ,
225+ "from" , currentName ,
226+ "to" , targetIfname )
227+ if err = s .nLink .LinkSetName (linkObj , targetIfname ); err != nil {
228+ logging .Warning ("LinkSetName failed when trying to rename" , "error" , err )
229+ return fmt .Errorf ("failed to rename interface from %q to %q: %v" , currentName , targetIfname , err )
230+ }
231+ }
232+
233+ // Move interface to target namespace
234+ logging .Debug ("Moving interface to target namespace" ,
235+ "func" , "renameAndMoveLink" ,
236+ "ifname" , targetIfname )
237+ if err = s .nLink .LinkSetNsFd (linkObj , int (target .Fd ())); err != nil {
238+ logging .Warning ("LinkSetNsFd failed when trying to move to target namespace" , "error" , err )
239+ return fmt .Errorf ("failed to move interface %q to target namespace: %v" , targetIfname , err )
240+ }
241+
242+ return nil
243+ })
244+ }
245+
180246// ReleaseVF reset a VF from Pod netns and return it to init netns
181247func (s * sriovManager ) ReleaseVF (conf * sriovtypes.NetConf , podifName string , netns ns.NetNS ) error {
182248 initns , err := ns .GetCurrentNS ()
@@ -273,7 +339,6 @@ func (s *sriovManager) ApplyVFConfig(conf *sriovtypes.NetConf) error {
273339 return fmt .Errorf ("failed to set vf %d vlan configuration - id %d, qos %d and proto %s: %v" , conf .VFID , * conf .Vlan , * conf .VlanQoS , * conf .VlanProto , err )
274340 }
275341 }
276-
277342 // 2. Set mac address
278343 if conf .MAC != "" {
279344 // when we restore the original hardware mac address we may get a device or resource busy. so we introduce retry
0 commit comments