Skip to content

Commit

Permalink
state_diff: fix filtering of host scoped routes
Browse files Browse the repository at this point in the history
When an interface has multiple IPs in the same subnet, there will be
host scoped routes for each of them and the "src" address will be one of
the IPs for all of them.

The filtering of this type of route was not working properly and
including the extra routes in the diff.

This change generalizes the verification to see if the destination
address is one of the system own addresses instead of comparing it with
the src address.

While here, fix the data structure passed to the filtering method. It
should be a list but a dictionary was being passed to it.
  • Loading branch information
daniloegea authored and slyon committed Jan 25, 2024
1 parent d2aa012 commit ebb7480
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 3 deletions.
4 changes: 2 additions & 2 deletions netplan_cli/cli/state_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ def _analyze_routes(self, config: dict, iface: dict) -> None:
netplan_routes = self._normalize_routes(netplan_routes)

# Filter out some routes that are expected to be added automatically
system_addresses = config.get('system_state', {}).get('addresses', [])
system_addresses = [ip for ip in config.get('system_state', {}).get('addresses', {})]
system_routes = self._filter_system_routes(system_routes, system_addresses)

present_only_in_netplan = netplan_routes.difference(system_routes)
Expand Down Expand Up @@ -394,7 +394,7 @@ def _filter_system_routes(self, system_routes: AbstractSet[NetplanRoute], system
if route.to != 'default' and ipaddress.ip_interface(route.to).is_link_local:
continue
# Filter out host scoped routes
if route.scope == 'host' and route.type == 'local' and route.to == route.from_addr:
if route.scope == 'host' and route.type == 'local' and route.to in addresses:
continue
# Filter out the default IPv6 multicast route
if route.family == 10 and route.type == 'multicast' and route.to == 'ff00::/8':
Expand Down
14 changes: 13 additions & 1 deletion tests/cli/test_state_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,19 @@ def test__filter_system_routes_dhcp_ra_routes(self):

def test__filter_system_routes_link_local_routes(self):
route = NetplanRoute(scope='host', type='local', to='1.2.3.4', from_addr='1.2.3.4')
filtered = self.diff_state._filter_system_routes({route}, [])
system_addresses = ['1.2.3.4/24']
filtered = self.diff_state._filter_system_routes({route}, system_addresses)
self.assertSetEqual(filtered, set())

def test__filter_system_routes_link_local_routes_with_multiple_ips_same_subnet(self):
# When an interface has multiple IPs in the same subnet the routing table will
# have routes using one of the IPs as source. Example:
# local 192.168.0.123 dev eth0 table local proto kernel scope host src 192.168.0.123
# local 192.168.0.124 dev eth0 table local proto kernel scope host src 192.168.0.123
route1 = NetplanRoute(scope='host', type='local', to='1.2.3.4', from_addr='1.2.3.4')
route2 = NetplanRoute(scope='host', type='local', to='1.2.3.5', from_addr='1.2.3.4')
system_addresses = ['1.2.3.4/24', '1.2.3.5/24']
filtered = self.diff_state._filter_system_routes({route1, route2}, system_addresses)
self.assertSetEqual(filtered, set())

def test__filter_system_routes_ipv6_multicast_routes(self):
Expand Down

0 comments on commit ebb7480

Please sign in to comment.