Commit cb6b9085 authored by David S. Miller's avatar David S. Miller

[IPV4]: Do fib_alias lookup walk directly in fib_semantic_match().

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c6ccac36
......@@ -256,32 +256,14 @@ fn_hash_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result
head = &fz->fz_hash[fn_hash(k, fz)];
hlist_for_each_entry(f, node, head, fn_hash) {
struct fib_alias *fa;
if (f->fn_key != k)
continue;
list_for_each_entry(fa, &f->fn_alias, fa_list) {
if (fa->fa_tos &&
fa->fa_tos != flp->fl4_tos)
continue;
if (fa->fa_scope < flp->fl4_scope)
continue;
fa->fa_state |= FA_S_ACCESSED;
err = fib_semantic_match(fa->fa_type,
fa->fa_info,
flp, res);
if (err == 0) {
res->type = fa->fa_type;
res->scope = fa->fa_scope;
res->prefixlen = fz->fz_order;
goto out;
}
if (err < 0)
goto out;
}
err = fib_semantic_match(&f->fn_alias,
flp, res,
fz->fz_order);
if (err <= 0)
goto out;
}
}
err = 1;
......
......@@ -17,8 +17,9 @@ struct fib_alias {
#define FA_S_ACCESSED 0x01
/* Exported by fib_semantics.c */
extern int fib_semantic_match(int type, struct fib_info *,
const struct flowi *, struct fib_result *);
extern int fib_semantic_match(struct list_head *head,
const struct flowi *flp,
struct fib_result *res, int prefixlen);
extern void fib_release_info(struct fib_info *);
extern struct fib_info *fib_create_info(const struct rtmsg *r,
struct kern_rta *rta,
......
......@@ -760,51 +760,73 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
return NULL;
}
int
fib_semantic_match(int type, struct fib_info *fi, const struct flowi *flp, struct fib_result *res)
int fib_semantic_match(struct list_head *head, const struct flowi *flp,
struct fib_result *res, int prefixlen)
{
int err = fib_props[type].error;
struct fib_alias *fa;
int nh_sel = 0;
if (err == 0) {
if (fi->fib_flags&RTNH_F_DEAD)
return 1;
list_for_each_entry(fa, head, fa_list) {
int err;
res->fi = fi;
if (fa->fa_tos &&
fa->fa_tos != flp->fl4_tos)
continue;
switch (type) {
case RTN_UNICAST:
case RTN_LOCAL:
case RTN_BROADCAST:
case RTN_ANYCAST:
case RTN_MULTICAST:
for_nexthops(fi) {
if (nh->nh_flags&RTNH_F_DEAD)
continue;
if (!flp->oif || flp->oif == nh->nh_oif)
break;
}
if (fa->fa_scope < flp->fl4_scope)
continue;
fa->fa_state |= FA_S_ACCESSED;
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;
switch (fa->fa_type) {
case RTN_UNICAST:
case RTN_LOCAL:
case RTN_BROADCAST:
case RTN_ANYCAST:
case RTN_MULTICAST:
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) {
res->nh_sel = nhsel;
atomic_inc(&fi->fib_clntref);
return 0;
}
if (nhsel < fi->fib_nhs) {
nh_sel = nhsel;
goto out_fill_res;
}
#else
if (nhsel < 1) {
atomic_inc(&fi->fib_clntref);
return 0;
}
if (nhsel < 1) {
goto out_fill_res;
}
#endif
endfor_nexthops(fi);
res->fi = NULL;
return 1;
default:
res->fi = NULL;
printk(KERN_DEBUG "impossible 102\n");
return -EINVAL;
endfor_nexthops(fi);
continue;
default:
printk(KERN_DEBUG "impossible 102\n");
return -EINVAL;
};
}
return err;
}
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;
atomic_inc(&res->fi->fib_clntref);
return 0;
}
/* Find appropriate source address to this destination */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment