@@ -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+ moveAndRenameLinkErr := s .moveAndRenameLink (tempNS , podifName , linkName , initns )
141+ if moveAndRenameLinkErr != nil {
142+ return fmt .Errorf ("setupVF failed: %v; rollback failed: %v" , err , moveAndRenameLinkErr )
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,56 @@ 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+ // moveAndRenameLink restores the original link name and moves it back to initns
199+ func (s * sriovManager ) moveAndRenameLink (sourceNM ns.NetNS , podifName , linkName string , initns ns.NetNS ) error {
200+ err := sourceNM .Do (func (_ ns.NetNS ) error {
201+ // Restore the original link name in case of error in renaming
202+ if nsLinkObj , err := s .nLink .LinkByName (podifName ); err == nil {
203+ linkSetNameError := s .nLink .LinkSetName (nsLinkObj , linkName )
204+ if linkSetNameError != nil {
205+ logging .Warning ("LinkSetName failed when trying to restore original name" , "error" , linkSetNameError )
206+ return fmt .Errorf ("error bringing interface up in container ns: %q" , linkSetNameError )
207+ }
208+ }
209+
210+ // Try to move interface back to initns
211+ if nsLinkObj , e := s .nLink .LinkByName (linkName ); e == nil {
212+ linkSetNsFdError := s .nLink .LinkSetNsFd (nsLinkObj , int (initns .Fd ()))
213+ if linkSetNsFdError != nil {
214+ logging .Warning ("LinkSetNsFd failed when trying to move back to initns in case of an error" , "error" , linkSetNsFdError )
215+ return fmt .Errorf ("failed to move IF %s back to initns: %w" , linkName , linkSetNsFdError )
216+ }
217+ }
218+ return nil
219+ })
220+ return err
221+ }
222+
180223// ReleaseVF reset a VF from Pod netns and return it to init netns
181224func (s * sriovManager ) ReleaseVF (conf * sriovtypes.NetConf , podifName string , netns ns.NetNS ) error {
182225 initns , err := ns .GetCurrentNS ()
@@ -273,7 +316,6 @@ func (s *sriovManager) ApplyVFConfig(conf *sriovtypes.NetConf) error {
273316 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 )
274317 }
275318 }
276-
277319 // 2. Set mac address
278320 if conf .MAC != "" {
279321 // when we restore the original hardware mac address we may get a device or resource busy. so we introduce retry
0 commit comments