* [PATCH net] ipv6: set fc_protocol with 0 when rtm_protocol is RTPROT_REDIRECT
@ 2017-07-30 12:51 Xin Long
2017-07-31 2:35 ` David Ahern
0 siblings, 1 reply; 7+ messages in thread
From: Xin Long @ 2017-07-30 12:51 UTC (permalink / raw)
To: network dev; +Cc: davem, grawity
After commit c2ed1880fd61 ("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 when flushing caches with iproute, in
which all route caches get dumped from kernel then removed one by
one by sending RTM_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 found and removed.
As rt6_fill_node always sets rtm proto with RTPROT_REDIRECT when
rt cache info goes to rtmsg, the reverse process is needed when
users remove a route cache and rtmsg goes to cfg.
This patch is to fix it by keeping cfg proto as 0 when rtm proto
is REDIRECT. It's a safe fix as rtm proto is set with REDIRECT
only if rt flag has RTF_DYNAMIC which is set when creating a rt
cache in rt6_do_redirect where the cache's proto is always 0.
Note that this issue can also be avoided in iproute by changing
rtm proto back to 0 before sending DELROUTE requests for cache.
But in kernel part, the fix is still necessary as kernel should
do the reverse conversion when rtm goes to cfg.
Fixes: c2ed1880fd61 ("net: ipv6: check route protocol when deleting routes")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/ipv6/route.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 4d30c96..187580f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2912,9 +2912,11 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
cfg->fc_dst_len = rtm->rtm_dst_len;
cfg->fc_src_len = rtm->rtm_src_len;
cfg->fc_flags = RTF_UP;
- cfg->fc_protocol = rtm->rtm_protocol;
cfg->fc_type = rtm->rtm_type;
+ if (rtm->rtm_protocol != RTPROT_REDIRECT)
+ cfg->fc_protocol = rtm->rtm_protocol;
+
if (rtm->rtm_type == RTN_UNREACHABLE ||
rtm->rtm_type == RTN_BLACKHOLE ||
rtm->rtm_type == RTN_PROHIBIT ||
--
2.1.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH net] ipv6: set fc_protocol with 0 when rtm_protocol is RTPROT_REDIRECT
2017-07-30 12:51 [PATCH net] ipv6: set fc_protocol with 0 when rtm_protocol is RTPROT_REDIRECT Xin Long
@ 2017-07-31 2:35 ` David Ahern
2017-07-31 3:31 ` Xin Long
0 siblings, 1 reply; 7+ messages in thread
From: David Ahern @ 2017-07-31 2:35 UTC (permalink / raw)
To: Xin Long, network dev; +Cc: davem, grawity
On 7/30/17 6:51 AM, Xin Long wrote:
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index 4d30c96..187580f 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -2912,9 +2912,11 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
> cfg->fc_dst_len = rtm->rtm_dst_len;
> cfg->fc_src_len = rtm->rtm_src_len;
> cfg->fc_flags = RTF_UP;
> - cfg->fc_protocol = rtm->rtm_protocol;
> cfg->fc_type = rtm->rtm_type;
>
> + if (rtm->rtm_protocol != RTPROT_REDIRECT)
> + cfg->fc_protocol = rtm->rtm_protocol;
> +
> if (rtm->rtm_type == RTN_UNREACHABLE ||
> rtm->rtm_type == RTN_BLACKHOLE ||
> rtm->rtm_type == RTN_PROHIBIT ||
Did you look at removing this hunk from rt6_fill_node:
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;
}
And have rtm_protocol set properly on the route when it is installed?
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net] ipv6: set fc_protocol with 0 when rtm_protocol is RTPROT_REDIRECT
2017-07-31 2:35 ` David Ahern
@ 2017-07-31 3:31 ` Xin Long
2017-08-01 0:12 ` David Ahern
0 siblings, 1 reply; 7+ messages in thread
From: Xin Long @ 2017-07-31 3:31 UTC (permalink / raw)
To: David Ahern; +Cc: network dev, davem, Mantas Mikulėnas
On Mon, Jul 31, 2017 at 2:35 PM, David Ahern <dsahern@gmail.com> wrote:
> On 7/30/17 6:51 AM, Xin Long wrote:
>> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
>> index 4d30c96..187580f 100644
>> --- a/net/ipv6/route.c
>> +++ b/net/ipv6/route.c
>> @@ -2912,9 +2912,11 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
>> cfg->fc_dst_len = rtm->rtm_dst_len;
>> cfg->fc_src_len = rtm->rtm_src_len;
>> cfg->fc_flags = RTF_UP;
>> - cfg->fc_protocol = rtm->rtm_protocol;
>> cfg->fc_type = rtm->rtm_type;
>>
>> + if (rtm->rtm_protocol != RTPROT_REDIRECT)
>> + cfg->fc_protocol = rtm->rtm_protocol;
>> +
>> if (rtm->rtm_type == RTN_UNREACHABLE ||
>> rtm->rtm_type == RTN_BLACKHOLE ||
>> rtm->rtm_type == RTN_PROHIBIT ||
Hi, David
>
> Did you look at removing this hunk from rt6_fill_node:
>
> 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;
> }
The issue seems to affect "ip -6 route flush all" as well, not only cache
since 'else if {}' also causes rtm proto being different from rt6 proto.
>
> And have rtm_protocol set properly on the route when it is installed?
The codes not keeping rtm proto consistent with rt6 proto day 1,
any idea on why it didn't use rt6 proto in kernel properly?
Thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net] ipv6: set fc_protocol with 0 when rtm_protocol is RTPROT_REDIRECT
2017-07-31 3:31 ` Xin Long
@ 2017-08-01 0:12 ` David Ahern
2017-08-01 1:40 ` Xin Long
0 siblings, 1 reply; 7+ messages in thread
From: David Ahern @ 2017-08-01 0:12 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, davem, Mantas Mikulėnas
On 7/30/17 9:31 PM, Xin Long wrote:
>> Did you look at removing this hunk from rt6_fill_node:
>>
>> 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;
>> }
> The issue seems to affect "ip -6 route flush all" as well, not only cache
> since 'else if {}' also causes rtm proto being different from rt6 proto.
>
>>
>> And have rtm_protocol set properly on the route when it is installed?
> The codes not keeping rtm proto consistent with rt6 proto day 1,
> any idea on why it didn't use rt6 proto in kernel properly?
no, AFAIK it was just an oversight when the original code was written. I
do not know of any reason that would prevent properly setting the
rt6i_protocol in the route when it is allocated.
Something like this (not compiled, much less tested):
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 4d30c96a819d..9a928839d247 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2347,6 +2347,7 @@ static void rt6_do_redirect(struct dst_entry *dst,
struct sock *sk, struct sk_bu
if (!nrt)
goto out;
+ nrt->rt6i_protocol = RTPROT_REDIRECT;
nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE;
if (on_link)
nrt->rt6i_flags &= ~RTF_GATEWAY;
@@ -2461,6 +2462,7 @@ static struct rt6_info *rt6_add_route_info(struct
net *net,
.fc_dst_len = prefixlen,
.fc_flags = RTF_GATEWAY | RTF_ADDRCONF |
RTF_ROUTEINFO |
RTF_UP | RTF_PREF(pref),
+ .fc_protocol = RTPROT_RA,
.fc_nlinfo.portid = 0,
.fc_nlinfo.nlh = NULL,
.fc_nlinfo.nl_net = net,
@@ -2513,6 +2515,7 @@ struct rt6_info *rt6_add_dflt_router(const struct
in6_addr *gwaddr,
.fc_ifindex = dev->ifindex,
.fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
+ .fc_protocol = RTPROT_RA,
.fc_nlinfo.portid = 0,
.fc_nlinfo.nlh = NULL,
.fc_nlinfo.nl_net = dev_net(dev),
@@ -3424,14 +3427,6 @@ static int rt6_fill_node(struct net *net,
rtm->rtm_flags = 0;
rtm->rtm_scope = RT_SCOPE_UNIVERSE;
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)
rtm->rtm_flags |= RTM_F_CLONED;
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH net] ipv6: set fc_protocol with 0 when rtm_protocol is RTPROT_REDIRECT
2017-08-01 0:12 ` David Ahern
@ 2017-08-01 1:40 ` Xin Long
2017-08-01 2:01 ` David Ahern
0 siblings, 1 reply; 7+ messages in thread
From: Xin Long @ 2017-08-01 1:40 UTC (permalink / raw)
To: David Ahern; +Cc: network dev, davem, Mantas Mikulėnas
On Tue, Aug 1, 2017 at 12:12 PM, David Ahern <dsahern@gmail.com> wrote:
> On 7/30/17 9:31 PM, Xin Long wrote:
>>> Did you look at removing this hunk from rt6_fill_node:
>>>
>>> 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;
>>> }
>> The issue seems to affect "ip -6 route flush all" as well, not only cache
>> since 'else if {}' also causes rtm proto being different from rt6 proto.
>>
>>>
>>> And have rtm_protocol set properly on the route when it is installed?
>> The codes not keeping rtm proto consistent with rt6 proto day 1,
>> any idea on why it didn't use rt6 proto in kernel properly?
>
> no, AFAIK it was just an oversight when the original code was written. I
> do not know of any reason that would prevent properly setting the
> rt6i_protocol in the route when it is allocated.
That's what I was worried about, it might break something,
but double checked, should be fine.
>
> Something like this (not compiled, much less tested):
To respect the old code more, setting RTPROT_RA only when
it's with the flag (ADDRCONF | DEFAULT | ROUTEINFO),
shouldn't it be:
[...]
@@ -2464,6 +2465,7 @@ static struct rt6_info
*rt6_add_route_info(struct net *net,
.fc_nlinfo.portid = 0,
.fc_nlinfo.nlh = NULL,
.fc_nlinfo.nl_net = net,
+ .fc_protocol = RTPROT_KERNEL,
};
cfg.fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO,
@@ -2471,8 +2473,10 @@ static struct rt6_info
*rt6_add_route_info(struct net *net,
cfg.fc_gateway = *gwaddr;
/* We should treat it as a default route if prefix length is 0. */
- if (!prefixlen)
+ if (!prefixlen) {
+ cfg.fc_protocol = RTPROT_RA;
cfg.fc_flags |= RTF_DEFAULT;
+ }
ip6_route_add(&cfg, NULL);
@@ -2516,6 +2520,7 @@ struct rt6_info *rt6_add_dflt_router(const
struct in6_addr *gwaddr,
.fc_nlinfo.portid = 0,
.fc_nlinfo.nlh = NULL,
.fc_nlinfo.nl_net = dev_net(dev),
+ .fc_protocol = RTPROT_KERNEL,
};
[...]
or you changed it intentionally ?
I will do some testing before posting v2.
thanks for your suggestion. :-)
>
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index 4d30c96a819d..9a928839d247 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -2347,6 +2347,7 @@ static void rt6_do_redirect(struct dst_entry *dst,
> struct sock *sk, struct sk_bu
> if (!nrt)
> goto out;
>
> + nrt->rt6i_protocol = RTPROT_REDIRECT;
> nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE;
> if (on_link)
> nrt->rt6i_flags &= ~RTF_GATEWAY;
> @@ -2461,6 +2462,7 @@ static struct rt6_info *rt6_add_route_info(struct
> net *net,
> .fc_dst_len = prefixlen,
> .fc_flags = RTF_GATEWAY | RTF_ADDRCONF |
> RTF_ROUTEINFO |
> RTF_UP | RTF_PREF(pref),
> + .fc_protocol = RTPROT_RA,
> .fc_nlinfo.portid = 0,
> .fc_nlinfo.nlh = NULL,
> .fc_nlinfo.nl_net = net,
> @@ -2513,6 +2515,7 @@ struct rt6_info *rt6_add_dflt_router(const struct
> in6_addr *gwaddr,
> .fc_ifindex = dev->ifindex,
> .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
> RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
> + .fc_protocol = RTPROT_RA,
> .fc_nlinfo.portid = 0,
> .fc_nlinfo.nlh = NULL,
> .fc_nlinfo.nl_net = dev_net(dev),
> @@ -3424,14 +3427,6 @@ static int rt6_fill_node(struct net *net,
> rtm->rtm_flags = 0;
> rtm->rtm_scope = RT_SCOPE_UNIVERSE;
> 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)
> rtm->rtm_flags |= RTM_F_CLONED;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net] ipv6: set fc_protocol with 0 when rtm_protocol is RTPROT_REDIRECT
2017-08-01 1:40 ` Xin Long
@ 2017-08-01 2:01 ` David Ahern
2017-08-01 2:50 ` Xin Long
0 siblings, 1 reply; 7+ messages in thread
From: David Ahern @ 2017-08-01 2:01 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, davem, Mantas Mikulėnas
On 7/31/17 7:40 PM, Xin Long wrote:
> To respect the old code more, setting RTPROT_RA only when
> it's with the flag (ADDRCONF | DEFAULT | ROUTEINFO),
> shouldn't it be:
Look at rtm_fill_info:
if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ROUTEINFO))
rtm->rtm_protocol = RTPROT_RA;
If either flag is set the protocol should be RTPROT_RA and looking at
both places that seems correct to me.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net] ipv6: set fc_protocol with 0 when rtm_protocol is RTPROT_REDIRECT
2017-08-01 2:01 ` David Ahern
@ 2017-08-01 2:50 ` Xin Long
0 siblings, 0 replies; 7+ messages in thread
From: Xin Long @ 2017-08-01 2:50 UTC (permalink / raw)
To: David Ahern; +Cc: network dev, davem, Mantas Mikulėnas
On Tue, Aug 1, 2017 at 2:01 PM, David Ahern <dsahern@gmail.com> wrote:
> On 7/31/17 7:40 PM, Xin Long wrote:
>> To respect the old code more, setting RTPROT_RA only when
>> it's with the flag (ADDRCONF | DEFAULT | ROUTEINFO),
>> shouldn't it be:
>
> Look at rtm_fill_info:
>
> if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ROUTEINFO))
> rtm->rtm_protocol = RTPROT_RA;
>
>
> If either flag is set the protocol should be RTPROT_RA and looking at
> both places that seems correct to me.
>
ok, right
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-08-01 2:50 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-30 12:51 [PATCH net] ipv6: set fc_protocol with 0 when rtm_protocol is RTPROT_REDIRECT Xin Long
2017-07-31 2:35 ` David Ahern
2017-07-31 3:31 ` Xin Long
2017-08-01 0:12 ` David Ahern
2017-08-01 1:40 ` Xin Long
2017-08-01 2:01 ` David Ahern
2017-08-01 2:50 ` Xin Long
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).