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.c80
1 files changed, 16 insertions, 64 deletions
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index bd4ce8681a12..1cf010124ec5 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -17,7 +17,6 @@
17 * this code was copied from it. 17 * this code was copied from it.
18 * 18 *
19 */ 19 */
20#include <linux/config.h>
21#include <linux/string.h> 20#include <linux/string.h>
22#include <linux/net.h> 21#include <linux/net.h>
23#include <linux/socket.h> 22#include <linux/socket.h>
@@ -35,6 +34,7 @@
35#include <net/neighbour.h> 34#include <net/neighbour.h>
36#include <net/dst.h> 35#include <net/dst.h>
37#include <net/flow.h> 36#include <net/flow.h>
37#include <net/fib_rules.h>
38#include <net/dn.h> 38#include <net/dn.h>
39#include <net/dn_route.h> 39#include <net/dn_route.h>
40#include <net/dn_fib.h> 40#include <net/dn_fib.h>
@@ -55,11 +55,9 @@
55 55
56#define endfor_nexthops(fi) } 56#define endfor_nexthops(fi) }
57 57
58extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
59
60static DEFINE_SPINLOCK(dn_fib_multipath_lock); 58static DEFINE_SPINLOCK(dn_fib_multipath_lock);
61static struct dn_fib_info *dn_fib_info_list; 59static struct dn_fib_info *dn_fib_info_list;
62static DEFINE_RWLOCK(dn_fib_info_lock); 60static DEFINE_SPINLOCK(dn_fib_info_lock);
63 61
64static struct 62static struct
65{ 63{
@@ -80,6 +78,9 @@ static struct
80 [RTN_XRESOLVE] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, 78 [RTN_XRESOLVE] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
81}; 79};
82 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
83void dn_fib_free_info(struct dn_fib_info *fi) 84void dn_fib_free_info(struct dn_fib_info *fi)
84{ 85{
85 if (fi->fib_dead == 0) { 86 if (fi->fib_dead == 0) {
@@ -97,7 +98,7 @@ void dn_fib_free_info(struct dn_fib_info *fi)
97 98
98void dn_fib_release_info(struct dn_fib_info *fi) 99void dn_fib_release_info(struct dn_fib_info *fi)
99{ 100{
100 write_lock(&dn_fib_info_lock); 101 spin_lock(&dn_fib_info_lock);
101 if (fi && --fi->fib_treeref == 0) { 102 if (fi && --fi->fib_treeref == 0) {
102 if (fi->fib_next) 103 if (fi->fib_next)
103 fi->fib_next->fib_prev = fi->fib_prev; 104 fi->fib_next->fib_prev = fi->fib_prev;
@@ -108,7 +109,7 @@ void dn_fib_release_info(struct dn_fib_info *fi)
108 fi->fib_dead = 1; 109 fi->fib_dead = 1;
109 dn_fib_info_put(fi); 110 dn_fib_info_put(fi);
110 } 111 }
111 write_unlock(&dn_fib_info_lock); 112 spin_unlock(&dn_fib_info_lock);
112} 113}
113 114
114static 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)
@@ -284,11 +285,10 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta
284 goto err_inval; 285 goto err_inval;
285 } 286 }
286 287
287 fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct dn_fib_nh), GFP_KERNEL); 288 fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct dn_fib_nh), GFP_KERNEL);
288 err = -ENOBUFS; 289 err = -ENOBUFS;
289 if (fi == NULL) 290 if (fi == NULL)
290 goto failure; 291 goto failure;
291 memset(fi, 0, sizeof(*fi)+nhs*sizeof(struct dn_fib_nh));
292 292
293 fi->fib_protocol = r->rtm_protocol; 293 fi->fib_protocol = r->rtm_protocol;
294 fi->fib_nhs = nhs; 294 fi->fib_nhs = nhs;
@@ -380,13 +380,13 @@ link_it:
380 380
381 fi->fib_treeref++; 381 fi->fib_treeref++;
382 atomic_inc(&fi->fib_clntref); 382 atomic_inc(&fi->fib_clntref);
383 write_lock(&dn_fib_info_lock); 383 spin_lock(&dn_fib_info_lock);
384 fi->fib_next = dn_fib_info_list; 384 fi->fib_next = dn_fib_info_list;
385 fi->fib_prev = NULL; 385 fi->fib_prev = NULL;
386 if (dn_fib_info_list) 386 if (dn_fib_info_list)
387 dn_fib_info_list->fib_prev = fi; 387 dn_fib_info_list->fib_prev = fi;
388 dn_fib_info_list = fi; 388 dn_fib_info_list = fi;
389 write_unlock(&dn_fib_info_lock); 389 spin_unlock(&dn_fib_info_lock);
390 return fi; 390 return fi;
391 391
392err_inval: 392err_inval:
@@ -492,7 +492,8 @@ static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
492 if (attr) { 492 if (attr) {
493 if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2) 493 if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2)
494 return -EINVAL; 494 return -EINVAL;
495 if (i != RTA_MULTIPATH && i != RTA_METRICS) 495 if (i != RTA_MULTIPATH && i != RTA_METRICS &&
496 i != RTA_TABLE)
496 rta[i-1] = (struct rtattr *)RTA_DATA(attr); 497 rta[i-1] = (struct rtattr *)RTA_DATA(attr);
497 } 498 }
498 } 499 }
@@ -509,7 +510,7 @@ int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
509 if (dn_fib_check_attr(r, rta)) 510 if (dn_fib_check_attr(r, rta))
510 return -EINVAL; 511 return -EINVAL;
511 512
512 tb = dn_fib_get_table(r->rtm_table, 0); 513 tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 0);
513 if (tb) 514 if (tb)
514 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));
515 516
@@ -525,46 +526,13 @@ int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
525 if (dn_fib_check_attr(r, rta)) 526 if (dn_fib_check_attr(r, rta))
526 return -EINVAL; 527 return -EINVAL;
527 528
528 tb = dn_fib_get_table(r->rtm_table, 1); 529 tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 1);
529 if (tb) 530 if (tb)
530 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));
531 532
532 return -ENOBUFS; 533 return -ENOBUFS;
533} 534}
534 535
535
536int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
537{
538 int t;
539 int 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) 536static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa)
569{ 537{
570 struct dn_fib_table *tb; 538 struct dn_fib_table *tb;
@@ -684,7 +652,7 @@ static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event,
684 return NOTIFY_DONE; 652 return NOTIFY_DONE;
685} 653}
686 654
687int 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)
688{ 656{
689 int ret = 0; 657 int ret = 0;
690 int scope = RT_SCOPE_NOWHERE; 658 int scope = RT_SCOPE_NOWHERE;
@@ -728,7 +696,7 @@ int dn_fib_sync_down(__le16 local, struct net_device *dev, int force)
728} 696}
729 697
730 698
731int dn_fib_sync_up(struct net_device *dev) 699static int dn_fib_sync_up(struct net_device *dev)
732{ 700{
733 int ret = 0; 701 int ret = 0;
734 702
@@ -762,22 +730,6 @@ int dn_fib_sync_up(struct net_device *dev)
762 return ret; 730 return ret;
763} 731}
764 732
765void dn_fib_flush(void)
766{
767 int flushed = 0;
768 struct dn_fib_table *tb;
769 int 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 = { 733static struct notifier_block dn_fib_dnaddr_notifier = {
782 .notifier_call = dn_fib_dnaddr_event, 734 .notifier_call = dn_fib_dnaddr_event,
783}; 735};