diff options
Diffstat (limited to 'net/decnet/dn_fib.c')
| -rw-r--r-- | net/decnet/dn_fib.c | 80 |
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 | ||
| 58 | extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); | ||
| 59 | |||
| 60 | static DEFINE_SPINLOCK(dn_fib_multipath_lock); | 58 | static DEFINE_SPINLOCK(dn_fib_multipath_lock); |
| 61 | static struct dn_fib_info *dn_fib_info_list; | 59 | static struct dn_fib_info *dn_fib_info_list; |
| 62 | static DEFINE_RWLOCK(dn_fib_info_lock); | 60 | static DEFINE_SPINLOCK(dn_fib_info_lock); |
| 63 | 61 | ||
| 64 | static struct | 62 | static 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 | ||
| 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 | |||
| 83 | void dn_fib_free_info(struct dn_fib_info *fi) | 84 | void 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 | ||
| 98 | void dn_fib_release_info(struct dn_fib_info *fi) | 99 | void 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 | ||
| 114 | 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) |
| @@ -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 | ||
| 392 | err_inval: | 392 | err_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 | |||
| 536 | int 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 | |||
| 568 | 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) |
| 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 | ||
| 687 | 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) |
| 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 | ||
| 731 | int dn_fib_sync_up(struct net_device *dev) | 699 | static 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 | ||
| 765 | void 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 | |||
| 781 | static struct notifier_block dn_fib_dnaddr_notifier = { | 733 | static struct notifier_block dn_fib_dnaddr_notifier = { |
| 782 | .notifier_call = dn_fib_dnaddr_event, | 734 | .notifier_call = dn_fib_dnaddr_event, |
| 783 | }; | 735 | }; |
