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>
This commit is contained in:
Родитель
4c8237cd76
Коммит
3be0686b6e
|
@ -51,4 +51,11 @@ static inline void fib_result_assign(struct fib_result *res,
|
|||
res->fi = fi;
|
||||
}
|
||||
|
||||
struct fib_prop {
|
||||
int error;
|
||||
u8 scope;
|
||||
};
|
||||
|
||||
extern const struct fib_prop fib_props[RTN_MAX + 1];
|
||||
|
||||
#endif /* _FIB_LOOKUP_H */
|
||||
|
|
|
@ -90,11 +90,7 @@ static DEFINE_SPINLOCK(fib_multipath_lock);
|
|||
#define endfor_nexthops(fi) }
|
||||
|
||||
|
||||
static const struct
|
||||
{
|
||||
int error;
|
||||
u8 scope;
|
||||
} fib_props[RTN_MAX + 1] = {
|
||||
const struct fib_prop fib_props[RTN_MAX + 1] = {
|
||||
[RTN_UNSPEC] = {
|
||||
.error = 0,
|
||||
.scope = RT_SCOPE_NOWHERE,
|
||||
|
@ -902,68 +898,6 @@ failure:
|
|||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/* Note! fib_semantic_match intentionally uses RCU list functions. */
|
||||
int fib_semantic_match(struct fib_table *tb, struct list_head *head,
|
||||
const struct flowi *flp, struct fib_result *res,
|
||||
int prefixlen, int fib_flags)
|
||||
{
|
||||
struct fib_alias *fa;
|
||||
int nh_sel = 0;
|
||||
|
||||
list_for_each_entry_rcu(fa, head, fa_list) {
|
||||
int 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 == 0) {
|
||||
struct fib_info *fi = fa->fa_info;
|
||||
|
||||
if (fi->fib_flags & RTNH_F_DEAD)
|
||||
continue;
|
||||
|
||||
for_nexthops(fi) {
|
||||
if (nh->nh_flags & RTNH_F_DEAD)
|
||||
continue;
|
||||
if (!flp->oif || flp->oif == nh->nh_oif)
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
||||
if (nhsel < fi->fib_nhs) {
|
||||
nh_sel = nhsel;
|
||||
goto out_fill_res;
|
||||
}
|
||||
#else
|
||||
if (nhsel < 1)
|
||||
goto out_fill_res;
|
||||
#endif
|
||||
endfor_nexthops(fi);
|
||||
continue;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
return 1;
|
||||
|
||||
out_fill_res:
|
||||
res->prefixlen = prefixlen;
|
||||
res->nh_sel = nh_sel;
|
||||
res->type = fa->fa_type;
|
||||
res->scope = fa->fa_scope;
|
||||
res->fi = fa->fa_info;
|
||||
res->table = tb;
|
||||
res->fa_head = head;
|
||||
if (!(fib_flags & FIB_LOOKUP_NOREF))
|
||||
atomic_inc(&res->fi->fib_clntref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find appropriate source address to this destination */
|
||||
|
||||
__be32 __fib_res_prefsrc(struct fib_result *res)
|
||||
|
|
|
@ -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
|
||||
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
|
||||
if (err <= 0)
|
||||
t->stats.semantic_match_passed++;
|
||||
else
|
||||
t->stats.semantic_match_miss++;
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче