Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipv4/fib: send notify when delete source address routes

After deleting an interface address in fib_del_ifaddr(), the function
scans the fib_info list for stray entries and calls fib_flush() and
fib_table_flush(). Then the stray entries will be deleted silently and no
RTM_DELROUTE notification will be sent.

This lack of notification can make routing daemons, or monitor like
`ip monitor route` miss the routing changes. e.g.

+ ip link add dummy1 type dummy
+ ip link add dummy2 type dummy
+ ip link set dummy1 up
+ ip link set dummy2 up
+ ip addr add 192.168.5.5/24 dev dummy1
+ ip route add 7.7.7.0/24 dev dummy2 src 192.168.5.5
+ ip -4 route
7.7.7.0/24 dev dummy2 scope link src 192.168.5.5
192.168.5.0/24 dev dummy1 proto kernel scope link src 192.168.5.5
+ ip monitor route
+ ip addr del 192.168.5.5/24 dev dummy1
Deleted 192.168.5.0/24 dev dummy1 proto kernel scope link src 192.168.5.5
Deleted broadcast 192.168.5.255 dev dummy1 table local proto kernel scope link src 192.168.5.5
Deleted local 192.168.5.5 dev dummy1 table local proto kernel scope host src 192.168.5.5

As Ido reminded, fib_table_flush() isn't only called when an address is
deleted, but also when an interface is deleted or put down. The lack of
notification in these cases is deliberate. And commit 7c6bb7d2faaf
("net/ipv6: Add knob to skip DELROUTE message on device down") introduced
a sysctl to make IPv6 behave like IPv4 in this regard. So we can't send
the route delete notify blindly in fib_table_flush().

To fix this issue, let's add a new flag in "struct fib_info" to track the
deleted prefer source address routes, and only send notify for them.

After update:
+ ip monitor route
+ ip addr del 192.168.5.5/24 dev dummy1
Deleted 192.168.5.0/24 dev dummy1 proto kernel scope link src 192.168.5.5
Deleted broadcast 192.168.5.255 dev dummy1 table local proto kernel scope link src 192.168.5.5
Deleted local 192.168.5.5 dev dummy1 table local proto kernel scope host src 192.168.5.5
Deleted 7.7.7.0/24 dev dummy2 scope link src 192.168.5.5

Suggested-by: Thomas Haller <thaller@redhat.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://lore.kernel.org/r/20230922075508.848925-1-liuhangbin@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Hangbin Liu and committed by
Paolo Abeni
4b2b6060 6a70e5cb

+6
+1
include/net/ip_fib.h
··· 154 154 int fib_nhs; 155 155 bool fib_nh_is_v6; 156 156 bool nh_updated; 157 + bool pfsrc_removed; 157 158 struct nexthop *nh; 158 159 struct rcu_head rcu; 159 160 struct fib_nh fib_nh[];
+1
net/ipv4/fib_semantics.c
··· 1887 1887 continue; 1888 1888 if (fi->fib_prefsrc == local) { 1889 1889 fi->fib_flags |= RTNH_F_DEAD; 1890 + fi->pfsrc_removed = true; 1890 1891 ret++; 1891 1892 } 1892 1893 }
+4
net/ipv4/fib_trie.c
··· 2027 2027 int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) 2028 2028 { 2029 2029 struct trie *t = (struct trie *)tb->tb_data; 2030 + struct nl_info info = { .nl_net = net }; 2030 2031 struct key_vector *pn = t->kv; 2031 2032 unsigned long cindex = 1; 2032 2033 struct hlist_node *tmp; ··· 2090 2089 2091 2090 fib_notify_alias_delete(net, n->key, &n->leaf, fa, 2092 2091 NULL); 2092 + if (fi->pfsrc_removed) 2093 + rtmsg_fib(RTM_DELROUTE, htonl(n->key), fa, 2094 + KEYLENGTH - fa->fa_slen, tb->tb_id, &info, 0); 2093 2095 hlist_del_rcu(&fa->fa_list); 2094 2096 fib_release_info(fa->fa_info); 2095 2097 alias_free_mem_rcu(fa);