diff options
Diffstat (limited to 'net/decnet/dn_fib.c')
-rw-r--r-- | net/decnet/dn_fib.c | 76 |
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 | ||
57 | extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); | ||
58 | |||
59 | static DEFINE_SPINLOCK(dn_fib_multipath_lock); | 58 | static DEFINE_SPINLOCK(dn_fib_multipath_lock); |
60 | static struct dn_fib_info *dn_fib_info_list; | 59 | static struct dn_fib_info *dn_fib_info_list; |
61 | static DEFINE_RWLOCK(dn_fib_info_lock); | 60 | static DEFINE_SPINLOCK(dn_fib_info_lock); |
62 | 61 | ||
63 | static struct | 62 | static 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 | ||
81 | static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force); | ||
82 | static int dn_fib_sync_up(struct net_device *dev); | ||
83 | |||
82 | void dn_fib_free_info(struct dn_fib_info *fi) | 84 | void 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 | ||
97 | void dn_fib_release_info(struct dn_fib_info *fi) | 99 | void 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 | ||
113 | static inline int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi) | 115 | static 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 | ||
390 | err_inval: | 392 | err_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 | |||
534 | int 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 | |||
566 | static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa) | 536 | static 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 | ||
685 | int dn_fib_sync_down(__le16 local, struct net_device *dev, int force) | 655 | static 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 | ||
729 | int dn_fib_sync_up(struct net_device *dev) | 699 | static 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 | ||
763 | void 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 | |||
779 | static struct notifier_block dn_fib_dnaddr_notifier = { | 733 | static struct notifier_block dn_fib_dnaddr_notifier = { |
780 | .notifier_call = dn_fib_dnaddr_event, | 734 | .notifier_call = dn_fib_dnaddr_event, |
781 | }; | 735 | }; |