diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-07 18:01:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-07 18:19:39 -0500 |
commit | 3be0686b6e2f953afe83626e871b4a7b0ceae49b (patch) | |
tree | 6591cba7d393d6b0bc7b2c647a5a5f1f5d8728e8 | |
parent | 4c8237cd76a0510677dc2e3dd0f8866ec8e0b1e5 (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>
-rw-r--r-- | net/ipv4/fib_lookup.h | 7 | ||||
-rw-r--r-- | net/ipv4/fib_semantics.c | 68 | ||||
-rw-r--r-- | net/ipv4/fib_trie.c | 51 |
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 | ||
54 | struct fib_prop { | ||
55 | int error; | ||
56 | u8 scope; | ||
57 | }; | ||
58 | |||
59 | extern 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 | ||
93 | static const struct | 93 | const 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. */ | ||
906 | int 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 | |||
954 | out_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; |