diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-08 02:01:10 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-08 02:19:39 +0300 |
commit | 3be0686b6e2f953afe83626e871b4a7b0ceae49b (patch) | |
tree | 6591cba7d393d6b0bc7b2c647a5a5f1f5d8728e8 /net/ipv4/fib_trie.c | |
parent | 4c8237cd76a0510677dc2e3dd0f8866ec8e0b1e5 (diff) | |
download | linux-3be0686b6e2f953afe83626e871b4a7b0ceae49b.tar.xz |
ipv4: Inline fib_semantic_match into check_leaf
This elimiates a lot of pure overhead due to parameter
passing.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/fib_trie.c')
-rw-r--r-- | net/ipv4/fib_trie.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index edf3b0997e01..a4109a544778 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1349,23 +1349,58 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, struct hlist_node *node; hlist_for_each_entry_rcu(li, node, hhead, hlist) { - int err; + struct fib_alias *fa; int plen = li->plen; __be32 mask = inet_make_mask(plen); if (l->key != (key & ntohl(mask))) continue; - err = fib_semantic_match(tb, &li->falh, flp, res, plen, fib_flags); + list_for_each_entry_rcu(fa, &li->falh, fa_list) { + struct fib_info *fi = fa->fa_info; + int nhsel, err; + if (fa->fa_tos && fa->fa_tos != flp->fl4_tos) + continue; + if (fa->fa_scope < flp->fl4_scope) + continue; + fib_alias_accessed(fa); + err = fib_props[fa->fa_type].error; + if (err) { #ifdef CONFIG_IP_FIB_TRIE_STATS - if (err <= 0) - t->stats.semantic_match_passed++; - else - t->stats.semantic_match_miss++; + t->stats.semantic_match_miss++; +#endif + return 1; + } + if (fi->fib_flags & RTNH_F_DEAD) + continue; + for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) { + const struct fib_nh *nh = &fi->fib_nh[nhsel]; + + if (nh->nh_flags & RTNH_F_DEAD) + continue; + if (flp->oif && flp->oif != nh->nh_oif) + continue; + +#ifdef CONFIG_IP_FIB_TRIE_STATS + t->stats.semantic_match_passed++; +#endif + res->prefixlen = plen; + res->nh_sel = nhsel; + res->type = fa->fa_type; + res->scope = fa->fa_scope; + res->fi = fi; + res->table = tb; + res->fa_head = &li->falh; + if (!(fib_flags & FIB_LOOKUP_NOREF)) + atomic_inc(&res->fi->fib_clntref); + return 0; + } + } + +#ifdef CONFIG_IP_FIB_TRIE_STATS + t->stats.semantic_match_miss++; #endif - if (err <= 0) - return err; } return 1; |