aboutsummaryrefslogtreecommitdiffstats
path: root/net/decnet/dn_fib.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/decnet/dn_fib.c')
-rw-r--r--net/decnet/dn_fib.c76
1 files changed, 15 insertions, 61 deletions
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index fa20e2efcfc1..1cf010124ec5 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -34,6 +34,7 @@
34#include <net/neighbour.h> 34#include <net/neighbour.h>
35#include <net/dst.h> 35#include <net/dst.h>
36#include <net/flow.h> 36#include <net/flow.h>
37#include <net/fib_rules.h>
37#include <net/dn.h> 38#include <net/dn.h>
38#include <net/dn_route.h> 39#include <net/dn_route.h>
39#include <net/dn_fib.h> 40#include <net/dn_fib.h>
@@ -54,11 +55,9 @@
54 55
55#define endfor_nexthops(fi) } 56#define endfor_nexthops(fi) }
56 57
57extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
58
59static DEFINE_SPINLOCK(dn_fib_multipath_lock); 58static DEFINE_SPINLOCK(dn_fib_multipath_lock);
60static struct dn_fib_info *dn_fib_info_list; 59static struct dn_fib_info *dn_fib_info_list;
61static DEFINE_RWLOCK(dn_fib_info_lock); 60static DEFINE_SPINLOCK(dn_fib_info_lock);
62 61
63static struct 62static struct
64{ 63{
@@ -79,6 +78,9 @@ static struct
79 [RTN_XRESOLVE] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, 78 [RTN_XRESOLVE] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
80}; 79};
81 80
81static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force);
82static int dn_fib_sync_up(struct net_device *dev);
83
82void dn_fib_free_info(struct dn_fib_info *fi) 84void dn_fib_free_info(struct dn_fib_info *fi)
83{ 85{
84 if (fi->fib_dead == 0) { 86 if (fi->fib_dead == 0) {
@@ -96,7 +98,7 @@ void dn_fib_free_info(struct dn_fib_info *fi)
96 98
97void dn_fib_release_info(struct dn_fib_info *fi) 99void dn_fib_release_info(struct dn_fib_info *fi)
98{ 100{
99 write_lock(&dn_fib_info_lock); 101 spin_lock(&dn_fib_info_lock);
100 if (fi && --fi->fib_treeref == 0) { 102 if (fi && --fi->fib_treeref == 0) {
101 if (fi->fib_next) 103 if (fi->fib_next)
102 fi->fib_next->fib_prev = fi->fib_prev; 104 fi->fib_next->fib_prev = fi->fib_prev;
@@ -107,7 +109,7 @@ void dn_fib_release_info(struct dn_fib_info *fi)
107 fi->fib_dead = 1; 109 fi->fib_dead = 1;
108 dn_fib_info_put(fi); 110 dn_fib_info_put(fi);
109 } 111 }
110 write_unlock(&dn_fib_info_lock); 112 spin_unlock(&dn_fib_info_lock);
111} 113}
112 114
113static inline int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi) 115static inline int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi)
@@ -378,13 +380,13 @@ link_it:
378 380
379 fi->fib_treeref++; 381 fi->fib_treeref++;
380 atomic_inc(&fi->fib_clntref); 382 atomic_inc(&fi->fib_clntref);
381 write_lock(&dn_fib_info_lock); 383 spin_lock(&dn_fib_info_lock);
382 fi->fib_next = dn_fib_info_list; 384 fi->fib_next = dn_fib_info_list;
383 fi->fib_prev = NULL; 385 fi->fib_prev = NULL;
384 if (dn_fib_info_list) 386 if (dn_fib_info_list)
385 dn_fib_info_list->fib_prev = fi; 387 dn_fib_info_list->fib_prev = fi;
386 dn_fib_info_list = fi; 388 dn_fib_info_list = fi;
387 write_unlock(&dn_fib_info_lock); 389 spin_unlock(&dn_fib_info_lock);
388 return fi; 390 return fi;
389 391
390err_inval: 392err_inval:
@@ -490,7 +492,8 @@ static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
490 if (attr) { 492 if (attr) {
491 if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2) 493 if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2)
492 return -EINVAL; 494 return -EINVAL;
493 if (i != RTA_MULTIPATH && i != RTA_METRICS) 495 if (i != RTA_MULTIPATH && i != RTA_METRICS &&
496 i != RTA_TABLE)
494 rta[i-1] = (struct rtattr *)RTA_DATA(attr); 497 rta[i-1] = (struct rtattr *)RTA_DATA(attr);
495 } 498 }
496 } 499 }
@@ -507,7 +510,7 @@ int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
507 if (dn_fib_check_attr(r, rta)) 510 if (dn_fib_check_attr(r, rta))
508 return -EINVAL; 511 return -EINVAL;
509 512
510 tb = dn_fib_get_table(r->rtm_table, 0); 513 tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 0);
511 if (tb) 514 if (tb)
512 return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb)); 515 return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
513 516
@@ -523,46 +526,13 @@ int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
523 if (dn_fib_check_attr(r, rta)) 526 if (dn_fib_check_attr(r, rta))
524 return -EINVAL; 527 return -EINVAL;
525 528
526 tb = dn_fib_get_table(r->rtm_table, 1); 529 tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 1);
527 if (tb) 530 if (tb)
528 return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb)); 531 return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
529 532
530 return -ENOBUFS; 533 return -ENOBUFS;
531} 534}
532 535
533
534int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
535{
536 int t;
537 int s_t;
538 struct dn_fib_table *tb;
539
540 if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
541 ((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
542 return dn_cache_dump(skb, cb);
543
544 s_t = cb->args[0];
545 if (s_t == 0)
546 s_t = cb->args[0] = RT_MIN_TABLE;
547
548 for(t = s_t; t <= RT_TABLE_MAX; t++) {
549 if (t < s_t)
550 continue;
551 if (t > s_t)
552 memset(&cb->args[1], 0,
553 sizeof(cb->args) - sizeof(cb->args[0]));
554 tb = dn_fib_get_table(t, 0);
555 if (tb == NULL)
556 continue;
557 if (tb->dump(tb, skb, cb) < 0)
558 break;
559 }
560
561 cb->args[0] = t;
562
563 return skb->len;
564}
565
566static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa) 536static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa)
567{ 537{
568 struct dn_fib_table *tb; 538 struct dn_fib_table *tb;
@@ -682,7 +652,7 @@ static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event,
682 return NOTIFY_DONE; 652 return NOTIFY_DONE;
683} 653}
684 654
685int dn_fib_sync_down(__le16 local, struct net_device *dev, int force) 655static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force)
686{ 656{
687 int ret = 0; 657 int ret = 0;
688 int scope = RT_SCOPE_NOWHERE; 658 int scope = RT_SCOPE_NOWHERE;
@@ -726,7 +696,7 @@ int dn_fib_sync_down(__le16 local, struct net_device *dev, int force)
726} 696}
727 697
728 698
729int dn_fib_sync_up(struct net_device *dev) 699static int dn_fib_sync_up(struct net_device *dev)
730{ 700{
731 int ret = 0; 701 int ret = 0;
732 702
@@ -760,22 +730,6 @@ int dn_fib_sync_up(struct net_device *dev)
760 return ret; 730 return ret;
761} 731}
762 732
763void dn_fib_flush(void)
764{
765 int flushed = 0;
766 struct dn_fib_table *tb;
767 int id;
768
769 for(id = RT_TABLE_MAX; id > 0; id--) {
770 if ((tb = dn_fib_get_table(id, 0)) == NULL)
771 continue;
772 flushed += tb->flush(tb);
773 }
774
775 if (flushed)
776 dn_rt_cache_flush(-1);
777}
778
779static struct notifier_block dn_fib_dnaddr_notifier = { 733static struct notifier_block dn_fib_dnaddr_notifier = {
780 .notifier_call = dn_fib_dnaddr_event, 734 .notifier_call = dn_fib_dnaddr_event,
781}; 735};