Loading net/ipv4/fib_lookup.h +7 −0 Original line number Diff line number Diff line Loading @@ -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 */ net/ipv4/fib_semantics.c +1 −67 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -902,68 +898,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg) 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) Loading net/ipv4/fib_trie.c +43 −8 Original line number Diff line number Diff line Loading @@ -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 #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; Loading Loading
net/ipv4/fib_lookup.h +7 −0 Original line number Diff line number Diff line Loading @@ -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 */
net/ipv4/fib_semantics.c +1 −67 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -902,68 +898,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg) 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) Loading
net/ipv4/fib_trie.c +43 −8 Original line number Diff line number Diff line Loading @@ -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 #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; Loading