Skip to content

Commit 5ea2362

Browse files
Use temp network namespace for rename
Signed-off-by: Muhammad Adil Ghaffar <[email protected]>
1 parent 21c8cba commit 5ea2362

File tree

3 files changed

+269
-100
lines changed

3 files changed

+269
-100
lines changed

pkg/sriov/sriov.go

Lines changed: 102 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -66,82 +66,100 @@ func NewSriovManager() Manager {
6666
// SetupVF sets up a VF in Pod netns
6767
func (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
181224
func (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

Comments
 (0)