aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a2d6f6c242af..b1169d511ab4 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3170,9 +3170,35 @@ static void addrconf_gre_config(struct net_device *dev)
}
#endif
+#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
+/* If the host route is cached on the addr struct make sure it is associated
+ * with the proper table. e.g., enslavement can change and if so the cached
+ * host route needs to move to the new table.
+ */
+static void l3mdev_check_host_rt(struct inet6_dev *idev,
+ struct inet6_ifaddr *ifp)
+{
+ if (ifp->rt) {
+ u32 tb_id = l3mdev_fib_table(idev->dev) ? : RT6_TABLE_LOCAL;
+
+ if (tb_id != ifp->rt->rt6i_table->tb6_id) {
+ ip6_del_rt(ifp->rt);
+ ifp->rt = NULL;
+ }
+ }
+}
+#else
+static void l3mdev_check_host_rt(struct inet6_dev *idev,
+ struct inet6_ifaddr *ifp)
+{
+}
+#endif
+
static int fixup_permanent_addr(struct inet6_dev *idev,
struct inet6_ifaddr *ifp)
{
+ l3mdev_check_host_rt(idev, ifp);
+
if (!ifp->rt) {
struct rt6_info *rt;