From: Vincent Bernat <hidden> Date: 2016-09-16 12:55:45
Commit 8c14586fc320 ("net: ipv6: Use passed in table for nexthop
lookups") introduced a regression: insertion of an IPv6 route in a table
not containing the appropriate connected route for the gateway but which
contained a non-connected route (like a default gateway) fails while it
was previously working:
$ ip link add eth0 type dummy
$ ip link set up dev eth0
$ ip addr add 2001:db8::1/64 dev eth0
$ ip route add ::/0 via 2001:db8::5 dev eth0 table 20
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
RTNETLINK answers: No route to host
$ ip -6 route show table 20
default via 2001:db8::5 dev eth0 metric 1024 pref medium
After this patch, we get:
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
$ ip -6 route show table 20
2001:db8:cafe::1 via 2001:db8::6 dev eth0 metric 1024 pref medium
default via 2001:db8::5 dev eth0 metric 1024 pref medium
Signed-off-by: Vincent Bernat <redacted>
---
net/ipv6/route.c | 48 +++++++++++++++++++++++++++---------------------
1 file changed, 27 insertions(+), 21 deletions(-)
From: David Ahern <hidden> Date: 2016-09-16 18:36:07
On 9/16/16 6:55 AM, Vincent Bernat wrote:
Commit 8c14586fc320 ("net: ipv6: Use passed in table for nexthop
lookups") introduced a regression: insertion of an IPv6 route in a table
not containing the appropriate connected route for the gateway but which
contained a non-connected route (like a default gateway) fails while it
was previously working:
$ ip link add eth0 type dummy
$ ip link set up dev eth0
$ ip addr add 2001:db8::1/64 dev eth0
$ ip route add ::/0 via 2001:db8::5 dev eth0 table 20
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
RTNETLINK answers: No route to host
$ ip -6 route show table 20
default via 2001:db8::5 dev eth0 metric 1024 pref medium
so your table 20 is not complete in that it lacks a connected route to resolve 2001:db8::6 as a nexthop, so you are relying on a fallback to other tables (main in this case).
-----8<-----
- if (!(grt->rt6i_flags & RTF_GATEWAY))
- err = 0;
This is the check that is failing for your use case. ip6_nh_lookup_table is returning the default route and nexthops can not rely on a gateway. Given that a simpler and more direct change is (whitespace mangled on paste):
@@ -1991,9 +1991,19 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg)if(!(gwa_type&IPV6_ADDR_UNICAST))gotoout;-if(cfg->fc_table)+if(cfg->fc_table){grt=ip6_nh_lookup_table(net,cfg,gw_addr);+/* a nexthop lookup can not go through a gw.+*ifthishappensonatablebasedlookup+*thenfallbacktoafulllookup+*/+if(grt&&grt->rt6i_flags&RTF_GATEWAY){+ip6_rt_put(grt);+grt=NULL;+}+}+if(!grt)grt=rt6_lookup(net,gw_addr,NULL,cfg->fc_ifindex,1);
From: Vincent Bernat <hidden> Date: 2016-09-16 19:15:19
❦ 16 septembre 2016 20:36 CEST, David Ahern [off-list ref] :
quoted
contained a non-connected route (like a default gateway) fails while it
was previously working:
$ ip link add eth0 type dummy
$ ip link set up dev eth0
$ ip addr add 2001:db8::1/64 dev eth0
$ ip route add ::/0 via 2001:db8::5 dev eth0 table 20
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
RTNETLINK answers: No route to host
$ ip -6 route show table 20
default via 2001:db8::5 dev eth0 metric 1024 pref medium
so your table 20 is not complete in that it lacks a connected route to
resolve 2001:db8::6 as a nexthop, so you are relying on a fallback to
other tables (main in this case).
- if (!(grt->rt6i_flags & RTF_GATEWAY))
- err = 0;
This is the check that is failing for your use
case. ip6_nh_lookup_table is returning the default route and nexthops
can not rely on a gateway. Given that a simpler and more direct change
is (whitespace mangled on paste):
@@ -1991,9 +1991,19 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg)if(!(gwa_type&IPV6_ADDR_UNICAST))gotoout;-if(cfg->fc_table)+if(cfg->fc_table){grt=ip6_nh_lookup_table(net,cfg,gw_addr);+/* a nexthop lookup can not go through a gw.+*ifthishappensonatablebasedlookup+*thenfallbacktoafulllookup+*/+if(grt&&grt->rt6i_flags&RTF_GATEWAY){+ip6_rt_put(grt);+grt=NULL;+}+}+if(!grt)grt=rt6_lookup(net,gw_addr,NULL,cfg->fc_ifindex,1);
OK. Should the dev check be dismissed or do we add "dev && dev !=
grt->dst.dev" just as a safety net (this would be a convulated setup,
but the correct direct route could be in an ip rule with higher priority
while the one in this table is incorrect)?
--
"... an experienced, industrious, ambitious, and often quite often
picturesque liar."
-- Mark Twain
@@ -1991,9 +1991,19 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg)if(!(gwa_type&IPV6_ADDR_UNICAST))gotoout;-if(cfg->fc_table)+if(cfg->fc_table){grt=ip6_nh_lookup_table(net,cfg,gw_addr);+/* a nexthop lookup can not go through a gw.+*ifthishappensonatablebasedlookup+*thenfallbacktoafulllookup+*/+if(grt&&grt->rt6i_flags&RTF_GATEWAY){+ip6_rt_put(grt);+grt=NULL;+}+}+if(!grt)grt=rt6_lookup(net,gw_addr,NULL,cfg->fc_ifindex,1);
OK. Should the dev check be dismissed or do we add "dev && dev !=
grt->dst.dev" just as a safety net (this would be a convulated setup,
but the correct direct route could be in an ip rule with higher priority
while the one in this table is incorrect)?
yes. So the validity check becomes:
grt = ip6_nh_lookup_table(net, cfg, gw_addr);
if (grt) {
if (grt->rt6i_flags & RTF_GATEWAY ||
dev && dev != grt->dst.dev) {
ip6_rt_put(grt);
grt = NULL; <---- causes the full rt6_lookup
}
}
From: Vincent Bernat <hidden> Date: 2016-09-16 20:34:19
Commit 8c14586fc320 ("net: ipv6: Use passed in table for nexthop
lookups") introduced a regression: insertion of an IPv6 route in a table
not containing the appropriate connected route for the gateway but which
contained a non-connected route (like a default gateway) fails while it
was previously working:
$ ip link add eth0 type dummy
$ ip link set up dev eth0
$ ip addr add 2001:db8::1/64 dev eth0
$ ip route add ::/0 via 2001:db8::5 dev eth0 table 20
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
RTNETLINK answers: No route to host
$ ip -6 route show table 20
default via 2001:db8::5 dev eth0 metric 1024 pref medium
After this patch, we get:
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
$ ip -6 route show table 20
2001:db8:cafe::1 via 2001:db8::6 dev eth0 metric 1024 pref medium
default via 2001:db8::5 dev eth0 metric 1024 pref medium
Signed-off-by: Vincent Bernat <redacted>
---
net/ipv6/route.c | 8 ++++++++
1 file changed, 8 insertions(+)
From: David Ahern <hidden> Date: 2016-09-18 15:12:55
On 9/16/16 2:33 PM, Vincent Bernat wrote:
Commit 8c14586fc320 ("net: ipv6: Use passed in table for nexthop
lookups") introduced a regression: insertion of an IPv6 route in a table
not containing the appropriate connected route for the gateway but which
contained a non-connected route (like a default gateway) fails while it
was previously working:
$ ip link add eth0 type dummy
$ ip link set up dev eth0
$ ip addr add 2001:db8::1/64 dev eth0
$ ip route add ::/0 via 2001:db8::5 dev eth0 table 20
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
RTNETLINK answers: No route to host
$ ip -6 route show table 20
default via 2001:db8::5 dev eth0 metric 1024 pref medium
After this patch, we get:
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
$ ip -6 route show table 20
2001:db8:cafe::1 via 2001:db8::6 dev eth0 metric 1024 pref medium
default via 2001:db8::5 dev eth0 metric 1024 pref medium
need an explicit Fixes tag here:
Fixes: 8c14586fc320 ("net: ipv6: Use passed in table for nexthop lookups")
From: Vincent Bernat <hidden> Date: 2016-09-18 15:46:17
Commit 8c14586fc320 ("net: ipv6: Use passed in table for nexthop
lookups") introduced a regression: insertion of an IPv6 route in a table
not containing the appropriate connected route for the gateway but which
contained a non-connected route (like a default gateway) fails while it
was previously working:
$ ip link add eth0 type dummy
$ ip link set up dev eth0
$ ip addr add 2001:db8::1/64 dev eth0
$ ip route add ::/0 via 2001:db8::5 dev eth0 table 20
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
RTNETLINK answers: No route to host
$ ip -6 route show table 20
default via 2001:db8::5 dev eth0 metric 1024 pref medium
After this patch, we get:
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
$ ip -6 route show table 20
2001:db8:cafe::1 via 2001:db8::6 dev eth0 metric 1024 pref medium
default via 2001:db8::5 dev eth0 metric 1024 pref medium
Fixes: 8c14586fc320 ("net: ipv6: Use passed in table for nexthop lookups")
Signed-off-by: Vincent Bernat <redacted>
---
net/ipv6/route.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
From: David Ahern <hidden> Date: 2016-09-18 15:48:02
On 9/18/16 9:46 AM, Vincent Bernat wrote:
Commit 8c14586fc320 ("net: ipv6: Use passed in table for nexthop
lookups") introduced a regression: insertion of an IPv6 route in a table
not containing the appropriate connected route for the gateway but which
contained a non-connected route (like a default gateway) fails while it
was previously working:
$ ip link add eth0 type dummy
$ ip link set up dev eth0
$ ip addr add 2001:db8::1/64 dev eth0
$ ip route add ::/0 via 2001:db8::5 dev eth0 table 20
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
RTNETLINK answers: No route to host
$ ip -6 route show table 20
default via 2001:db8::5 dev eth0 metric 1024 pref medium
After this patch, we get:
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
$ ip -6 route show table 20
2001:db8:cafe::1 via 2001:db8::6 dev eth0 metric 1024 pref medium
default via 2001:db8::5 dev eth0 metric 1024 pref medium
Fixes: 8c14586fc320 ("net: ipv6: Use passed in table for nexthop lookups")
Signed-off-by: Vincent Bernat <redacted>
---
net/ipv6/route.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
Acked-by: David Ahern <redacted>
Tested-by: David Ahern <redacted>
@@ -1808,6 +1808,30 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net, return rt; }+static int ip6_nh_valid(struct rt6_info *grt,+ struct net_device **dev, struct inet6_dev **idev) {+ int ret = 0;
First, this is not formatted properly. The openning brace should start
on a new line.
Second, please use "bool", "true", and "false" for the return value.
Thanks.
From: Vincent Bernat <hidden> Date: 2016-09-19 20:27:37
❦ 19 septembre 2016 06:58 CEST, David Miller [off-list ref] :
quoted
@@ -1808,6 +1808,30 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net, return rt; }+static int ip6_nh_valid(struct rt6_info *grt,+ struct net_device **dev, struct inet6_dev **idev) {+ int ret = 0;
First, this is not formatted properly. The openning brace should start
on a new line.
Second, please use "bool", "true", and "false" for the return value.
Noted for the next time. However, the v3 version of the patch doesn't
have the function anymore.
--
Avoid temporary variables.
- The Elements of Programming Style (Kernighan & Plauger)
Commit 8c14586fc320 ("net: ipv6: Use passed in table for nexthop
lookups") introduced a regression: insertion of an IPv6 route in a table
not containing the appropriate connected route for the gateway but which
contained a non-connected route (like a default gateway) fails while it
was previously working:
$ ip link add eth0 type dummy
$ ip link set up dev eth0
$ ip addr add 2001:db8::1/64 dev eth0
$ ip route add ::/0 via 2001:db8::5 dev eth0 table 20
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
RTNETLINK answers: No route to host
$ ip -6 route show table 20
default via 2001:db8::5 dev eth0 metric 1024 pref medium
After this patch, we get:
$ ip route add 2001:db8:cafe::1/128 via 2001:db8::6 dev eth0 table 20
$ ip -6 route show table 20
2001:db8:cafe::1 via 2001:db8::6 dev eth0 metric 1024 pref medium
default via 2001:db8::5 dev eth0 metric 1024 pref medium
Fixes: 8c14586fc320 ("net: ipv6: Use passed in table for nexthop lookups")
Signed-off-by: Vincent Bernat <redacted>