Skip to content

Commit 2cc273e

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

File tree

3 files changed

+257
-101
lines changed

3 files changed

+257
-101
lines changed

pkg/sriov/sriov.go

Lines changed: 90 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -66,82 +66,86 @@ 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, _ := ns.GetCurrentNS()
72+
tempNS, err := ns.TempNetNS()
73+
if err != nil {
74+
return fmt.Errorf("failed to create tempNS: %v", err)
75+
}
76+
defer tempNS.Close()
6977

7078
linkObj, err := s.nLink.LinkByName(linkName)
7179
if err != nil {
72-
return fmt.Errorf("error getting VF netdevice with name %s", linkName)
80+
return fmt.Errorf("error: %v. Failed to get VF netdevice with name %s", err, linkName)
7381
}
7482

7583
// Save the original effective MAC address before overriding it
7684
conf.OrigVfState.EffectiveMAC = linkObj.Attrs().HardwareAddr.String()
7785

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",
86+
// 1.Move interface to tempNS
87+
logging.Debug("1. Move the interface to tempNS",
8388
"func", "SetupVF",
8489
"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)
90+
if err = s.nLink.LinkSetNsFd(linkObj, int(tempNS.Fd())); err != nil {
91+
return fmt.Errorf("failed to move %q to tempNS: %v", linkName, err)
9692
}
93+
err = tempNS.Do(func(linkNS ns.NetNS) error {
94+
// lookup the device in tempNS (index might have changed)
95+
tempNSLinkObj, err := s.nLink.LinkByName(linkName)
96+
if err != nil {
97+
return fmt.Errorf("failed to find %q in tempNS: %v", linkName, err)
98+
}
99+
// Rename the interface to pod interface name
100+
if err = s.nLink.LinkSetName(tempNSLinkObj, podifName); err != nil {
101+
return fmt.Errorf("failed to rename host device %q to %q: %v", linkName, podifName, err)
102+
}
97103

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)
104+
// 3. Remove alt name from the nic
105+
logging.Debug("3. Remove interface original name from alt names",
106+
"func", "SetupVF",
107+
"tempNSObj", tempNSLinkObj,
108+
"OriginalLinkName", linkName)
109+
for _, altName := range tempNSLinkObj.Attrs().AltNames {
110+
if altName == linkName {
111+
if err = s.nLink.LinkDelAltName(tempNSLinkObj, linkName); err != nil {
112+
return fmt.Errorf("error removing VF altname %s: %v", linkName, err)
113+
}
112114
}
113115
}
114-
}
115116

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)
117+
// 4. Change netns
118+
logging.Debug("4. Change netns",
119+
"func", "SetupVF",
120+
"tempNSObj", tempNSLinkObj,
121+
"netns.Fd()", int(netns.Fd()))
122+
if err = s.nLink.LinkSetNsFd(tempNSLinkObj, int(netns.Fd())); err != nil {
123+
return fmt.Errorf("failed to move IF %s to netns: %w", podifName, err)
124+
}
125+
return nil
126+
})
127+
if err != nil {
128+
logging.Debug("Move the interface back to initNS because of ", "error", err)
129+
s.moveAndRenameLink(tempNS, podifName, linkName, initns)
130+
return err
123131
}
124132

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)
133+
err = netns.Do(func(_ ns.NetNS) error {
134+
netNSLinkObj, err := s.nLink.LinkByName(podifName)
135+
if err != nil {
136+
return fmt.Errorf("error: %v. Failed to get VF netdevice with name %s", err, podifName)
133137
}
134138

135-
// 6. Enable IPv4 ARP notify and IPv6 Network Discovery notify
139+
// 5. Enable IPv4 ARP notify and IPv6 Network Discovery notify
136140
// 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",
141+
logging.Debug("5. Enable IPv4 ARP notify and IPv6 Network Discovery notify",
138142
"func", "SetupVF",
139143
"podifName", podifName)
140144
_ = s.utils.EnableArpAndNdiscNotify(podifName)
141145

142-
// 7. Set MAC address
146+
// 6. Set MAC address
143147
if conf.MAC != "" {
144-
logging.Debug("7. Set MAC address",
148+
logging.Debug("6. Set MAC address",
145149
"func", "SetupVF",
146150
"s.nLink", s.nLink,
147151
"podifName", podifName,
@@ -152,31 +156,57 @@ func (s *sriovManager) SetupVF(conf *sriovtypes.NetConf, podifName string, netns
152156
}
153157
}
154158

155-
logging.Debug("8. Enable Optimistic DAD for IPv6 addresses", "func", "SetupVF",
156-
"linkObj", linkObj)
159+
logging.Debug("7. Enable Optimistic DAD for IPv6 addresses", "func", "SetupVF",
160+
"linkObj", netNSLinkObj)
157161
_ = s.utils.EnableOptimisticDad(podifName)
158162

159-
// 9. Bring IF up in Pod netns
160-
logging.Debug("9. Bring IF up in Pod netns",
163+
// 8. Bring IF up in Pod netns
164+
logging.Debug("8. Bring IF up in Pod netns",
161165
"func", "SetupVF",
162-
"linkObj", linkObj)
163-
if err := s.nLink.LinkSetUp(linkObj); err != nil {
166+
"linkObj", netNSLinkObj)
167+
if err = s.nLink.LinkSetUp(netNSLinkObj); err != nil {
164168
return fmt.Errorf("error bringing interface up in container ns: %q", err)
165169
}
166170

167171
return nil
168-
}); err != nil {
169-
return fmt.Errorf("error setting up interface in container namespace: %q", err)
172+
})
173+
if err != nil {
174+
// Cleanup: try to move interface back to tempNS
175+
logging.Debug("Move the interface back to tempNS because of ", "error", err)
176+
// Restore the original link name in case of error in renaming
177+
s.moveAndRenameLink(netns, podifName, linkName, initns)
178+
return err
170179
}
171180

172181
// Copy the MTU value to a new variable
173182
// and use it as a pointer
174183
vfMTU := linkObj.Attrs().MTU
175184
conf.MTU = &vfMTU
176-
177185
return nil
178186
}
179187

188+
// moveAndRenameLink restores the original link name and moves it back to initns
189+
func (s *sriovManager) moveAndRenameLink(sourceNM ns.NetNS, podifName, linkName string, initns ns.NetNS) {
190+
_ = sourceNM.Do(func(_ ns.NetNS) error {
191+
// Restore the original link name in case of error in renaming
192+
if nsLinkObj, err := s.nLink.LinkByName(podifName); err == nil {
193+
linkSetNameError := s.nLink.LinkSetName(nsLinkObj, linkName)
194+
if linkSetNameError != nil {
195+
logging.Warning("LinkSetName failed when trying to restore original name", "error", linkSetNameError)
196+
}
197+
}
198+
199+
// Try to move interface back to initns
200+
if nsLinkObj, e := s.nLink.LinkByName(linkName); e == nil {
201+
linkSetNsFdError := s.nLink.LinkSetNsFd(nsLinkObj, int(initns.Fd()))
202+
if linkSetNsFdError != nil {
203+
logging.Warning("LinkSetNsFd failed when trying to move back to initns in case of an error", "error", linkSetNsFdError)
204+
}
205+
}
206+
return nil
207+
})
208+
}
209+
180210
// ReleaseVF reset a VF from Pod netns and return it to init netns
181211
func (s *sriovManager) ReleaseVF(conf *sriovtypes.NetConf, podifName string, netns ns.NetNS) error {
182212
initns, err := ns.GetCurrentNS()
@@ -273,7 +303,6 @@ func (s *sriovManager) ApplyVFConfig(conf *sriovtypes.NetConf) error {
273303
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)
274304
}
275305
}
276-
277306
// 2. Set mac address
278307
if conf.MAC != "" {
279308
// 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)