aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-08-11 02:11:47 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:54:28 -0400
commitabcab268303c22d24fc89fedd35d82271d20f5da (patch)
tree2add5b99164734899d92ad37d89b1ded91c219bf
parent1b43af5480c351dbcb2eef478bafe179cbeb6e83 (diff)
[DECNET]: Increase number of possible routing tables to 2^32
Increase the number of possible routing tables to 2^32 by replacing the fixed sized array of pointers by a hash table and replacing iterations over all possible table IDs by hash table walking. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/dn_fib.h3
-rw-r--r--net/decnet/dn_fib.c49
-rw-r--r--net/decnet/dn_rules.c2
-rw-r--r--net/decnet/dn_table.c125
4 files changed, 93 insertions, 86 deletions
diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
index cd9c3782f838..d97aa10c463f 100644
--- a/include/net/dn_fib.h
+++ b/include/net/dn_fib.h
@@ -94,6 +94,7 @@ struct dn_fib_node {
94 94
95 95
96struct dn_fib_table { 96struct dn_fib_table {
97 struct hlist_node hlist;
97 u32 n; 98 u32 n;
98 99
99 int (*insert)(struct dn_fib_table *t, struct rtmsg *r, 100 int (*insert)(struct dn_fib_table *t, struct rtmsg *r,
@@ -177,8 +178,6 @@ static inline void dn_fib_res_put(struct dn_fib_res *res)
177 fib_rule_put(res->r); 178 fib_rule_put(res->r);
178} 179}
179 180
180extern struct dn_fib_table *dn_fib_tables[];
181
182#else /* Endnode */ 181#else /* Endnode */
183 182
184#define dn_fib_init() do { } while(0) 183#define dn_fib_init() do { } while(0)
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index fb596373daa8..5ccca3ed53bd 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -532,39 +532,6 @@ int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
532 return -ENOBUFS; 532 return -ENOBUFS;
533} 533}
534 534
535
536int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
537{
538 u32 t;
539 u32 s_t;
540 struct dn_fib_table *tb;
541
542 if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
543 ((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
544 return dn_cache_dump(skb, cb);
545
546 s_t = cb->args[0];
547 if (s_t == 0)
548 s_t = cb->args[0] = RT_MIN_TABLE;
549
550 for(t = s_t; t <= RT_TABLE_MAX; t++) {
551 if (t < s_t)
552 continue;
553 if (t > s_t)
554 memset(&cb->args[1], 0,
555 sizeof(cb->args) - sizeof(cb->args[0]));
556 tb = dn_fib_get_table(t, 0);
557 if (tb == NULL)
558 continue;
559 if (tb->dump(tb, skb, cb) < 0)
560 break;
561 }
562
563 cb->args[0] = t;
564
565 return skb->len;
566}
567
568static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa) 535static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa)
569{ 536{
570 struct dn_fib_table *tb; 537 struct dn_fib_table *tb;
@@ -762,22 +729,6 @@ int dn_fib_sync_up(struct net_device *dev)
762 return ret; 729 return ret;
763} 730}
764 731
765void dn_fib_flush(void)
766{
767 int flushed = 0;
768 struct dn_fib_table *tb;
769 u32 id;
770
771 for(id = RT_TABLE_MAX; id > 0; id--) {
772 if ((tb = dn_fib_get_table(id, 0)) == NULL)
773 continue;
774 flushed += tb->flush(tb);
775 }
776
777 if (flushed)
778 dn_rt_cache_flush(-1);
779}
780
781static struct notifier_block dn_fib_dnaddr_notifier = { 732static struct notifier_block dn_fib_dnaddr_notifier = {
782 .notifier_call = dn_fib_dnaddr_event, 733 .notifier_call = dn_fib_dnaddr_event,
783}; 734};
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 096f1273e714..878312ff34ec 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -210,7 +210,7 @@ unsigned dnet_addr_type(__le16 addr)
210 struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } }; 210 struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } };
211 struct dn_fib_res res; 211 struct dn_fib_res res;
212 unsigned ret = RTN_UNICAST; 212 unsigned ret = RTN_UNICAST;
213 struct dn_fib_table *tb = dn_fib_tables[RT_TABLE_LOCAL]; 213 struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0);
214 214
215 res.r = NULL; 215 res.r = NULL;
216 216
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index eca7c1e10c80..10e87262b6fb 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -75,9 +75,9 @@ for( ; ((f) = *(fp)) != NULL; (fp) = &(f)->fn_next)
75for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next) 75for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next)
76 76
77#define RT_TABLE_MIN 1 77#define RT_TABLE_MIN 1
78 78#define DN_FIB_TABLE_HASHSZ 256
79static struct hlist_head dn_fib_table_hash[DN_FIB_TABLE_HASHSZ];
79static DEFINE_RWLOCK(dn_fib_tables_lock); 80static DEFINE_RWLOCK(dn_fib_tables_lock);
80struct dn_fib_table *dn_fib_tables[RT_TABLE_MAX + 1];
81 81
82static kmem_cache_t *dn_hash_kmem __read_mostly; 82static kmem_cache_t *dn_hash_kmem __read_mostly;
83static int dn_fib_hash_zombies; 83static int dn_fib_hash_zombies;
@@ -361,7 +361,7 @@ static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
361{ 361{
362 int i, s_i; 362 int i, s_i;
363 363
364 s_i = cb->args[3]; 364 s_i = cb->args[4];
365 for(i = 0; f; i++, f = f->fn_next) { 365 for(i = 0; f; i++, f = f->fn_next) {
366 if (i < s_i) 366 if (i < s_i)
367 continue; 367 continue;
@@ -374,11 +374,11 @@ static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
374 (f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type, 374 (f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type,
375 f->fn_scope, &f->fn_key, dz->dz_order, 375 f->fn_scope, &f->fn_key, dz->dz_order,
376 f->fn_info, NLM_F_MULTI) < 0) { 376 f->fn_info, NLM_F_MULTI) < 0) {
377 cb->args[3] = i; 377 cb->args[4] = i;
378 return -1; 378 return -1;
379 } 379 }
380 } 380 }
381 cb->args[3] = i; 381 cb->args[4] = i;
382 return skb->len; 382 return skb->len;
383} 383}
384 384
@@ -389,20 +389,20 @@ static __inline__ int dn_hash_dump_zone(struct sk_buff *skb,
389{ 389{
390 int h, s_h; 390 int h, s_h;
391 391
392 s_h = cb->args[2]; 392 s_h = cb->args[3];
393 for(h = 0; h < dz->dz_divisor; h++) { 393 for(h = 0; h < dz->dz_divisor; h++) {
394 if (h < s_h) 394 if (h < s_h)
395 continue; 395 continue;
396 if (h > s_h) 396 if (h > s_h)
397 memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0])); 397 memset(&cb->args[4], 0, sizeof(cb->args) - 4*sizeof(cb->args[0]));
398 if (dz->dz_hash == NULL || dz->dz_hash[h] == NULL) 398 if (dz->dz_hash == NULL || dz->dz_hash[h] == NULL)
399 continue; 399 continue;
400 if (dn_hash_dump_bucket(skb, cb, tb, dz, dz->dz_hash[h]) < 0) { 400 if (dn_hash_dump_bucket(skb, cb, tb, dz, dz->dz_hash[h]) < 0) {
401 cb->args[2] = h; 401 cb->args[3] = h;
402 return -1; 402 return -1;
403 } 403 }
404 } 404 }
405 cb->args[2] = h; 405 cb->args[3] = h;
406 return skb->len; 406 return skb->len;
407} 407}
408 408
@@ -413,26 +413,63 @@ static int dn_fib_table_dump(struct dn_fib_table *tb, struct sk_buff *skb,
413 struct dn_zone *dz; 413 struct dn_zone *dz;
414 struct dn_hash *table = (struct dn_hash *)tb->data; 414 struct dn_hash *table = (struct dn_hash *)tb->data;
415 415
416 s_m = cb->args[1]; 416 s_m = cb->args[2];
417 read_lock(&dn_fib_tables_lock); 417 read_lock(&dn_fib_tables_lock);
418 for(dz = table->dh_zone_list, m = 0; dz; dz = dz->dz_next, m++) { 418 for(dz = table->dh_zone_list, m = 0; dz; dz = dz->dz_next, m++) {
419 if (m < s_m) 419 if (m < s_m)
420 continue; 420 continue;
421 if (m > s_m) 421 if (m > s_m)
422 memset(&cb->args[2], 0, sizeof(cb->args) - 2*sizeof(cb->args[0])); 422 memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0]));
423 423
424 if (dn_hash_dump_zone(skb, cb, tb, dz) < 0) { 424 if (dn_hash_dump_zone(skb, cb, tb, dz) < 0) {
425 cb->args[1] = m; 425 cb->args[2] = m;
426 read_unlock(&dn_fib_tables_lock); 426 read_unlock(&dn_fib_tables_lock);
427 return -1; 427 return -1;
428 } 428 }
429 } 429 }
430 read_unlock(&dn_fib_tables_lock); 430 read_unlock(&dn_fib_tables_lock);
431 cb->args[1] = m; 431 cb->args[2] = m;
432 432
433 return skb->len; 433 return skb->len;
434} 434}
435 435
436int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
437{
438 unsigned int h, s_h;
439 unsigned int e = 0, s_e;
440 struct dn_fib_table *tb;
441 struct hlist_node *node;
442 int dumped = 0;
443
444 if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
445 ((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
446 return dn_cache_dump(skb, cb);
447
448 s_h = cb->args[0];
449 s_e = cb->args[1];
450
451 for (h = s_h; h < DN_FIB_TABLE_HASHSZ; h++, s_h = 0) {
452 e = 0;
453 hlist_for_each_entry(tb, node, &dn_fib_table_hash[h], hlist) {
454 if (e < s_e)
455 goto next;
456 if (dumped)
457 memset(&cb->args[2], 0, sizeof(cb->args) -
458 2 * sizeof(cb->args[0]));
459 if (tb->dump(tb, skb, cb) < 0)
460 goto out;
461 dumped = 1;
462next:
463 e++;
464 }
465 }
466out:
467 cb->args[1] = e;
468 cb->args[0] = h;
469
470 return skb->len;
471}
472
436static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req) 473static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req)
437{ 474{
438 struct dn_hash *table = (struct dn_hash *)tb->data; 475 struct dn_hash *table = (struct dn_hash *)tb->data;
@@ -744,6 +781,8 @@ out:
744struct dn_fib_table *dn_fib_get_table(u32 n, int create) 781struct dn_fib_table *dn_fib_get_table(u32 n, int create)
745{ 782{
746 struct dn_fib_table *t; 783 struct dn_fib_table *t;
784 struct hlist_node *node;
785 unsigned int h;
747 786
748 if (n < RT_TABLE_MIN) 787 if (n < RT_TABLE_MIN)
749 return NULL; 788 return NULL;
@@ -751,8 +790,15 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create)
751 if (n > RT_TABLE_MAX) 790 if (n > RT_TABLE_MAX)
752 return NULL; 791 return NULL;
753 792
754 if (dn_fib_tables[n]) 793 h = n & (DN_FIB_TABLE_HASHSZ - 1);
755 return dn_fib_tables[n]; 794 rcu_read_lock();
795 hlist_for_each_entry_rcu(t, node, &dn_fib_table_hash[h], hlist) {
796 if (t->n == n) {
797 rcu_read_unlock();
798 return t;
799 }
800 }
801 rcu_read_unlock();
756 802
757 if (!create) 803 if (!create)
758 return NULL; 804 return NULL;
@@ -773,33 +819,37 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create)
773 t->flush = dn_fib_table_flush; 819 t->flush = dn_fib_table_flush;
774 t->dump = dn_fib_table_dump; 820 t->dump = dn_fib_table_dump;
775 memset(t->data, 0, sizeof(struct dn_hash)); 821 memset(t->data, 0, sizeof(struct dn_hash));
776 dn_fib_tables[n] = t; 822 hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]);
777 823
778 return t; 824 return t;
779} 825}
780 826
781static void dn_fib_del_tree(u32 n)
782{
783 struct dn_fib_table *t;
784
785 write_lock(&dn_fib_tables_lock);
786 t = dn_fib_tables[n];
787 dn_fib_tables[n] = NULL;
788 write_unlock(&dn_fib_tables_lock);
789
790 kfree(t);
791}
792
793struct dn_fib_table *dn_fib_empty_table(void) 827struct dn_fib_table *dn_fib_empty_table(void)
794{ 828{
795 u32 id; 829 u32 id;
796 830
797 for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++) 831 for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++)
798 if (dn_fib_tables[id] == NULL) 832 if (dn_fib_get_table(id, 0) == NULL)
799 return dn_fib_get_table(id, 1); 833 return dn_fib_get_table(id, 1);
800 return NULL; 834 return NULL;
801} 835}
802 836
837void dn_fib_flush(void)
838{
839 int flushed = 0;
840 struct dn_fib_table *tb;
841 struct hlist_node *node;
842 unsigned int h;
843
844 for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
845 hlist_for_each_entry(tb, node, &dn_fib_table_hash[h], hlist)
846 flushed += tb->flush(tb);
847 }
848
849 if (flushed)
850 dn_rt_cache_flush(-1);
851}
852
803void __init dn_fib_table_init(void) 853void __init dn_fib_table_init(void)
804{ 854{
805 dn_hash_kmem = kmem_cache_create("dn_fib_info_cache", 855 dn_hash_kmem = kmem_cache_create("dn_fib_info_cache",
@@ -810,10 +860,17 @@ void __init dn_fib_table_init(void)
810 860
811void __exit dn_fib_table_cleanup(void) 861void __exit dn_fib_table_cleanup(void)
812{ 862{
813 int i; 863 struct dn_fib_table *t;
814 864 struct hlist_node *node, *next;
815 for (i = RT_TABLE_MIN; i <= RT_TABLE_MAX; ++i) 865 unsigned int h;
816 dn_fib_del_tree(i);
817 866
818 return; 867 write_lock(&dn_fib_tables_lock);
868 for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
869 hlist_for_each_entry_safe(t, node, next, &dn_fib_table_hash[h],
870 hlist) {
871 hlist_del(&t->hlist);
872 kfree(t);
873 }
874 }
875 write_unlock(&dn_fib_tables_lock);
819} 876}