diff mbox series

[PATCHv4,net] ipv4/fib: send notify when delete source address routes

Message ID 20230922075508.848925-1-liuhangbin@gmail.com (mailing list archive)
State Accepted
Commit 4b2b606075e50cdae62ab2356b0a1e206947c354
Delegated to: Netdev Maintainers
Headers show
Series [PATCHv4,net] ipv4/fib: send notify when delete source address routes | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/fixes_present fail Series targets non-next tree, but doesn't contain any Fixes tags
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 3139 this patch: 3139
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/build_clang success Errors and warnings before: 1546 this patch: 1546
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 3380 this patch: 3380
netdev/checkpatch warning WARNING: line length of 88 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Hangbin Liu Sept. 22, 2023, 7:55 a.m. UTC
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>
---
v4: As David Ahern said, do not use bitfield as it has higher overhead.
v3: update patch description
v2: Add a bit in fib_info to mark the deleted src route.
---
 include/net/ip_fib.h     | 1 +
 net/ipv4/fib_semantics.c | 1 +
 net/ipv4/fib_trie.c      | 4 ++++
 3 files changed, 6 insertions(+)

Comments

Nicolas Dichtel Sept. 22, 2023, 3:51 p.m. UTC | #1
Le 22/09/2023 à 09:55, Hangbin Liu a écrit :
> 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>
David Ahern Oct. 2, 2023, 8:07 p.m. UTC | #2
On 9/22/23 1:55 AM, Hangbin Liu wrote:
> 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>
> ---
> v4: As David Ahern said, do not use bitfield as it has higher overhead.
> v3: update patch description
> v2: Add a bit in fib_info to mark the deleted src route.
> ---
>  include/net/ip_fib.h     | 1 +
>  net/ipv4/fib_semantics.c | 1 +
>  net/ipv4/fib_trie.c      | 4 ++++
>  3 files changed, 6 insertions(+)
> 

Reviewed-by: David Ahern <dsahern@kernel.org>
patchwork-bot+netdevbpf@kernel.org Oct. 3, 2023, 7:20 a.m. UTC | #3
Hello:

This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Fri, 22 Sep 2023 15:55:08 +0800 you wrote:
> 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.
> 
> [...]

Here is the summary with links:
  - [PATCHv4,net] ipv4/fib: send notify when delete source address routes
    https://git.kernel.org/netdev/net/c/4b2b606075e5

You are awesome, thank you!
diff mbox series

Patch

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index f0c13864180e..15de07d36540 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -154,6 +154,7 @@  struct fib_info {
 	int			fib_nhs;
 	bool			fib_nh_is_v6;
 	bool			nh_updated;
+	bool			pfsrc_removed;
 	struct nexthop		*nh;
 	struct rcu_head		rcu;
 	struct fib_nh		fib_nh[];
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index eafa4a033515..1ea82bc33ef1 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1887,6 +1887,7 @@  int fib_sync_down_addr(struct net_device *dev, __be32 local)
 			continue;
 		if (fi->fib_prefsrc == local) {
 			fi->fib_flags |= RTNH_F_DEAD;
+			fi->pfsrc_removed = true;
 			ret++;
 		}
 	}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index d13fb9e76b97..9bdfdab906fe 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2027,6 +2027,7 @@  void fib_table_flush_external(struct fib_table *tb)
 int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
 {
 	struct trie *t = (struct trie *)tb->tb_data;
+	struct nl_info info = { .nl_net = net };
 	struct key_vector *pn = t->kv;
 	unsigned long cindex = 1;
 	struct hlist_node *tmp;
@@ -2089,6 +2090,9 @@  int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
 
 			fib_notify_alias_delete(net, n->key, &n->leaf, fa,
 						NULL);
+			if (fi->pfsrc_removed)
+				rtmsg_fib(RTM_DELROUTE, htonl(n->key), fa,
+					  KEYLENGTH - fa->fa_slen, tb->tb_id, &info, 0);
 			hlist_del_rcu(&fa->fa_list);
 			fib_release_info(fa->fa_info);
 			alias_free_mem_rcu(fa);