]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv4/fib_semantics.c
net: use the macros defined for the members of flowi
[net-next-2.6.git] / net / ipv4 / fib_semantics.c
index ba52f399a898915cc109bd6338c82b6c6ad487ef..12d3dc3df1b7d683e94cbf42140a9ac40b35029d 100644 (file)
@@ -148,6 +148,13 @@ static const struct
 
 /* Release a nexthop info record */
 
+static void free_fib_info_rcu(struct rcu_head *head)
+{
+       struct fib_info *fi = container_of(head, struct fib_info, rcu);
+
+       kfree(fi);
+}
+
 void free_fib_info(struct fib_info *fi)
 {
        if (fi->fib_dead == 0) {
@@ -161,7 +168,7 @@ void free_fib_info(struct fib_info *fi)
        } endfor_nexthops(fi);
        fib_info_cnt--;
        release_net(fi->fib_net);
-       kfree(fi);
+       call_rcu(&fi->rcu, free_fib_info_rcu);
 }
 
 void fib_release_info(struct fib_info *fi)
@@ -553,14 +560,11 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
                        nh->nh_scope = RT_SCOPE_LINK;
                        return 0;
                }
+               rcu_read_lock();
                {
                        struct flowi fl = {
-                               .nl_u = {
-                                       .ip4_u = {
-                                               .daddr = nh->nh_gw,
-                                               .scope = cfg->fc_scope + 1,
-                                       },
-                               },
+                               .fl4_dst = nh->nh_gw,
+                               .fl4_scope = cfg->fc_scope + 1,
                                .oif = nh->nh_oif,
                        };
 
@@ -568,8 +572,10 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
                        if (fl.fl4_scope < RT_SCOPE_LINK)
                                fl.fl4_scope = RT_SCOPE_LINK;
                        err = fib_lookup(net, &fl, &res);
-                       if (err)
+                       if (err) {
+                               rcu_read_unlock();
                                return err;
+                       }
                }
                err = -EINVAL;
                if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
@@ -580,32 +586,29 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
                if (!dev)
                        goto out;
                dev_hold(dev);
-               err = -ENETDOWN;
-               if (!(dev->flags & IFF_UP))
-                       goto out;
-               err = 0;
-out:
-               fib_res_put(&res);
-               return err;
+               err = (dev->flags & IFF_UP) ? 0 : -ENETDOWN;
        } else {
                struct in_device *in_dev;
 
                if (nh->nh_flags & (RTNH_F_PERVASIVE | RTNH_F_ONLINK))
                        return -EINVAL;
 
+               rcu_read_lock();
+               err = -ENODEV;
                in_dev = inetdev_by_index(net, nh->nh_oif);
                if (in_dev == NULL)
-                       return -ENODEV;
-               if (!(in_dev->dev->flags & IFF_UP)) {
-                       in_dev_put(in_dev);
-                       return -ENETDOWN;
-               }
+                       goto out;
+               err = -ENETDOWN;
+               if (!(in_dev->dev->flags & IFF_UP))
+                       goto out;
                nh->nh_dev = in_dev->dev;
                dev_hold(nh->nh_dev);
                nh->nh_scope = RT_SCOPE_HOST;
-               in_dev_put(in_dev);
+               err = 0;
        }
-       return 0;
+out:
+       rcu_read_unlock();
+       return err;
 }
 
 static inline unsigned int fib_laddr_hashfn(__be32 val)
@@ -879,7 +882,7 @@ failure:
 
 /* Note! fib_semantic_match intentionally uses  RCU list functions. */
 int fib_semantic_match(struct list_head *head, const struct flowi *flp,
-                      struct fib_result *res, int prefixlen)
+                      struct fib_result *res, int prefixlen, int fib_flags)
 {
        struct fib_alias *fa;
        int nh_sel = 0;
@@ -894,7 +897,7 @@ int fib_semantic_match(struct list_head *head, const struct flowi *flp,
                if (fa->fa_scope < flp->fl4_scope)
                        continue;
 
-               fa->fa_state |= FA_S_ACCESSED;
+               fib_alias_accessed(fa);
 
                err = fib_props[fa->fa_type].error;
                if (err == 0) {
@@ -943,7 +946,8 @@ out_fill_res:
        res->type = fa->fa_type;
        res->scope = fa->fa_scope;
        res->fi = fa->fa_info;
-       atomic_inc(&res->fi->fib_clntref);
+       if (!(fib_flags & FIB_LOOKUP_NOREF))
+               atomic_inc(&res->fi->fib_clntref);
        return 0;
 }