Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8cfddaf authored by Hangbin Liu's avatar Hangbin Liu Committed by Greg Kroah-Hartman
Browse files

net/ipv6: need update peer route when modify metric



[ Upstream commit 617940123e0140521f3080d2befc2bf55bcda094 ]

When we modify the route metric, the peer address's route need also
be updated. Before the fix:

+ ip addr add dev dummy1 2001:db8::1 peer 2001:db8::2 metric 60
+ ip -6 route show dev dummy1
2001:db8::1 proto kernel metric 60 pref medium
2001:db8::2 proto kernel metric 60 pref medium
+ ip addr change dev dummy1 2001:db8::1 peer 2001:db8::2 metric 61
+ ip -6 route show dev dummy1
2001:db8::1 proto kernel metric 61 pref medium
2001:db8::2 proto kernel metric 60 pref medium

After the fix:
+ ip addr change dev dummy1 2001:db8::1 peer 2001:db8::2 metric 61
+ ip -6 route show dev dummy1
2001:db8::1 proto kernel metric 61 pref medium
2001:db8::2 proto kernel metric 61 pref medium

Fixes: 8308f3ff ("net/ipv6: Add support for specifying metric of connected routes")
Signed-off-by: default avatarHangbin Liu <liuhangbin@gmail.com>
Reviewed-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b5a8261a
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -4535,12 +4535,13 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
}

static int modify_prefix_route(struct inet6_ifaddr *ifp,
			       unsigned long expires, u32 flags)
			       unsigned long expires, u32 flags,
			       bool modify_peer)
{
	struct fib6_info *f6i;
	u32 prio;

	f6i = addrconf_get_prefix_route(&ifp->addr,
	f6i = addrconf_get_prefix_route(modify_peer ? &ifp->peer_addr : &ifp->addr,
					ifp->prefix_len,
					ifp->idev->dev,
					0, RTF_GATEWAY | RTF_DEFAULT);
@@ -4553,7 +4554,8 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp,
		ip6_del_rt(dev_net(ifp->idev->dev), f6i);

		/* add new one */
		addrconf_prefix_route(&ifp->addr, ifp->prefix_len,
		addrconf_prefix_route(modify_peer ? &ifp->peer_addr : &ifp->addr,
				      ifp->prefix_len,
				      ifp->rt_priority, ifp->idev->dev,
				      expires, flags, GFP_KERNEL);
	} else {
@@ -4629,7 +4631,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
		int rc = -ENOENT;

		if (had_prefixroute)
			rc = modify_prefix_route(ifp, expires, flags);
			rc = modify_prefix_route(ifp, expires, flags, false);

		/* prefix route could have been deleted; if so restore it */
		if (rc == -ENOENT) {
@@ -4637,6 +4639,15 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
					      ifp->rt_priority, ifp->idev->dev,
					      expires, flags, GFP_KERNEL);
		}

		if (had_prefixroute && !ipv6_addr_any(&ifp->peer_addr))
			rc = modify_prefix_route(ifp, expires, flags, true);

		if (rc == -ENOENT && !ipv6_addr_any(&ifp->peer_addr)) {
			addrconf_prefix_route(&ifp->peer_addr, ifp->prefix_len,
					      ifp->rt_priority, ifp->idev->dev,
					      expires, flags, GFP_KERNEL);
		}
	} else if (had_prefixroute) {
		enum cleanup_prefix_rt_t action;
		unsigned long rt_expires;