Skip to content

Commit

Permalink
ipv4: Refactor nhc evaluation in fib_table_lookup
Browse files Browse the repository at this point in the history
Signed-off-by: David Ahern <dsahern@gmail.com>
  • Loading branch information
dsahern committed May 21, 2020
1 parent c0fd9a2 commit 063512a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 15 deletions.
2 changes: 2 additions & 0 deletions include/net/ip_fib.h
Expand Up @@ -480,6 +480,8 @@ void fib_nh_common_release(struct fib_nh_common *nhc);
void fib_alias_hw_flags_set(struct net *net, const struct fib_rt_info *fri);
void fib_trie_init(void);
struct fib_table *fib_trie_table(u32 id, struct fib_table *alias);
bool fib_lookup_good_nhc(const struct fib_nh_common *nhc, int fib_flags,
const struct flowi4 *flp);

static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
{
Expand Down
29 changes: 29 additions & 0 deletions include/net/nexthop.h
Expand Up @@ -233,6 +233,35 @@ struct fib_nh_common *nexthop_fib_nhc(struct nexthop *nh, int nhsel)
return &nhi->fib_nhc;
}

/* called from fib_table_lookup with rcu_lock */
static inline
struct fib_nh_common *nexthop_get_nhc_lookup(const struct nexthop *nh,
int fib_flags,
const struct flowi4 *flp)
{
struct nh_info *nhi;

if (nh->is_group) {
struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
int i;

for (i = 0; i < nhg->num_nh; i++) {
struct nexthop *nhe = nhg->nh_entries[i].nh;

nhi = rcu_dereference(nhe->nh_info);
if (fib_lookup_good_nhc(&nhi->fib_nhc, fib_flags, flp))
return &nhi->fib_nhc;
}
} else {
nhi = rcu_dereference(nh->nh_info);
if (fib_lookup_good_nhc(&nhi->fib_nhc, fib_flags, flp))
return &nhi->fib_nhc;
}

return NULL;
}


static inline unsigned int fib_info_num_path(const struct fib_info *fi)
{
if (unlikely(fi->nh))
Expand Down
50 changes: 35 additions & 15 deletions net/ipv4/fib_trie.c
Expand Up @@ -1371,6 +1371,26 @@ static inline t_key prefix_mismatch(t_key key, struct key_vector *n)
return (key ^ prefix) & (prefix | -prefix);
}

bool fib_lookup_good_nhc(const struct fib_nh_common *nhc, int fib_flags,
const struct flowi4 *flp)
{
if (nhc->nhc_flags & RTNH_F_DEAD)
return false;

if (ip_ignore_linkdown(nhc->nhc_dev) &&
nhc->nhc_flags & RTNH_F_LINKDOWN &&
!(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE))
return false;

if (!(flp->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF)) {
if (flp->flowi4_oif &&
flp->flowi4_oif != nhc->nhc_oif)
return false;
}

return true;
}

/* should be called with rcu_read_lock */
int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
struct fib_result *res, int fib_flags)
Expand Down Expand Up @@ -1503,6 +1523,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
/* Step 3: Process the leaf, if that fails fall back to backtracing */
hlist_for_each_entry_rcu(fa, &n->leaf, fa_list) {
struct fib_info *fi = fa->fa_info;
struct fib_nh_common *nhc;
int nhsel, err;

if ((BITS_PER_LONG > KEYLENGTH) || (fa->fa_slen < KEYLENGTH)) {
Expand All @@ -1528,26 +1549,24 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
if (fi->fib_flags & RTNH_F_DEAD)
continue;

if (unlikely(fi->nh && nexthop_is_blackhole(fi->nh))) {
err = fib_props[RTN_BLACKHOLE].error;
goto out_reject;
if (unlikely(fi->nh)) {
if (nexthop_is_blackhole(fi->nh)) {
err = fib_props[RTN_BLACKHOLE].error;
goto out_reject;
}

nhc = nexthop_get_nhc_lookup(fi->nh, fib_flags, flp);
if (nhc)
goto set_result;
goto miss;
}

for (nhsel = 0; nhsel < fib_info_num_path(fi); nhsel++) {
struct fib_nh_common *nhc = fib_info_nhc(fi, nhsel);
nhc = fib_info_nhc(fi, nhsel);

if (nhc->nhc_flags & RTNH_F_DEAD)
if (!fib_lookup_good_nhc(nhc, fib_flags, flp))
continue;
if (ip_ignore_linkdown(nhc->nhc_dev) &&
nhc->nhc_flags & RTNH_F_LINKDOWN &&
!(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE))
continue;
if (!(flp->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF)) {
if (flp->flowi4_oif &&
flp->flowi4_oif != nhc->nhc_oif)
continue;
}

set_result:
if (!(fib_flags & FIB_LOOKUP_NOREF))
refcount_inc(&fi->fib_clntref);

Expand All @@ -1568,6 +1587,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
return err;
}
}
miss:
#ifdef CONFIG_IP_FIB_TRIE_STATS
this_cpu_inc(stats->semantic_match_miss);
#endif
Expand Down

0 comments on commit 063512a

Please sign in to comment.