| From foo@baz Wed Mar 11 11:44:33 CET 2015 |
| From: Martin KaFai Lau <kafai@fb.com> |
| Date: Thu, 12 Feb 2015 16:14:08 -0800 |
| Subject: ipv6: fix ipv6_cow_metrics for non DST_HOST case |
| |
| From: Martin KaFai Lau <kafai@fb.com> |
| |
| [ Upstream commit 3b4711757d7903ab6fa88a9e7ab8901b8227da60 ] |
| |
| ipv6_cow_metrics() currently assumes only DST_HOST routes require |
| dynamic metrics allocation from inetpeer. The assumption breaks |
| when ndisc discovered router with RTAX_MTU and RTAX_HOPLIMIT metric. |
| Refer to ndisc_router_discovery() in ndisc.c and note that dst_metric_set() |
| is called after the route is created. |
| |
| This patch creates the metrics array (by calling dst_cow_metrics_generic) in |
| ipv6_cow_metrics(). |
| |
| Test: |
| radvd.conf: |
| interface qemubr0 |
| { |
| AdvLinkMTU 1300; |
| AdvCurHopLimit 30; |
| |
| prefix fd00:face:face:face::/64 |
| { |
| AdvOnLink on; |
| AdvAutonomous on; |
| AdvRouterAddr off; |
| }; |
| }; |
| |
| Before: |
| [root@qemu1 ~]# ip -6 r show | egrep -v unreachable |
| fd00:face:face:face::/64 dev eth0 proto kernel metric 256 expires 27sec |
| fe80::/64 dev eth0 proto kernel metric 256 |
| default via fe80::74df:d0ff:fe23:8ef2 dev eth0 proto ra metric 1024 expires 27sec |
| |
| After: |
| [root@qemu1 ~]# ip -6 r show | egrep -v unreachable |
| fd00:face:face:face::/64 dev eth0 proto kernel metric 256 expires 27sec mtu 1300 |
| fe80::/64 dev eth0 proto kernel metric 256 mtu 1300 |
| default via fe80::74df:d0ff:fe23:8ef2 dev eth0 proto ra metric 1024 expires 27sec mtu 1300 hoplimit 30 |
| |
| Fixes: 8e2ec639173f325 (ipv6: don't use inetpeer to store metrics for routes.) |
| Signed-off-by: Martin KaFai Lau <kafai@fb.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv6/route.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/net/ipv6/route.c |
| +++ b/net/ipv6/route.c |
| @@ -141,7 +141,7 @@ static u32 *ipv6_cow_metrics(struct dst_ |
| u32 *p = NULL; |
| |
| if (!(rt->dst.flags & DST_HOST)) |
| - return NULL; |
| + return dst_cow_metrics_generic(dst, old); |
| |
| peer = rt6_get_peer_create(rt); |
| if (peer) { |