]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv4/fib_trie.c
fib: introduce fib_alias_accessed() helper
[net-next-2.6.git] / net / ipv4 / fib_trie.c
index 4a8e370862bca453cd6e939162ded09de6bdf831..cd5e13aee7d5b689b76c834673d70dd7c334361e 100644 (file)
@@ -186,9 +186,7 @@ static inline struct tnode *node_parent_rcu(struct node *node)
 {
        struct tnode *ret = node_parent(node);
 
-       return rcu_dereference_check(ret,
-                                    rcu_read_lock_held() ||
-                                    lockdep_rtnl_is_held());
+       return rcu_dereference_rtnl(ret);
 }
 
 /* Same as rcu_assign_pointer
@@ -211,9 +209,7 @@ static inline struct node *tnode_get_child_rcu(struct tnode *tn, unsigned int i)
 {
        struct node *ret = tnode_get_child(tn, i);
 
-       return rcu_dereference_check(ret,
-                                    rcu_read_lock_held() ||
-                                    lockdep_rtnl_is_held());
+       return rcu_dereference_rtnl(ret);
 }
 
 static inline int tnode_child_length(const struct tnode *tn)
@@ -459,8 +455,8 @@ static struct tnode *tnode_new(t_key key, int pos, int bits)
                tn->empty_children = 1<<bits;
        }
 
-       pr_debug("AT %p s=%u %lu\n", tn, (unsigned int) sizeof(struct tnode),
-                (unsigned long) (sizeof(struct node) << bits));
+       pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode),
+                sizeof(struct node) << bits);
        return tn;
 }
 
@@ -609,11 +605,10 @@ static struct node *resize(struct trie *t, struct tnode *tn)
 
        /* Keep root node larger  */
 
-       if (!node_parent((struct node*) tn)) {
+       if (!node_parent((struct node *)tn)) {
                inflate_threshold_use = inflate_threshold_root;
                halve_threshold_use = halve_threshold_root;
-       }
-       else {
+       } else {
                inflate_threshold_use = inflate_threshold;
                halve_threshold_use = halve_threshold;
        }
@@ -639,7 +634,7 @@ static struct node *resize(struct trie *t, struct tnode *tn)
        check_tnode(tn);
 
        /* Return if at least one inflate is run */
-       ifmax_work != MAX_WORK)
+       if (max_work != MAX_WORK)
                return (struct node *) tn;
 
        /*
@@ -966,9 +961,7 @@ fib_find_node(struct trie *t, u32 key)
        struct node *n;
 
        pos = 0;
-       n = rcu_dereference_check(t->trie,
-                                 rcu_read_lock_held() ||
-                                 lockdep_rtnl_is_held());
+       n = rcu_dereference_rtnl(t->trie);
 
        while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
                tn = (struct tnode *) n;
@@ -1349,7 +1342,7 @@ err:
 /* should be called with rcu_read_lock */
 static int check_leaf(struct trie *t, struct leaf *l,
                      t_key key,  const struct flowi *flp,
-                     struct fib_result *res)
+                     struct fib_result *res, int fib_flags)
 {
        struct leaf_info *li;
        struct hlist_head *hhead = &l->list;
@@ -1363,7 +1356,7 @@ static int check_leaf(struct trie *t, struct leaf *l,
                if (l->key != (key & ntohl(mask)))
                        continue;
 
-               err = fib_semantic_match(&li->falh, flp, res, plen);
+               err = fib_semantic_match(&li->falh, flp, res, plen, fib_flags);
 
 #ifdef CONFIG_IP_FIB_TRIE_STATS
                if (err <= 0)
@@ -1379,7 +1372,7 @@ static int check_leaf(struct trie *t, struct leaf *l,
 }
 
 int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
-                    struct fib_result *res)
+                    struct fib_result *res, int fib_flags)
 {
        struct trie *t = (struct trie *) tb->tb_data;
        int ret;
@@ -1391,8 +1384,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
        t_key cindex = 0;
        int current_prefix_length = KEYLENGTH;
        struct tnode *cn;
-       t_key node_prefix, key_prefix, pref_mismatch;
-       int mp;
+       t_key pref_mismatch;
 
        rcu_read_lock();
 
@@ -1406,7 +1398,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
 
        /* Just a leaf? */
        if (IS_LEAF(n)) {
-               ret = check_leaf(t, (struct leaf *)n, key, flp, res);
+               ret = check_leaf(t, (struct leaf *)n, key, flp, res, fib_flags);
                goto found;
        }
 
@@ -1431,7 +1423,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
                }
 
                if (IS_LEAF(n)) {
-                       ret = check_leaf(t, (struct leaf *)n, key, flp, res);
+                       ret = check_leaf(t, (struct leaf *)n, key, flp, res, fib_flags);
                        if (ret > 0)
                                goto backtrace;
                        goto found;
@@ -1507,10 +1499,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
                 * matching prefix.
                 */
 
-               node_prefix = mask_pfx(cn->key, cn->pos);
-               key_prefix = mask_pfx(key, cn->pos);
-               pref_mismatch = key_prefix^node_prefix;
-               mp = 0;
+               pref_mismatch = mask_pfx(cn->key ^ key, cn->pos);
 
                /*
                 * In short: If skipped bits in this node do not match
@@ -1518,13 +1507,9 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
                 * state.directly.
                 */
                if (pref_mismatch) {
-                       while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) {
-                               mp++;
-                               pref_mismatch = pref_mismatch << 1;
-                       }
-                       key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp);
+                       int mp = KEYLENGTH - fls(pref_mismatch);
 
