Commit b91d5329 authored by Xin Long's avatar Xin Long Committed by David S. Miller

ipv6: set rt6i_protocol properly in the route when it is installed

After commit c2ed1880 ("net: ipv6: check route protocol when
deleting routes"), ipv6 route checks rt protocol when trying to
remove a rt entry.

It introduced a side effect causing 'ip -6 route flush cache' not
to work well. When flushing caches with iproute, all route caches
get dumped from kernel then removed one by one by sending DELROUTE
requests to kernel for each cache.

The thing is iproute sends the request with the cache whose proto
is set with RTPROT_REDIRECT by rt6_fill_node() when kernel dumps
it. But in kernel the rt_cache protocol is still 0, which causes
the cache not to be matched and removed.

So the real reason is rt6i_protocol in the route is not set when
it is allocated. As David Ahern's suggestion, this patch is to
set rt6i_protocol properly in the route when it is installed and
remove the codes setting rtm_protocol according to rt6i_flags in
rt6_fill_node.

This is also an improvement to keep rt6i_protocol consistent with
rtm_protocol.

Fixes: c2ed1880 ("net: ipv6: check route protocol when deleting routes")
Reported-by: default avatarJianlin Shi <jishi@redhat.com>
Suggested-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2dda6400
...@@ -2351,6 +2351,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu ...@@ -2351,6 +2351,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
if (on_link) if (on_link)
nrt->rt6i_flags &= ~RTF_GATEWAY; nrt->rt6i_flags &= ~RTF_GATEWAY;
nrt->rt6i_protocol = RTPROT_REDIRECT;
nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key; nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key;
if (ip6_ins_rt(nrt)) if (ip6_ins_rt(nrt))
...@@ -2461,6 +2462,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net, ...@@ -2461,6 +2462,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
.fc_dst_len = prefixlen, .fc_dst_len = prefixlen,
.fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
RTF_UP | RTF_PREF(pref), RTF_UP | RTF_PREF(pref),
.fc_protocol = RTPROT_RA,
.fc_nlinfo.portid = 0, .fc_nlinfo.portid = 0,
.fc_nlinfo.nlh = NULL, .fc_nlinfo.nlh = NULL,
.fc_nlinfo.nl_net = net, .fc_nlinfo.nl_net = net,
...@@ -2513,6 +2515,7 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr, ...@@ -2513,6 +2515,7 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
.fc_ifindex = dev->ifindex, .fc_ifindex = dev->ifindex,
.fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
RTF_UP | RTF_EXPIRES | RTF_PREF(pref), RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
.fc_protocol = RTPROT_RA,
.fc_nlinfo.portid = 0, .fc_nlinfo.portid = 0,
.fc_nlinfo.nlh = NULL, .fc_nlinfo.nlh = NULL,
.fc_nlinfo.nl_net = dev_net(dev), .fc_nlinfo.nl_net = dev_net(dev),
...@@ -3424,14 +3427,6 @@ static int rt6_fill_node(struct net *net, ...@@ -3424,14 +3427,6 @@ static int rt6_fill_node(struct net *net,
rtm->rtm_flags = 0; rtm->rtm_flags = 0;
rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_scope = RT_SCOPE_UNIVERSE;
rtm->rtm_protocol = rt->rt6i_protocol; rtm->rtm_protocol = rt->rt6i_protocol;
if (rt->rt6i_flags & RTF_DYNAMIC)
rtm->rtm_protocol = RTPROT_REDIRECT;
else if (rt->rt6i_flags & RTF_ADDRCONF) {
if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ROUTEINFO))
rtm->rtm_protocol = RTPROT_RA;
else
rtm->rtm_protocol = RTPROT_KERNEL;
}
if (rt->rt6i_flags & RTF_CACHE) if (rt->rt6i_flags & RTF_CACHE)
rtm->rtm_flags |= RTM_F_CLONED; rtm->rtm_flags |= RTM_F_CLONED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment