ipv6: Change addrconf_f6i_alloc to use ip6_route_info_create
authorDavid Ahern <dsahern@gmail.com>
Thu, 21 Mar 2019 12:21:35 +0000 (05:21 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 21 Mar 2019 17:16:54 +0000 (10:16 -0700)
Change addrconf_f6i_alloc to generate a fib6_config and call
ip6_route_info_create. addrconf_f6i_alloc is the last caller to
fib6_info_alloc besides ip6_route_info_create, and there is no
reason for it to do its own initialization on a fib6_info.

Host routes need to be created even if the device is down, so add a
new flag, fc_ignore_dev_down, to fib6_config and update fib6_nh_init
to not error out if device is not up.

Notes on the conversion:
- ip_fib_metrics_init is the same as fib6_config has fc_mx set to NULL
  and fc_mx_len set to 0
- dst_nocount is handled by the RTF_ADDRCONF flag
- dst_host is handled by fc_dst_len = 128

nh_gw does not get set after the conversion to ip6_route_info_create
but it should not be set in addrconf_f6i_alloc since this is a host
route not a gateway route.

Everything else is a straight forward map between fib6_info and
fib6_config.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip6_fib.h
net/ipv6/route.c

index 8409701..2acb78a 100644 (file)
@@ -50,7 +50,8 @@ struct fib6_config {
        u32             fc_protocol;
        u16             fc_type;        /* only 8 bits are used */
        u16             fc_delete_all_nh : 1,
-                       __unused : 15;
+                       fc_ignore_dev_down:1,
+                       __unused : 14;
 
        struct in6_addr fc_dst;
        struct in6_addr fc_src;
index b9df5f8..0c8c148 100644 (file)
@@ -3079,7 +3079,7 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
                goto out;
        }
 
-       if (!(dev->flags & IFF_UP)) {
+       if (!(dev->flags & IFF_UP) && !cfg->fc_ignore_dev_down) {
                NL_SET_ERR_MSG(extack, "Nexthop device is not up");
                err = -ENETDOWN;
                goto out;
@@ -3712,36 +3712,26 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
                                     const struct in6_addr *addr,
                                     bool anycast, gfp_t gfp_flags)
 {
-       u32 tb_id;
-       struct net_device *dev = idev->dev;
-       struct fib6_info *f6i;
-
-       f6i = fib6_info_alloc(gfp_flags);
-       if (!f6i)
-               return ERR_PTR(-ENOMEM);
+       struct fib6_config cfg = {
+               .fc_table = l3mdev_fib_table(idev->dev) ? : RT6_TABLE_LOCAL,
+               .fc_ifindex = idev->dev->ifindex,
+               .fc_flags = RTF_UP | RTF_ADDRCONF | RTF_NONEXTHOP,
+               .fc_dst = *addr,
+               .fc_dst_len = 128,
+               .fc_protocol = RTPROT_KERNEL,
+               .fc_nlinfo.nl_net = net,
+               .fc_ignore_dev_down = true,
+       };
 
-       f6i->fib6_metrics = ip_fib_metrics_init(net, NULL, 0, NULL);
-       f6i->dst_nocount = true;
-       f6i->dst_host = true;
-       f6i->fib6_protocol = RTPROT_KERNEL;
-       f6i->fib6_flags = RTF_UP | RTF_NONEXTHOP;
        if (anycast) {
-               f6i->fib6_type = RTN_ANYCAST;
-               f6i->fib6_flags |= RTF_ANYCAST;
+               cfg.fc_type = RTN_ANYCAST;
+               cfg.fc_flags |= RTF_ANYCAST;
        } else {
-               f6i->fib6_type = RTN_LOCAL;
-               f6i->fib6_flags |= RTF_LOCAL;
+               cfg.fc_type = RTN_LOCAL;
+               cfg.fc_flags |= RTF_LOCAL;
        }
 
-       f6i->fib6_nh.nh_gw = *addr;
-       dev_hold(dev);
-       f6i->fib6_nh.nh_dev = dev;
-       f6i->fib6_dst.addr = *addr;
-       f6i->fib6_dst.plen = 128;
-       tb_id = l3mdev_fib_table(idev->dev) ? : RT6_TABLE_LOCAL;
-       f6i->fib6_table = fib6_get_table(net, tb_id);
-
-       return f6i;
+       return ip6_route_info_create(&cfg, gfp_flags, NULL);
 }
 
 /* remove deleted ip from prefsrc entries */