-                       if (key_prefix != 0)
+                       if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0)
                                goto backtrace;
 
                        if (current_prefix_length >= cn->pos)
@@ -1748,16 +1733,14 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c)
 
                /* Node empty, walk back up to parent */
                c = (struct node *) p;
-       } while ( (p = node_parent_rcu(c)) != NULL);
+       } while ((p = node_parent_rcu(c)) != NULL);
 
        return NULL; /* Root of trie */
 }
 
 static struct leaf *trie_firstleaf(struct trie *t)
 {
-       struct tnode *n = (struct tnode *) rcu_dereference_check(t->trie,
-                                                       rcu_read_lock_held() ||
-                                                       lockdep_rtnl_is_held());
+       struct tnode *n = (struct tnode *)rcu_dereference_rtnl(t->trie);
 
        if (!n)
                return NULL;
@@ -1855,7 +1838,8 @@ void fib_table_select_default(struct fib_table *tb,
                if (!next_fi->fib_nh[0].nh_gw ||
                    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
                        continue;
-               fa->fa_state |= FA_S_ACCESSED;
+
+               fib_alias_accessed(fa);
 
                if (fi == NULL) {
                        if (next_fi != res->fi)
@@ -2043,14 +2027,14 @@ struct fib_trie_iter {
        struct seq_net_private p;
        struct fib_table *tb;
        struct tnode *tnode;
-       unsigned index;
-       unsigned depth;
+       unsigned int index;
+       unsigned int depth;
 };
 
 static struct node *fib_trie_get_next(struct fib_trie_iter *iter)
 {
        struct tnode *tn = iter->tnode;
-       unsigned cindex = iter->index;
+       unsigned int cindex = iter->index;
        struct tnode *p;
 
        /* A single entry routing table */
@@ -2159,7 +2143,7 @@ static void trie_collect_stats(struct trie *t, struct trie_stat *s)
  */
 static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
 {
-       unsigned i, max, pointers, bytes, avdepth;
+       unsigned int i, max, pointers, bytes, avdepth;
 
        if (stat->leaves)
                avdepth = stat->totdepth*100 / stat->leaves;
@@ -2356,7 +2340,8 @@ static void fib_trie_seq_stop(struct seq_file *seq, void *v)
 
 static void seq_indent(struct seq_file *seq, int n)
 {
-       while (n-- > 0) seq_puts(seq, "   ");
+       while (n-- > 0)
+               seq_puts(seq, "   ");
 }
 
 static inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s)
@@ -2388,7 +2373,7 @@ static const char *const rtn_type_names[__RTN_MAX] = {
        [RTN_XRESOLVE] = "XRESOLVE",
 };
 
-static inline const char *rtn_type(char *buf, size_t len, unsigned t)
+static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
 {
        if (t < __RTN_MAX && rtn_type_names[t])
                return rtn_type_names[t];
@@ -2544,13 +2529,12 @@ static void fib_route_seq_stop(struct seq_file *seq, void *v)
        rcu_read_unlock();
 }
 
-static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
+static unsigned int fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
 {
-       static unsigned type2flags[RTN_MAX + 1] = {
-               [7] = RTF_REJECT, [8] = RTF_REJECT,
-       };
-       unsigned flags = type2flags[type];
+       unsigned int flags = 0;
 
+       if (type == RTN_UNREACHABLE || type == RTN_PROHIBIT)
+               flags = RTF_REJECT;
        if (fi && fi->fib_nh->nh_gw)
                flags |= RTF_GATEWAY;
        if (mask == htonl(0xFFFFFFFF))
@@ -2562,7 +2546,7 @@ static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
 /*
  *     This outputs /proc/net/route.
  *     The format of the file is not supposed to be changed
- *     and needs to be same as fib_hash output to avoid breaking
+ *     and needs to be same as fib_hash output to avoid breaking
  *     legacy utilities
  */
 static int fib_route_seq_show(struct seq_file *seq, void *v)
@@ -2587,7 +2571,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
 
                list_for_each_entry_rcu(fa, &li->falh, fa_list) {
                        const struct fib_info *fi = fa->fa_info;
-                       unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
+                       unsigned int flags = fib_flag_trans(fa->fa_type, mask, fi);
                        int len;
 
                        if (fa->fa_type == RTN_BROADCAST