@@ -2,6 +2,7 @@ package network
22
33import (
44 "context"
5+ "fmt"
56 "os"
67 "strings"
78 "time"
@@ -13,6 +14,7 @@ import (
1314 "github.com/Azure/azure-container-networking/network/networkutils"
1415 "github.com/Azure/azure-container-networking/platform"
1516 "github.com/pkg/errors"
17+ vishnetlink "github.com/vishvananda/netlink"
1618 "go.uber.org/zap"
1719 "k8s.io/kubernetes/pkg/kubelet"
1820)
@@ -190,15 +192,15 @@ func (client *SecondaryEndpointClient) DeleteEndpoints(ep *endpoint) error {
190192 }
191193 }()
192194 // For stateless cni linux, check if delegated vmnic type, and if so, delete using this *endpoint* struct's ifname
193- if ep .NICType == cns .DelegatedVMNIC {
194- if err := client .moveInterfaceToHostNetns (ep .IfName , vmns ); err != nil {
195+ if ep .NICType == cns .NodeNetworkInterfaceFrontendNIC {
196+ if err := client .MoveInterfaceToHostNetns (ep .IfName , vmns ); err != nil {
195197 logger .Error ("Failed to move interface" , zap .String ("IfName" , ep .IfName ), zap .Error (newErrorSecondaryEndpointClient (err )))
196198 }
197199 }
198200 // For Statefull cni linux, Use SecondaryInterfaces map to move all interfaces to host netns
199201 // TODO: SecondaryInterfaces map should be retired and only IfName field and NICType should be used to determine the delgated NIC
200202 for iface := range ep .SecondaryInterfaces {
201- if err := client .moveInterfaceToHostNetns (iface , vmns ); err != nil {
203+ if err := client .MoveInterfaceToHostNetns (iface , vmns ); err != nil {
202204 logger .Error ("Failed to move interface" , zap .String ("IfName" , iface ), zap .Error (newErrorSecondaryEndpointClient (err )))
203205 continue
204206 }
@@ -209,10 +211,74 @@ func (client *SecondaryEndpointClient) DeleteEndpoints(ep *endpoint) error {
209211}
210212
211213// moveInterfaceToHostNetns moves the given interface to the host netns.
212- func (client * SecondaryEndpointClient ) moveInterfaceToHostNetns (ifName string , vmns int ) error {
214+ func (client * SecondaryEndpointClient ) MoveInterfaceToHostNetns (ifName string , vmns int ) error {
213215 logger .Info ("Moving interface to host netns" , zap .String ("IfName" , ifName ))
214216 if err := client .netlink .SetLinkNetNs (ifName , uintptr (vmns )); err != nil {
215217 return newErrorSecondaryEndpointClient (err )
216218 }
217219 return nil
218220}
221+
222+ // removeInterfacesfromNetnsPath finds and removes all interfaces from the specified netns path except the infra and non-eth interfaces.
223+ func (client * SecondaryEndpointClient ) RemoveInterfacesfromNetnsPath (infraInterfaceName string , netnspath string ) error {
224+ // Get VM namespace
225+ vmns , err := netns .New ().Get ()
226+ if err != nil {
227+ return newErrorSecondaryEndpointClient (err )
228+ }
229+
230+ // Open the network namespace.
231+ logger .Info ("Opening netns" , zap .Any ("NetNsPath" , netnspath ))
232+ ns , err := client .nsClient .OpenNamespace (netnspath )
233+ if err != nil {
234+ return newErrorSecondaryEndpointClient (err )
235+ }
236+ defer ns .Close ()
237+
238+ // Enter the container network namespace.
239+ logger .Info ("Entering netns" , zap .Any ("NetNsPath" , netnspath ))
240+ if err := ns .Enter (); err != nil {
241+ if errors .Is (err , os .ErrNotExist ) {
242+ return nil
243+ }
244+
245+ return newErrorSecondaryEndpointClient (err )
246+ }
247+
248+ // Return to host network namespace.
249+ defer func () {
250+ logger .Info ("Exiting netns" , zap .Any ("NetNsPath" , netnspath ))
251+ if err := ns .Exit (); err != nil {
252+ logger .Error ("Failed to exit netns with" , zap .Error (newErrorSecondaryEndpointClient (err )))
253+ }
254+ }()
255+ // For stateless cni linux, check if delegated vmnic type, and if so, delete using this *endpoint* struct's ifname
256+ ifnames , err := listIfNamesInNetns (ns )
257+ for _ , iface := range ifnames {
258+ // skip the infra interface as well as non-eth interfaces
259+ if iface == infraInterfaceName || ! strings .Contains (iface , "eth" ) {
260+ continue
261+ }
262+ if err := client .MoveInterfaceToHostNetns (iface , vmns ); err != nil {
263+ logger .Error ("Failed to move interface" , zap .String ("IfName" , iface ), zap .Error (newErrorSecondaryEndpointClient (err )))
264+ }
265+ }
266+
267+ return nil
268+ }
269+
270+ // ListIfNamesInNetns returns all interface names in the given netns path.
271+ func listIfNamesInNetns (ns NamespaceInterface ) ([]string , error ) {
272+ // Use the existing netlink interface to list links
273+ links , err := vishnetlink .LinkList ()
274+ if err != nil {
275+ return nil , fmt .Errorf ("failed to list links: %w" , err )
276+ }
277+
278+ names := make ([]string , 0 , len (links ))
279+ for _ , l := range links {
280+ names = append (names , l .Attrs ().Name )
281+ }
282+ logger .Info ("Found interfaces in netns that needs to be moved back to host" , zap .Any ("interfaces" , names ))
283+ return names , nil
284+ }
0 commit comments