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;
};
{
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;
{
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;
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);
}
}
int err;
struct tnode *l;
- if (plen > 32)
+ if (plen > KEYLENGTH)
return -EINVAL;
key = ntohl(cfg->fc_dst);
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) {
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;
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);
continue;
}
- plen = li->plen;
+ slen = li->slen;
}
- l->slen = KEYLENGTH - plen;
+ l->slen = slen;
return found;
}
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)
{
tb->tb_id,
fa->fa_type,
xkey,
- plen,
+ KEYLENGTH - slen,
fa->fa_tos,
fa->fa_info, NLM_F_MULTI) < 0) {
cb->args[5] = i;
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;
}
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),
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) {