diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/fib_trie.c | 63 |
1 files changed, 30 insertions, 33 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index f17e2239b7b9..d28362db51a0 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -114,8 +114,7 @@ struct tnode { struct leaf_info { struct hlist_node hlist; - int plen; - u32 mask_plen; /* ntohl(inet_make_mask(plen)) */ + unsigned char slen; struct hlist_head falh; struct rcu_head rcu; }; @@ -337,8 +336,7 @@ static struct leaf_info *leaf_info_new(int plen) { struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL); if (li) { - li->plen = plen; - li->mask_plen = ntohl(inet_make_mask(plen)); + li->slen = KEYLENGTH - plen; INIT_HLIST_HEAD(&li->falh); } return li; @@ -873,9 +871,10 @@ static struct leaf_info *find_leaf_info(struct tnode *l, int plen) { struct hlist_head *head = &l->list; struct leaf_info *li; + int slen = KEYLENGTH - plen; hlist_for_each_entry_rcu(li, head, hlist) - if (li->plen == plen) + if (li->slen == slen) return li; return NULL; @@ -929,33 +928,29 @@ static void remove_leaf_info(struct tnode *l, struct leaf_info *old) return; /* update the trie with the latest suffix length */ - l->slen = KEYLENGTH - li->plen; + l->slen = li->slen; leaf_pull_suffix(l); } static void insert_leaf_info(struct tnode *l, struct leaf_info *new) { struct hlist_head *head = &l->list; - struct leaf_info *li = NULL, *last = NULL; - - if (hlist_empty(head)) { - hlist_add_head_rcu(&new->hlist, head); - } else { - hlist_for_each_entry(li, head, hlist) { - if (new->plen > li->plen) - break; + struct leaf_info *li, *last = NULL; - last = li; - } - if (last) - hlist_add_behind_rcu(&new->hlist, &last->hlist); - else - hlist_add_before_rcu(&new->hlist, &li->hlist); + hlist_for_each_entry(li, head, hlist) { + if (new->slen < li->slen) + break; + last = li; } + if (last) + hlist_add_behind_rcu(&new->hlist, &last->hlist); + else + hlist_add_head_rcu(&new->hlist, head); + /* if we added to the tail node then we need to update slen */ - if (l->slen < (KEYLENGTH - new->plen)) { - l->slen = KEYLENGTH - new->plen; + if (l->slen < new->slen) { + l->slen = new->slen; leaf_push_suffix(l); } } @@ -1139,7 +1134,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) int err; struct tnode *l; - if (plen > 32) + if (plen > KEYLENGTH) return -EINVAL; key = ntohl(cfg->fc_dst); @@ -1425,7 +1420,8 @@ found: hlist_for_each_entry_rcu(li, &n->list, hlist) { struct fib_alias *fa; - if ((key ^ n->key) & li->mask_plen) + if (((key ^ n->key) >= (1ul << li->slen)) && + ((BITS_PER_LONG > KEYLENGTH) || (li->slen != KEYLENGTH))) continue; hlist_for_each_entry_rcu(fa, &li->falh, fa_list) { @@ -1459,7 +1455,7 @@ found: if (!(fib_flags & FIB_LOOKUP_NOREF)) atomic_inc(&fi->fib_clntref); - res->prefixlen = li->plen; + res->prefixlen = KEYLENGTH - li->slen; res->nh_sel = nhsel; res->type = fa->fa_type; res->scope = fi->fib_scope; @@ -1614,7 +1610,7 @@ static int trie_flush_leaf(struct tnode *l) int found = 0; struct hlist_node *tmp; struct leaf_info *li; - unsigned char plen = KEYLENGTH; + unsigned char slen = 0; hlist_for_each_entry_safe(li, tmp, &l->list, hlist) { found += trie_flush_list(&li->falh); @@ -1625,10 +1621,10 @@ static int trie_flush_leaf(struct tnode *l) continue; } - plen = li->plen; + slen = li->slen; } - l->slen = KEYLENGTH - plen; + l->slen = slen; return found; } @@ -1739,7 +1735,7 @@ void fib_free_table(struct fib_table *tb) kfree(tb); } -static int fn_trie_dump_fa(t_key key, int plen, struct hlist_head *fah, +static int fn_trie_dump_fa(t_key key, int slen, struct hlist_head *fah, struct fib_table *tb, struct sk_buff *skb, struct netlink_callback *cb) { @@ -1764,7 +1760,7 @@ static int fn_trie_dump_fa(t_key key, int plen, struct hlist_head *fah, tb->tb_id, fa->fa_type, xkey, - plen, + KEYLENGTH - slen, fa->fa_tos, fa->fa_info, NLM_F_MULTI) < 0) { cb->args[5] = i; @@ -1798,7 +1794,7 @@ static int fn_trie_dump_leaf(struct tnode *l, struct fib_table *tb, if (hlist_empty(&li->falh)) continue; - if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) { + if (fn_trie_dump_fa(l->key, li->slen, &li->falh, tb, skb, cb) < 0) { cb->args[4] = i; return -1; } @@ -2284,7 +2280,8 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) char buf1[32], buf2[32]; seq_indent(seq, iter->depth+1); - seq_printf(seq, " /%d %s %s", li->plen, + seq_printf(seq, " /%zu %s %s", + KEYLENGTH - li->slen, rtn_scope(buf1, sizeof(buf1), fa->fa_info->fib_scope), rtn_type(buf2, sizeof(buf2), @@ -2434,7 +2431,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v) struct fib_alias *fa; __be32 mask, prefix; - mask = inet_make_mask(li->plen); + mask = inet_make_mask(KEYLENGTH - li->slen); prefix = htonl(l->key); hlist_for_each_entry_rcu(fa, &li->falh, fa_list) { |