net: common metrics init helper for FIB entries
authorDavid Ahern <dsahern@gmail.com>
Fri, 5 Oct 2018 03:07:51 +0000 (20:07 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 5 Oct 2018 04:54:03 +0000 (21:54 -0700)
Consolidate initialization of ipv4 and ipv6 metrics when fib entries
are created into a single helper, ip_fib_metrics_init, that handles
the call to ip_metrics_convert.

If no metrics are defined for the fib entry, then the metrics is set
to dst_default_metrics.

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

index e44b1a44f67ad447528f1c59f05915157e016154..8cbe7e8c9e1e06e347163d077e03b5cb327fc015 100644 (file)
@@ -420,8 +420,8 @@ static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
        return min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
 }
 
-int ip_metrics_convert(struct net *net, struct nlattr *fc_mx, int fc_mx_len,
-                      u32 *metrics);
+struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
+                                       int fc_mx_len);
 
 u32 ip_idents_reserve(u32 hash, int segs);
 void __ip_select_ident(struct net *net, struct iphdr *iph, int segs);
index bee8db979195e72f620b2bbf8e3385b51b774a11..e8f4add597edafa4d19b9deab4074d87e10777c0 100644 (file)
@@ -1020,13 +1020,6 @@ static bool fib_valid_prefsrc(struct fib_config *cfg, __be32 fib_prefsrc)
        return true;
 }
 
-static int
-fib_convert_metrics(struct fib_info *fi, const struct fib_config *cfg)
-{
-       return ip_metrics_convert(fi->fib_net, cfg->fc_mx, cfg->fc_mx_len,
-                                 fi->fib_metrics->metrics);
-}
-
 struct fib_info *fib_create_info(struct fib_config *cfg,
                                 struct netlink_ext_ack *extack)
 {
@@ -1084,16 +1077,14 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
        fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
        if (!fi)
                goto failure;
-       if (cfg->fc_mx) {
-               fi->fib_metrics = kzalloc(sizeof(*fi->fib_metrics), GFP_KERNEL);
-               if (unlikely(!fi->fib_metrics)) {
-                       kfree(fi);
-                       return ERR_PTR(err);
-               }
-               refcount_set(&fi->fib_metrics->refcnt, 1);
-       } else {
-               fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics;
+       fi->fib_metrics = ip_fib_metrics_init(fi->fib_net, cfg->fc_mx,
+                                             cfg->fc_mx_len);
+       if (unlikely(IS_ERR(fi->fib_metrics))) {
+               err = PTR_ERR(fi->fib_metrics);
+               kfree(fi);
+               return ERR_PTR(err);
        }
+
        fib_info_cnt++;
        fi->fib_net = net;
        fi->fib_protocol = cfg->fc_protocol;
@@ -1112,10 +1103,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
                        goto failure;
        } endfor_nexthops(fi)
 
-       err = fib_convert_metrics(fi, cfg);
-       if (err)
-               goto failure;
-
        if (cfg->fc_mp) {
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
                err = fib_get_nhs(fi, cfg->fc_mp, cfg->fc_mp_len, cfg, extack);
index 04311f7067e2e9e3dafb89aa4f8e30dab0fde854..6d218f5a2e712582c5deea1aa3d50239031e090f 100644 (file)
@@ -5,8 +5,8 @@
 #include <net/net_namespace.h>
 #include <net/tcp.h>
 
-int ip_metrics_convert(struct net *net, struct nlattr *fc_mx, int fc_mx_len,
-                      u32 *metrics)
+static int ip_metrics_convert(struct net *net, struct nlattr *fc_mx,
+                             int fc_mx_len, u32 *metrics)
 {
        bool ecn_ca = false;
        struct nlattr *nla;
@@ -52,4 +52,28 @@ int ip_metrics_convert(struct net *net, struct nlattr *fc_mx, int fc_mx_len,
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(ip_metrics_convert);
+
+struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
+                                       int fc_mx_len)
+{
+       struct dst_metrics *fib_metrics;
+       int err;
+
+       if (!fc_mx)
+               return (struct dst_metrics *)&dst_default_metrics;
+
+       fib_metrics = kzalloc(sizeof(*fib_metrics), GFP_KERNEL);
+       if (unlikely(!fib_metrics))
+               return ERR_PTR(-ENOMEM);
+
+       err = ip_metrics_convert(net, fc_mx, fc_mx_len, fib_metrics->metrics);
+       if (!err) {
+               refcount_set(&fib_metrics->refcnt, 1);
+       } else {
+               kfree(fib_metrics);
+               fib_metrics = ERR_PTR(err);
+       }
+
+       return fib_metrics;
+}
+EXPORT_SYMBOL_GPL(ip_fib_metrics_init);
index 5516f55e214bd85ff7a07cf8c24648db327902c2..de063780a1750bacfec8a24ed42406f9103c78df 100644 (file)
@@ -160,8 +160,6 @@ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags)
        }
 
        INIT_LIST_HEAD(&f6i->fib6_siblings);
-       f6i->fib6_metrics = (struct dst_metrics *)&dst_default_metrics;
-
        atomic_inc(&f6i->fib6_ref);
 
        return f6i;
index 3adf107b42d275656c72fb8f0d1bc720ade22558..b62b7aa53bbe5b78745095d1a632133f09a0730c 100644 (file)
@@ -2705,24 +2705,6 @@ out:
        return entries > rt_max_size;
 }
 
-static int ip6_convert_metrics(struct net *net, struct fib6_info *rt,
-                              struct fib6_config *cfg)
-{
-       struct dst_metrics *p;
-
-       if (!cfg->fc_mx)
-               return 0;
-
-       p = kzalloc(sizeof(*rt->fib6_metrics), GFP_KERNEL);
-       if (unlikely(!p))
-               return -ENOMEM;
-
-       refcount_set(&p->refcnt, 1);
-       rt->fib6_metrics = p;
-
-       return ip_metrics_convert(net, cfg->fc_mx, cfg->fc_mx_len, p->metrics);
-}
-
 static struct rt6_info *ip6_nh_lookup_table(struct net *net,
                                            struct fib6_config *cfg,
                                            const struct in6_addr *gw_addr,
@@ -2998,13 +2980,15 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
        if (!rt)
                goto out;
 
+       rt->fib6_metrics = ip_fib_metrics_init(net, cfg->fc_mx, cfg->fc_mx_len);
+       if (IS_ERR(rt->fib6_metrics)) {
+               err = PTR_ERR(rt->fib6_metrics);
+               goto out;
+       }
+
        if (cfg->fc_flags & RTF_ADDRCONF)
                rt->dst_nocount = true;
 
-       err = ip6_convert_metrics(net, rt, cfg);
-       if (err < 0)
-               goto out;
-
        if (cfg->fc_flags & RTF_EXPIRES)
                fib6_set_expires(rt, jiffies +
                                clock_t_to_jiffies(cfg->fc_expires));
@@ -3727,6 +3711,7 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
        if (!f6i)
                return ERR_PTR(-ENOMEM);
 
+       f6i->fib6_metrics = ip_fib_metrics_init(net, NULL, 0);
        f6i->dst_nocount = true;
        f6i->dst_host = true;
        f6i->fib6_protocol = RTPROT_KERNEL;