When encountering an error while deleting an ip in sandbox networking mode, check the ip is still on the interface

When multiple ipv4 ips are added on interfaces, gvisor fails to delete the additional ips from the
interface in sandbox networking mode with the following error:

starting container: setting up network: creating interfaces from net namespace "/proc/909056/ns/net":
removing address 10.0.2.101/24 from device "tun0": cannot assign requested address

This is due to the fact that additional ips on these interfaces are tagged as secondary ips.
When gvisor deletes the primary ip, secondary ips get deleted at the same time and cease to exist
on the interface.
This commit is contained in:
Thomas Lefebvre
2022-06-06 17:58:47 +00:00
parent f4d6127a5c
commit 02c6e8791b
+30
View File
@@ -264,6 +264,13 @@ func createInterfacesAndRoutesFromNS(conn *urpc.Client, nsPath string, hardwareG
// Steal IP address from NIC.
if err := removeAddress(ifaceLink, addr.String()); err != nil {
// If we encounter an error while deleting the ip,
// verify the ip is still present on the interface.
if present, err := isAddressOnInterface(iface.Name, addr); err != nil {
return fmt.Errorf("checking if address %v is on interface %q: %w", addr, iface.Name, err)
} else if !present {
continue
}
return fmt.Errorf("removing address %v from device %q: %w", addr, iface.Name, err)
}
}
@@ -278,6 +285,29 @@ func createInterfacesAndRoutesFromNS(conn *urpc.Client, nsPath string, hardwareG
return nil
}
// isAddressOnInterface checks if an address is on an interface
func isAddressOnInterface(ifaceName string, addr *net.IPNet) (bool, error) {
iface, err := net.InterfaceByName(ifaceName)
if err != nil {
return false, fmt.Errorf("getting interface by name %q: %w", ifaceName, err)
}
ifaceAddrs, err := iface.Addrs()
if err != nil {
return false, fmt.Errorf("fetching interface addresses for %q: %w", iface.Name, err)
}
for _, ifaceAddr := range ifaceAddrs {
ipNet, ok := ifaceAddr.(*net.IPNet)
if !ok {
log.Warningf("Can't cast address to *net.IPNet, skipping: %+v", ifaceAddr)
continue
}
if ipNet.String() == addr.String() {
return true, nil
}
}
return false, nil
}
type socketEntry struct {
deviceFile *os.File
gsoMaxSize uint32