aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-07 18:01:10 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-07 18:19:39 -0500
commit3be0686b6e2f953afe83626e871b4a7b0ceae49b (patch)
tree6591cba7d393d6b0bc7b2c647a5a5f1f5d8728e8 /net/ipv4
parent4c8237cd76a0510677dc2e3dd0f8866ec8e0b1e5 (diff)
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')
-rw-r--r--net/ipv4/fib_lookup.h7
-rw-r--r--net/ipv4/fib_semantics.c68
-rw-r--r--net/ipv4/fib_trie.c51
3 files changed, 51 insertions, 75 deletions
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index d5c40d8f6632..84db2da5c848 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -51,4 +51,11 @@ static inline void fib_result_assign(struct fib_result *res,
51 res->fi = fi; 51 res->fi = fi;
52} 52}
53 53
54struct fib_prop {
55 int error;
56 u8 scope;
57};
58
59extern const struct fib_prop fib_props[RTN_MAX + 1];
60
54#endif /* _FIB_LOOKUP_H */ 61#endif /* _FIB_LOOKUP_H */
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index c29291b21009..6349a21692ec 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -90,11 +90,7 @@ static DEFINE_SPINLOCK(fib_multipath_lock);
90#define endfor_nexthops(fi) } 90#define endfor_nexthops(fi) }
91 91
92 92
93static const struct 93const struct fib_prop fib_props[RTN_MAX + 1] = {
94{
95 int error;
96 u8 scope;
97} fib_props[RTN_MAX + 1] = {
98 [RTN_UNSPEC] = { 94 [RTN_UNSPEC] = {
99 .error = 0, 95 .error = 0,
100 .scope = RT_SCOPE_NOWHERE, 96 .scope = RT_SCOPE_NOWHERE,
@@ -902,68 +898,6 @@ failure:
902 return ERR_PTR(err); 898 return ERR_PTR(err);
903} 899}
904 900
905/* Note! fib_semantic_match intentionally uses RCU list functions. */
906int fib_semantic_match(struct fib_table *tb, struct list_head *head,
907 const struct flowi *flp, struct fib_result *res,
908 int prefixlen, int fib_flags)
909{
910 struct fib_alias *fa;
911 int nh_sel = 0;
912
913 list_for_each_entry_rcu(fa, head, fa_list) {
914 int err;
915
916 if (fa->fa_tos &&
917 fa->fa_tos != flp->fl4_tos)
918 continue;
919
920 if (fa->fa_scope < flp->fl4_scope)
921 continue;
922
923 fib_alias_accessed(fa);
924
925 err = fib_props[fa->fa_type].error;
926 if (err == 0) {
927 struct fib_info *fi = fa->fa_info;
928
929 if (fi->fib_flags & RTNH_F_DEAD)
930 continue;
931
932 for_nexthops(fi) {
933 if (nh->nh_flags & RTNH_F_DEAD)
934 continue;
935 if (!flp->oif || flp->oif == nh->nh_oif)
936 break;
937 }
938#ifdef CONFIG_IP_ROUTE_MULTIPATH
939 if (nhsel < fi->fib_nhs) {
940 nh_sel = nhsel;
941 goto out_fill_res;
942 }
943#else
944 if (nhsel < 1)
945 goto out_fill_res;
946#endif
947 endfor_nexthops(fi);
948 continue;
949 }
950 return err;
951 }
952 return 1;
953
954out_fill_res:
955 res->prefixlen = prefixlen;
956 res->nh_sel = nh_sel;
957 res->type = fa->fa_type;
958 res->scope = fa->fa_scope;
959 res->fi = fa->fa_info;
960 res->table = tb;
961 res->fa_head = head;
962 if (!(fib_flags & FIB_LOOKUP_NOREF))
963 atomic_inc(&res->fi->fib_clntref);
964 return 0;
965}
966
967/* Find appropriate source address to this destination */ 901/* Find appropriate source address to this destination */
968 902
969__be32 __fib_res_prefsrc(struct fib_result *res) 903__be32 __fib_res_prefsrc(struct fib_result *res)
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,
1349 struct hlist_node *node; 1349 struct hlist_node *node;
1350 1350
1351 hlist_for_each_entry_rcu(li, node, hhead, hlist) { 1351 hlist_for_each_entry_rcu(li, node, hhead, hlist) {
1352 int err; 1352 struct fib_alias *fa;
1353 int plen = li->plen; 1353 int plen = li->plen;
1354 __be32 mask = inet_make_mask(plen); 1354 __be32 mask = inet_make_mask(plen);
1355 1355
1356 if (l->key != (key & ntohl(mask))) 1356 if (l->key != (key & ntohl(mask)))
1357 continue; 1357 continue;
1358 1358
1359 err = fib_semantic_match(tb, &li->falh, flp, res, plen, fib_flags); 1359 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
1360 struct fib_info *fi = fa->fa_info;
1361 int nhsel, err;
1360 1362
1363 if (fa->fa_tos && fa->fa_tos != flp->fl4_tos)
1364 continue;
1365 if (fa->fa_scope < flp->fl4_scope)
1366 continue;
1367 fib_alias_accessed(fa);
1368 err = fib_props[fa->fa_type].error;
1369 if (err) {
1361#ifdef CONFIG_IP_FIB_TRIE_STATS 1370#ifdef CONFIG_IP_FIB_TRIE_STATS
1362 if (err <= 0) 1371 t->stats.semantic_match_miss++;
1363 t->stats.semantic_match_passed++; 1372#endif
1364 else 1373 return 1;
1365 t->stats.semantic_match_miss++; 1374 }
1375 if (fi->fib_flags & RTNH_F_DEAD)
1376 continue;
1377 for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
1378 const struct fib_nh *nh = &fi->fib_nh[nhsel];
1379
1380 if (nh->nh_flags & RTNH_F_DEAD)
1381 continue;
1382 if (flp->oif && flp->oif != nh->nh_oif)
1383 continue;
1384
1385#ifdef CONFIG_IP_FIB_TRIE_STATS
1386 t->stats.semantic_match_passed++;
1387#endif
1388 res->prefixlen = plen;
1389 res->nh_sel = nhsel;
1390 res->type = fa->fa_type;
1391 res->scope = fa->fa_scope;
1392 res->fi = fi;
1393 res->table = tb;
1394 res->fa_head = &li->falh;
1395 if (!(fib_flags & FIB_LOOKUP_NOREF))
1396 atomic_inc(&res->fi->fib_clntref);
1397 return 0;
1398 }
1399 }
1400
1401#ifdef CONFIG_IP_FIB_TRIE_STATS
1402 t->stats.semantic_match_miss++;
1366#endif 1403#endif
1367 if (err <= 0)
1368 return err;
1369 } 1404 }
1370 1405
1371 return 1; 1406 return 1;