-
Notifications
You must be signed in to change notification settings - Fork 144
core: services: cable_guy: api: manager: Remove subnet from deleted IP #3996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |||||||||||||||||||||||
| from networksetup import AbstractNetworkHandler, NetworkHandlerDetector | ||||||||||||||||||||||||
| from pyroute2 import IW, NDB, IPRoute | ||||||||||||||||||||||||
| from pyroute2.netlink.exceptions import NetlinkError | ||||||||||||||||||||||||
| from pyroute2.netlink.rtnl import rtprotos | ||||||||||||||||||||||||
| from pyroute2.netlink.rtnl.ifaddrmsg import ifaddrmsg | ||||||||||||||||||||||||
| from typedefs import ( | ||||||||||||||||||||||||
| AddressMode, | ||||||||||||||||||||||||
|
|
@@ -380,8 +381,38 @@ def remove_ip(self, interface_name: str, ip_address: str) -> None: | |||||||||||||||||||||||
| address for address in saved_interface.addresses if address.mode != AddressMode.Client | ||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| self._remove_orphaned_subnet_route(interface_name, ip_address, saved_interface) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| self._update_interface_settings(interface_name, saved_interface) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def _remove_orphaned_subnet_route( | ||||||||||||||||||||||||
| self, interface_name: str, ip_address: str, saved_interface: NetworkInterface | ||||||||||||||||||||||||
| ) -> None: | ||||||||||||||||||||||||
| # A subnet route previously adopted will outlives its IP and can hijack traffic | ||||||||||||||||||||||||
| if not self.weak_is_ip_address(ip_address) or ip_address == "0.0.0.0": | ||||||||||||||||||||||||
| return | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # /24 mirrors the prefix used when adding/removing static IPs | ||||||||||||||||||||||||
| subnet = ip_network(f"{ip_address}/24", strict=False) | ||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||
| remaining = self.get_interface_by_name(interface_name).addresses | ||||||||||||||||||||||||
| except Exception as error: | ||||||||||||||||||||||||
| logger.error(f"Could not check remaining addresses on {interface_name}: {error}") | ||||||||||||||||||||||||
| return | ||||||||||||||||||||||||
| if any(self.weak_is_ip_address(address.ip) and IPv4Address(address.ip) in subnet for address in remaining): | ||||||||||||||||||||||||
| return | ||||||||||||||||||||||||
|
Comment on lines
+402
to
+403
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||
| self.ipr.route("del", dst=str(subnet), oif=self._get_interface_index(interface_name)) | ||||||||||||||||||||||||
| logger.info(f"Removed orphaned route {subnet} from interface {interface_name}.") | ||||||||||||||||||||||||
| except NetlinkError as error: | ||||||||||||||||||||||||
| # the kernel already removes its own connected routes on address deletion, so a missing route is fine | ||||||||||||||||||||||||
| if error.code not in (errno.ESRCH, errno.ENOENT): | ||||||||||||||||||||||||
| logger.error(f"Failed to remove orphaned route {subnet} on {interface_name}: {error}") | ||||||||||||||||||||||||
| return | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| saved_interface.routes = [route for route in saved_interface.routes if route.destination != str(subnet)] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def get_interface_by_name(self, name: str, include_dhcp_markers: bool = False) -> NetworkInterface: | ||||||||||||||||||||||||
| """Get interface by name. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
@@ -689,6 +720,11 @@ def get_routes(self, interface_name: str, ignore_unmanaged: bool = True) -> Set[ | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| routes: Set[Route] = set() | ||||||||||||||||||||||||
| for raw_route in raw_routes: | ||||||||||||||||||||||||
| # Kernel-maintained connected routes are created/removed automatically alongside their | ||||||||||||||||||||||||
| # interface addresses. Adopting them would turn them into persistent routes | ||||||||||||||||||||||||
| # that outlive their IP, so we ignore them entirely. | ||||||||||||||||||||||||
| if raw_route["proto"] == rtprotos["RTPROT_KERNEL"]: | ||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I remember seeing a forever-growing list in some scenarios, and I think this must be it. |
||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||
| route = self._parse_route(raw_route) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.