Skip to content

Conversation

hedrok
Copy link

@hedrok hedrok commented Sep 12, 2025

Fixes issue #13561

Linux kernel deletes IPv4 routes when last interface IPv4 address is deleted, but intentionally doesn't send RTM_DELROUTE in this case.

FRR has function rib_update_handle_kernel_route_down_possibility that handles setting interface down, but not removal of last address.

To fix the situation:

  • Add RIB_UPDATE_KERNEL_LAST_ADDRESS_DELETED to enum rib_update_event
  • In zebra_if_addr_update_ctx make more specific check that last address is deleted and trigger RIB_UPDATE_KERNEL_LAST_ADDRESS_DELETED instead of RIB_UPDATE_KERNEL in this case. If it was not last address, don't emit any RIB_UPDATE.
  • Call rib_update_handle_kernel_route_down_possibility not only for event RIB_UPDATE_INTERFACE_DOWN, but also for RIB_UPDATE_KERNEL_LAST_ADDRESS_DELETED.
  • Change rib_update_handle_kernel_route_down_possibility not to consider IPv4 route alive when interface is up, but there are no IPv4 addresses left.

Relevant kernel code:

  • net/ipv4/fib_frontend.c fib_inetaddr_event
  • net/ipv4/fib_semantics.c fib_sync_down_dev

Comment from kernel networking author that RTM_DELROUTE isn't sent intentionally:

Routing applications are expected to know that when an interface or address goes away the related routes disappear as well.

This is done as an optimization to avoid sending millions of netlink messages for large scale routers. It has always been this way since the first versions of netlink on Linux and will not change since it would break applications.

(Stephen Hemminger)

https://bugzilla.kernel.org/show_bug.cgi?id=207089

test

Also added test_zebra_kernel_last_ipv4_address_deleted to zebra_multiple_connected/test_zebra_multiple_connected.py with basic flow:

ip -4 addr flush dev {ifname}
ip -4 addr add 192.168.0.2/24 dev {ifname}
ip -4 route add default via 192.168.0.1
ip -4 addr add 192.168.100.7/24 dev {ifname}
ip -4 route add 10.0.170.3 dev {ifname}

Check there are default and 10.0.170.3 routes.

ip -4 addr del 192.168.0.2/24 dev {ifname}

Check there are still default and 10.0.170.3 routes.

ip -4 addr del 192.168.100.7/24 dev {ifname}

Check there are no default and 10.0.170.3 routes.

In each check make sure kernel routes are as expected (using topotest.ip4_route) and zebra routes are as expected (using show ip route json).

@frrbot frrbot bot added the zebra label Sep 12, 2025
@hedrok hedrok force-pushed the 13561-zebra-kernel-route-last-address-delete branch from 516000d to 28e0579 Compare September 13, 2025 01:06
@github-actions github-actions bot added size/L and removed size/M labels Sep 13, 2025
@hedrok hedrok marked this pull request as draft September 13, 2025 01:07
Fixes issue FRRouting#13561

Linux kernel deletes IPv4 routes when last interface IPv4 address
is deleted, but intentionally doesn't send RTM_DELROUTE in this case.

FRR has function rib_update_handle_kernel_route_down_possibility
that handles setting interface down, but not removal of last address.

To fix the situation:

* Add RIB_UPDATE_KERNEL_LAST_ADDRESS_DELETED to enum rib_update_event
* In zebra_if_addr_update_ctx make more specific check that last
  address is deleted and trigger RIB_UPDATE_KERNEL_LAST_ADDRESS_DELETED
  instead of RIB_UPDATE_KERNEL in this case. If it was not last address,
  don't emit any RIB_UPDATE.
* Call rib_update_handle_kernel_route_down_possibility not only
  for event RIB_UPDATE_INTERFACE_DOWN, but also for
  RIB_UPDATE_KERNEL_LAST_ADDRESS_DELETED.
* Change rib_update_handle_kernel_route_down_possibility not to
  consider IPv4 route alive when interface is up, but there
  are no IPv4 addresses left.

Relevant kernel code:

* net/ipv4/fib_frontend.c fib_inetaddr_event
* net/ipv4/fib_semantics.c fib_sync_down_dev

Comment from kernel networking author that RTM_DELROUTE isn't sent
intentionally:

https://bugzilla.kernel.org/show_bug.cgi?id=207089
Signed-off-by: Kyrylo Yatsenko <[email protected]>
@hedrok hedrok force-pushed the 13561-zebra-kernel-route-last-address-delete branch 2 times, most recently from a68bb7d to 42eee42 Compare September 13, 2025 08:04
Add test that checks kernel routes behaviour on last address deletion.

See FRRouting#13561

Signed-off-by: Kyrylo Yatsenko <[email protected]>
@hedrok hedrok force-pushed the 13561-zebra-kernel-route-last-address-delete branch from 42eee42 to 6bad366 Compare September 13, 2025 13:25
@hedrok hedrok marked this pull request as ready for review September 13, 2025 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant