Skip to content

Commit 25fb6ca

Browse files
0xba1adavem330
authored andcommitted
net IPv6 : Fix broken IPv6 routing table after loopback down-up
IPv6 Routing table becomes broken once we do ifdown, ifup of the loopback(lo) interface. After down-up, routes of other interface's IPv6 addresses through 'lo' are lost. IPv6 addresses assigned to all interfaces are routed through 'lo' for internal communication. Once 'lo' is down, those routing entries are removed from routing table. But those removed entries are not being re-created properly when 'lo' is brought up. So IPv6 addresses of other interfaces becomes unreachable from the same machine. Also this breaks communication with other machines because of NDISC packet processing failure. This patch fixes this issue by reading all interface's IPv6 addresses and adding them to IPv6 routing table while bringing up 'lo'. ==Testing== Before applying the patch: $ route -A inet6 Kernel IPv6 routing table Destination Next Hop Flag Met Ref Use If 2000::20/128 :: U 256 0 0 eth0 fe80::/64 :: U 256 0 0 eth0 ::/0 :: !n -1 1 1 lo ::1/128 :: Un 0 1 0 lo 2000::20/128 :: Un 0 1 0 lo fe80::xxxx:xxxx:xxxx:xxxx/128 :: Un 0 1 0 lo ff00::/8 :: U 256 0 0 eth0 ::/0 :: !n -1 1 1 lo $ sudo ifdown lo $ sudo ifup lo $ route -A inet6 Kernel IPv6 routing table Destination Next Hop Flag Met Ref Use If 2000::20/128 :: U 256 0 0 eth0 fe80::/64 :: U 256 0 0 eth0 ::/0 :: !n -1 1 1 lo ::1/128 :: Un 0 1 0 lo ff00::/8 :: U 256 0 0 eth0 ::/0 :: !n -1 1 1 lo $ After applying the patch: $ route -A inet6 Kernel IPv6 routing table Destination Next Hop Flag Met Ref Use If 2000::20/128 :: U 256 0 0 eth0 fe80::/64 :: U 256 0 0 eth0 ::/0 :: !n -1 1 1 lo ::1/128 :: Un 0 1 0 lo 2000::20/128 :: Un 0 1 0 lo fe80::xxxx:xxxx:xxxx:xxxx/128 :: Un 0 1 0 lo ff00::/8 :: U 256 0 0 eth0 ::/0 :: !n -1 1 1 lo $ sudo ifdown lo $ sudo ifup lo $ route -A inet6 Kernel IPv6 routing table Destination Next Hop Flag Met Ref Use If 2000::20/128 :: U 256 0 0 eth0 fe80::/64 :: U 256 0 0 eth0 ::/0 :: !n -1 1 1 lo ::1/128 :: Un 0 1 0 lo 2000::20/128 :: Un 0 1 0 lo fe80::xxxx:xxxx:xxxx:xxxx/128 :: Un 0 1 0 lo ff00::/8 :: U 256 0 0 eth0 ::/0 :: !n -1 1 1 lo $ Signed-off-by: Balakumaran Kannan <Balakumaran.Kannan@ap.sony.com> Signed-off-by: Maruthi Thotad <Maruthi.Thotad@ap.sony.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f0f6ee1 commit 25fb6ca

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

net/ipv6/addrconf.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,6 +2529,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
25292529
static void init_loopback(struct net_device *dev)
25302530
{
25312531
struct inet6_dev *idev;
2532+
struct net_device *sp_dev;
2533+
struct inet6_ifaddr *sp_ifa;
2534+
struct rt6_info *sp_rt;
25322535

25332536
/* ::1 */
25342537

@@ -2540,6 +2543,30 @@ static void init_loopback(struct net_device *dev)
25402543
}
25412544

25422545
add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
2546+
2547+
/* Add routes to other interface's IPv6 addresses */
2548+
for_each_netdev(dev_net(dev), sp_dev) {
2549+
if (!strcmp(sp_dev->name, dev->name))
2550+
continue;
2551+
2552+
idev = __in6_dev_get(sp_dev);
2553+
if (!idev)
2554+
continue;
2555+
2556+
read_lock_bh(&idev->lock);
2557+
list_for_each_entry(sp_ifa, &idev->addr_list, if_list) {
2558+
2559+
if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
2560+
continue;
2561+
2562+
sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
2563+
2564+
/* Failure cases are ignored */
2565+
if (!IS_ERR(sp_rt))
2566+
ip6_ins_rt(sp_rt);
2567+
}
2568+
read_unlock_bh(&idev->lock);
2569+
}
25432570
}
25442571

25452572
static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr)

0 commit comments

Comments
 (0)