diff options
author | Stephen Hemminger <shemminger@vyatta.com> | 2009-09-20 06:35:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-05 03:21:56 -0400 |
commit | 16c6cf8bb471392fd09b48b7c27e7d83a446b4bc (patch) | |
tree | 6b7c83c37314b54508f6a37613c33610e388d85b /net | |
parent | 977750076d98c7ff6cbda51858bb5a5894a9d9ab (diff) |
ipv4: fib table algorithm performance improvement
The FIB algorithim for IPV4 is set at compile time, but kernel goes through
the overhead of function call indirection at runtime. Save some
cycles by turning the indirect calls to direct calls to either
hash or trie code.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/fib_frontend.c | 26 | ||||
-rw-r--r-- | net/ipv4/fib_hash.c | 25 | ||||
-rw-r--r-- | net/ipv4/fib_rules.c | 2 | ||||
-rw-r--r-- | net/ipv4/fib_trie.c | 26 |
4 files changed, 34 insertions, 45 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index e2f950592566..f73dbed0f0d7 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -125,7 +125,7 @@ void fib_select_default(struct net *net, | |||
125 | #endif | 125 | #endif |
126 | tb = fib_get_table(net, table); | 126 | tb = fib_get_table(net, table); |
127 | if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) | 127 | if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) |
128 | tb->tb_select_default(tb, flp, res); | 128 | fib_table_select_default(tb, flp, res); |
129 | } | 129 | } |
130 | 130 | ||
131 | static void fib_flush(struct net *net) | 131 | static void fib_flush(struct net *net) |
@@ -139,7 +139,7 @@ static void fib_flush(struct net *net) | |||
139 | for (h = 0; h < FIB_TABLE_HASHSZ; h++) { | 139 | for (h = 0; h < FIB_TABLE_HASHSZ; h++) { |
140 | head = &net->ipv4.fib_table_hash[h]; | 140 | head = &net->ipv4.fib_table_hash[h]; |
141 | hlist_for_each_entry(tb, node, head, tb_hlist) | 141 | hlist_for_each_entry(tb, node, head, tb_hlist) |
142 | flushed += tb->tb_flush(tb); | 142 | flushed += fib_table_flush(tb); |
143 | } | 143 | } |
144 | 144 | ||
145 | if (flushed) | 145 | if (flushed) |
@@ -162,7 +162,7 @@ struct net_device * ip_dev_find(struct net *net, __be32 addr) | |||
162 | #endif | 162 | #endif |
163 | 163 | ||
164 | local_table = fib_get_table(net, RT_TABLE_LOCAL); | 164 | local_table = fib_get_table(net, RT_TABLE_LOCAL); |
165 | if (!local_table || local_table->tb_lookup(local_table, &fl, &res)) | 165 | if (!local_table || fib_table_lookup(local_table, &fl, &res)) |
166 | return NULL; | 166 | return NULL; |
167 | if (res.type != RTN_LOCAL) | 167 | if (res.type != RTN_LOCAL) |
168 | goto out; | 168 | goto out; |
@@ -200,7 +200,7 @@ static inline unsigned __inet_dev_addr_type(struct net *net, | |||
200 | local_table = fib_get_table(net, RT_TABLE_LOCAL); | 200 | local_table = fib_get_table(net, RT_TABLE_LOCAL); |
201 | if (local_table) { | 201 | if (local_table) { |
202 | ret = RTN_UNICAST; | 202 | ret = RTN_UNICAST; |
203 | if (!local_table->tb_lookup(local_table, &fl, &res)) { | 203 | if (!fib_table_lookup(local_table, &fl, &res)) { |
204 | if (!dev || dev == res.fi->fib_dev) | 204 | if (!dev || dev == res.fi->fib_dev) |
205 | ret = res.type; | 205 | ret = res.type; |
206 | fib_res_put(&res); | 206 | fib_res_put(&res); |
@@ -473,13 +473,13 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
473 | if (cmd == SIOCDELRT) { | 473 | if (cmd == SIOCDELRT) { |
474 | tb = fib_get_table(net, cfg.fc_table); | 474 | tb = fib_get_table(net, cfg.fc_table); |
475 | if (tb) | 475 | if (tb) |
476 | err = tb->tb_delete(tb, &cfg); | 476 | err = fib_table_delete(tb, &cfg); |
477 | else | 477 | else |
478 | err = -ESRCH; | 478 | err = -ESRCH; |
479 | } else { | 479 | } else { |
480 | tb = fib_new_table(net, cfg.fc_table); | 480 | tb = fib_new_table(net, cfg.fc_table); |
481 | if (tb) | 481 | if (tb) |
482 | err = tb->tb_insert(tb, &cfg); | 482 | err = fib_table_insert(tb, &cfg); |
483 | else | 483 | else |
484 | err = -ENOBUFS; | 484 | err = -ENOBUFS; |
485 | } | 485 | } |
@@ -594,7 +594,7 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *ar | |||
594 | goto errout; | 594 | goto errout; |
595 | } | 595 | } |
596 | 596 | ||
597 | err = tb->tb_delete(tb, &cfg); | 597 | err = fib_table_delete(tb, &cfg); |
598 | errout: | 598 | errout: |
599 | return err; | 599 | return err; |
600 | } | 600 | } |
@@ -616,7 +616,7 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *ar | |||
616 | goto errout; | 616 | goto errout; |
617 | } | 617 | } |
618 | 618 | ||
619 | err = tb->tb_insert(tb, &cfg); | 619 | err = fib_table_insert(tb, &cfg); |
620 | errout: | 620 | errout: |
621 | return err; | 621 | return err; |
622 | } | 622 | } |
@@ -647,7 +647,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
647 | if (dumped) | 647 | if (dumped) |
648 | memset(&cb->args[2], 0, sizeof(cb->args) - | 648 | memset(&cb->args[2], 0, sizeof(cb->args) - |
649 | 2 * sizeof(cb->args[0])); | 649 | 2 * sizeof(cb->args[0])); |
650 | if (tb->tb_dump(tb, skb, cb) < 0) | 650 | if (fib_table_dump(tb, skb, cb) < 0) |
651 | goto out; | 651 | goto out; |
652 | dumped = 1; | 652 | dumped = 1; |
653 | next: | 653 | next: |
@@ -701,9 +701,9 @@ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifad | |||
701 | cfg.fc_scope = RT_SCOPE_HOST; | 701 | cfg.fc_scope = RT_SCOPE_HOST; |
702 | 702 | ||
703 | if (cmd == RTM_NEWROUTE) | 703 | if (cmd == RTM_NEWROUTE) |
704 | tb->tb_insert(tb, &cfg); | 704 | fib_table_insert(tb, &cfg); |
705 | else | 705 | else |
706 | tb->tb_delete(tb, &cfg); | 706 | fib_table_delete(tb, &cfg); |
707 | } | 707 | } |
708 | 708 | ||
709 | void fib_add_ifaddr(struct in_ifaddr *ifa) | 709 | void fib_add_ifaddr(struct in_ifaddr *ifa) |
@@ -832,7 +832,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | |||
832 | local_bh_disable(); | 832 | local_bh_disable(); |
833 | 833 | ||
834 | frn->tb_id = tb->tb_id; | 834 | frn->tb_id = tb->tb_id; |
835 | frn->err = tb->tb_lookup(tb, &fl, &res); | 835 | frn->err = fib_table_lookup(tb, &fl, &res); |
836 | 836 | ||
837 | if (!frn->err) { | 837 | if (!frn->err) { |
838 | frn->prefixlen = res.prefixlen; | 838 | frn->prefixlen = res.prefixlen; |
@@ -1009,7 +1009,7 @@ static void __net_exit ip_fib_net_exit(struct net *net) | |||
1009 | head = &net->ipv4.fib_table_hash[i]; | 1009 | head = &net->ipv4.fib_table_hash[i]; |
1010 | hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) { | 1010 | hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) { |
1011 | hlist_del(node); | 1011 | hlist_del(node); |
1012 | tb->tb_flush(tb); | 1012 | fib_table_flush(tb); |
1013 | kfree(tb); | 1013 | kfree(tb); |
1014 | } | 1014 | } |
1015 | } | 1015 | } |
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index ecd39454235c..14972017b9c2 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c | |||
@@ -242,8 +242,8 @@ fn_new_zone(struct fn_hash *table, int z) | |||
242 | return fz; | 242 | return fz; |
243 | } | 243 | } |
244 | 244 | ||
245 | static int | 245 | int fib_table_lookup(struct fib_table *tb, |
246 | fn_hash_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result *res) | 246 | const struct flowi *flp, struct fib_result *res) |
247 | { | 247 | { |
248 | int err; | 248 | int err; |
249 | struct fn_zone *fz; | 249 | struct fn_zone *fz; |
@@ -274,8 +274,8 @@ out: | |||
274 | return err; | 274 | return err; |
275 | } | 275 | } |
276 | 276 | ||
277 | static void | 277 | void fib_table_select_default(struct fib_table *tb, |
278 | fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res) | 278 | const struct flowi *flp, struct fib_result *res) |
279 | { | 279 | { |
280 | int order, last_idx; | 280 | int order, last_idx; |
281 | struct hlist_node *node; | 281 | struct hlist_node *node; |
@@ -366,7 +366,7 @@ static struct fib_node *fib_find_node(struct fn_zone *fz, __be32 key) | |||
366 | return NULL; | 366 | return NULL; |
367 | } | 367 | } |
368 | 368 | ||
369 | static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) | 369 | int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) |
370 | { | 370 | { |
371 | struct fn_hash *table = (struct fn_hash *) tb->tb_data; | 371 | struct fn_hash *table = (struct fn_hash *) tb->tb_data; |
372 | struct fib_node *new_f = NULL; | 372 | struct fib_node *new_f = NULL; |
@@ -544,8 +544,7 @@ out: | |||
544 | return err; | 544 | return err; |
545 | } | 545 | } |
546 | 546 | ||
547 | 547 | int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) | |
548 | static int fn_hash_delete(struct fib_table *tb, struct fib_config *cfg) | ||
549 | { | 548 | { |
550 | struct fn_hash *table = (struct fn_hash *)tb->tb_data; | 549 | struct fn_hash *table = (struct fn_hash *)tb->tb_data; |
551 | struct fib_node *f; | 550 | struct fib_node *f; |
@@ -662,7 +661,7 @@ static int fn_flush_list(struct fn_zone *fz, int idx) | |||
662 | return found; | 661 | return found; |
663 | } | 662 | } |
664 | 663 | ||
665 | static int fn_hash_flush(struct fib_table *tb) | 664 | int fib_table_flush(struct fib_table *tb) |
666 | { | 665 | { |
667 | struct fn_hash *table = (struct fn_hash *) tb->tb_data; | 666 | struct fn_hash *table = (struct fn_hash *) tb->tb_data; |
668 | struct fn_zone *fz; | 667 | struct fn_zone *fz; |
@@ -743,7 +742,8 @@ fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb, | |||
743 | return skb->len; | 742 | return skb->len; |
744 | } | 743 | } |
745 | 744 | ||
746 | static int fn_hash_dump(struct fib_table *tb, struct sk_buff *skb, struct netlink_callback *cb) | 745 | int fib_table_dump(struct fib_table *tb, struct sk_buff *skb, |
746 | struct netlink_callback *cb) | ||
747 | { | 747 | { |
748 | int m, s_m; | 748 | int m, s_m; |
749 | struct fn_zone *fz; | 749 | struct fn_zone *fz; |
@@ -787,12 +787,7 @@ struct fib_table *fib_hash_table(u32 id) | |||
787 | 787 | ||
788 | tb->tb_id = id; | 788 | tb->tb_id = id; |
789 | tb->tb_default = -1; | 789 | tb->tb_default = -1; |
790 | tb->tb_lookup = fn_hash_lookup; | 790 | |
791 | tb->tb_insert = fn_hash_insert; | ||
792 | tb->tb_delete = fn_hash_delete; | ||
793 | tb->tb_flush = fn_hash_flush; | ||
794 | tb->tb_select_default = fn_hash_select_default; | ||
795 | tb->tb_dump = fn_hash_dump; | ||
796 | memset(tb->tb_data, 0, sizeof(struct fn_hash)); | 791 | memset(tb->tb_data, 0, sizeof(struct fn_hash)); |
797 | return tb; | 792 | return tb; |
798 | } | 793 | } |
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 92d9d97ec5e3..835262c2b867 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
@@ -94,7 +94,7 @@ static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
94 | if ((tbl = fib_get_table(rule->fr_net, rule->table)) == NULL) | 94 | if ((tbl = fib_get_table(rule->fr_net, rule->table)) == NULL) |
95 | goto errout; | 95 | goto errout; |
96 | 96 | ||
97 | err = tbl->tb_lookup(tbl, flp, (struct fib_result *) arg->result); | 97 | err = fib_table_lookup(tbl, flp, (struct fib_result *) arg->result); |
98 | if (err > 0) | 98 | if (err > 0) |
99 | err = -EAGAIN; | 99 | err = -EAGAIN; |
100 | errout: | 100 | errout: |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 291bdf50a21f..af5d89792860 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1174,7 +1174,7 @@ done: | |||
1174 | /* | 1174 | /* |
1175 | * Caller must hold RTNL. | 1175 | * Caller must hold RTNL. |
1176 | */ | 1176 | */ |
1177 | static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) | 1177 | int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) |
1178 | { | 1178 | { |
1179 | struct trie *t = (struct trie *) tb->tb_data; | 1179 | struct trie *t = (struct trie *) tb->tb_data; |
1180 | struct fib_alias *fa, *new_fa; | 1180 | struct fib_alias *fa, *new_fa; |
@@ -1373,8 +1373,8 @@ static int check_leaf(struct trie *t, struct leaf *l, | |||
1373 | return 1; | 1373 | return 1; |
1374 | } | 1374 | } |
1375 | 1375 | ||
1376 | static int fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, | 1376 | int fib_table_lookup(struct fib_table *tb, const struct flowi *flp, |
1377 | struct fib_result *res) | 1377 | struct fib_result *res) |
1378 | { | 1378 | { |
1379 | struct trie *t = (struct trie *) tb->tb_data; | 1379 | struct trie *t = (struct trie *) tb->tb_data; |
1380 | int ret; | 1380 | int ret; |
@@ -1595,7 +1595,7 @@ static void trie_leaf_remove(struct trie *t, struct leaf *l) | |||
1595 | /* | 1595 | /* |
1596 | * Caller must hold RTNL. | 1596 | * Caller must hold RTNL. |
1597 | */ | 1597 | */ |
1598 | static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg) | 1598 | int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) |
1599 | { | 1599 | { |
1600 | struct trie *t = (struct trie *) tb->tb_data; | 1600 | struct trie *t = (struct trie *) tb->tb_data; |
1601 | u32 key, mask; | 1601 | u32 key, mask; |
@@ -1786,7 +1786,7 @@ static struct leaf *trie_leafindex(struct trie *t, int index) | |||
1786 | /* | 1786 | /* |
1787 | * Caller must hold RTNL. | 1787 | * Caller must hold RTNL. |
1788 | */ | 1788 | */ |
1789 | static int fn_trie_flush(struct fib_table *tb) | 1789 | int fib_table_flush(struct fib_table *tb) |
1790 | { | 1790 | { |
1791 | struct trie *t = (struct trie *) tb->tb_data; | 1791 | struct trie *t = (struct trie *) tb->tb_data; |
1792 | struct leaf *l, *ll = NULL; | 1792 | struct leaf *l, *ll = NULL; |
@@ -1807,9 +1807,9 @@ static int fn_trie_flush(struct fib_table *tb) | |||
1807 | return found; | 1807 | return found; |
1808 | } | 1808 | } |
1809 | 1809 | ||
1810 | static void fn_trie_select_default(struct fib_table *tb, | 1810 | void fib_table_select_default(struct fib_table *tb, |
1811 | const struct flowi *flp, | 1811 | const struct flowi *flp, |
1812 | struct fib_result *res) | 1812 | struct fib_result *res) |
1813 | { | 1813 | { |
1814 | struct trie *t = (struct trie *) tb->tb_data; | 1814 | struct trie *t = (struct trie *) tb->tb_data; |
1815 | int order, last_idx; | 1815 | int order, last_idx; |
@@ -1952,8 +1952,8 @@ static int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb, | |||
1952 | return skb->len; | 1952 | return skb->len; |
1953 | } | 1953 | } |
1954 | 1954 | ||
1955 | static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, | 1955 | int fib_table_dump(struct fib_table *tb, struct sk_buff *skb, |
1956 | struct netlink_callback *cb) | 1956 | struct netlink_callback *cb) |
1957 | { | 1957 | { |
1958 | struct leaf *l; | 1958 | struct leaf *l; |
1959 | struct trie *t = (struct trie *) tb->tb_data; | 1959 | struct trie *t = (struct trie *) tb->tb_data; |
@@ -2020,12 +2020,6 @@ struct fib_table *fib_hash_table(u32 id) | |||
2020 | 2020 | ||
2021 | tb->tb_id = id; | 2021 | tb->tb_id = id; |
2022 | tb->tb_default = -1; | 2022 | tb->tb_default = -1; |
2023 | tb->tb_lookup = fn_trie_lookup; | ||
2024 | tb->tb_insert = fn_trie_insert; | ||
2025 | tb->tb_delete = fn_trie_delete; | ||
2026 | tb->tb_flush = fn_trie_flush; | ||
2027 | tb->tb_select_default = fn_trie_select_default; | ||
2028 | tb->tb_dump = fn_trie_dump; | ||
2029 | 2023 | ||
2030 | t = (struct trie *) tb->tb_data; | 2024 | t = (struct trie *) tb->tb_data; |
2031 | memset(t, 0, sizeof(*t)); | 2025 | memset(t, 0, sizeof(*t)); |