diff options
| author | Richard Alpe <richard.alpe@ericsson.com> | 2014-11-20 04:29:17 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-11-21 15:01:31 -0500 |
| commit | 3e4b6ab58d614934e7ca99bdf448089695d34ffa (patch) | |
| tree | d802397c1372ddba7e63eb784afb13261381d106 /net/tipc | |
| parent | 1e55417d8fc6f6d93b1cc6995b911d48ded2adfb (diff) | |
tipc: add node get/dump to new netlink api
Add TIPC_NL_NODE_GET to the new tipc netlink API.
This command can dump the address and node status of all nodes in the
tipc cluster.
Netlink logical layout of returned node/address data:
-> node
-> address
-> up flag
Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/netlink.c | 7 | ||||
| -rw-r--r-- | net/tipc/node.c | 96 | ||||
| -rw-r--r-- | net/tipc/node.h | 4 |
3 files changed, 106 insertions, 1 deletions
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 8673e370b7ed..5b0e3c8457d2 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include "socket.h" | 39 | #include "socket.h" |
| 40 | #include "bearer.h" | 40 | #include "bearer.h" |
| 41 | #include "link.h" | 41 | #include "link.h" |
| 42 | #include "node.h" | ||
| 42 | #include <net/genetlink.h> | 43 | #include <net/genetlink.h> |
| 43 | 44 | ||
| 44 | static int handle_cmd(struct sk_buff *skb, struct genl_info *info) | 45 | static int handle_cmd(struct sk_buff *skb, struct genl_info *info) |
| @@ -78,6 +79,7 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = { | |||
| 78 | [TIPC_NLA_PUBL] = { .type = NLA_NESTED, }, | 79 | [TIPC_NLA_PUBL] = { .type = NLA_NESTED, }, |
| 79 | [TIPC_NLA_LINK] = { .type = NLA_NESTED, }, | 80 | [TIPC_NLA_LINK] = { .type = NLA_NESTED, }, |
| 80 | [TIPC_NLA_MEDIA] = { .type = NLA_NESTED, }, | 81 | [TIPC_NLA_MEDIA] = { .type = NLA_NESTED, }, |
| 82 | [TIPC_NLA_NODE] = { .type = NLA_NESTED, } | ||
| 81 | }; | 83 | }; |
| 82 | 84 | ||
| 83 | /* Legacy ASCII API */ | 85 | /* Legacy ASCII API */ |
| @@ -166,6 +168,11 @@ static const struct genl_ops tipc_genl_v2_ops[] = { | |||
| 166 | .cmd = TIPC_NL_MEDIA_SET, | 168 | .cmd = TIPC_NL_MEDIA_SET, |
| 167 | .doit = tipc_nl_media_set, | 169 | .doit = tipc_nl_media_set, |
| 168 | .policy = tipc_nl_policy, | 170 | .policy = tipc_nl_policy, |
| 171 | }, | ||
| 172 | { | ||
| 173 | .cmd = TIPC_NL_NODE_GET, | ||
| 174 | .dumpit = tipc_nl_node_dump, | ||
| 175 | .policy = tipc_nl_policy, | ||
| 169 | } | 176 | } |
| 170 | }; | 177 | }; |
| 171 | 178 | ||
diff --git a/net/tipc/node.c b/net/tipc/node.c index 5781634e957d..72a75d4838b2 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
| @@ -58,6 +58,12 @@ struct tipc_sock_conn { | |||
| 58 | struct list_head list; | 58 | struct list_head list; |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { | ||
| 62 | [TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC }, | ||
| 63 | [TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 }, | ||
| 64 | [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG } | ||
| 65 | }; | ||
| 66 | |||
| 61 | /* | 67 | /* |
| 62 | * A trivial power-of-two bitmask technique is used for speed, since this | 68 | * A trivial power-of-two bitmask technique is used for speed, since this |
| 63 | * operation is done for every incoming TIPC packet. The number of hash table | 69 | * operation is done for every incoming TIPC packet. The number of hash table |
| @@ -601,3 +607,93 @@ void tipc_node_unlock(struct tipc_node *node) | |||
| 601 | tipc_nametbl_withdraw(TIPC_LINK_STATE, addr, | 607 | tipc_nametbl_withdraw(TIPC_LINK_STATE, addr, |
| 602 | link_id, addr); | 608 | link_id, addr); |
| 603 | } | 609 | } |
| 610 | |||
| 611 | /* Caller should hold node lock for the passed node */ | ||
| 612 | int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node) | ||
| 613 | { | ||
| 614 | void *hdr; | ||
| 615 | struct nlattr *attrs; | ||
| 616 | |||
| 617 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, | ||
| 618 | NLM_F_MULTI, TIPC_NL_NODE_GET); | ||
| 619 | if (!hdr) | ||
| 620 | return -EMSGSIZE; | ||
| 621 | |||
| 622 | attrs = nla_nest_start(msg->skb, TIPC_NLA_NODE); | ||
| 623 | if (!attrs) | ||
| 624 | goto msg_full; | ||
| 625 | |||
| 626 | if (nla_put_u32(msg->skb, TIPC_NLA_NODE_ADDR, node->addr)) | ||
| 627 | goto attr_msg_full; | ||
| 628 | if (tipc_node_is_up(node)) | ||
| 629 | if (nla_put_flag(msg->skb, TIPC_NLA_NODE_UP)) | ||
| 630 | goto attr_msg_full; | ||
| 631 | |||
| 632 | nla_nest_end(msg->skb, attrs); | ||
| 633 | genlmsg_end(msg->skb, hdr); | ||
| 634 | |||
| 635 | return 0; | ||
| 636 | |||
| 637 | attr_msg_full: | ||
| 638 | nla_nest_cancel(msg->skb, attrs); | ||
| 639 | msg_full: | ||
| 640 | genlmsg_cancel(msg->skb, hdr); | ||
| 641 | |||
| 642 | return -EMSGSIZE; | ||
| 643 | } | ||
| 644 | |||
| 645 | int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
| 646 | { | ||
| 647 | int err; | ||
| 648 | int done = cb->args[0]; | ||
| 649 | int last_addr = cb->args[1]; | ||
| 650 | struct tipc_node *node; | ||
| 651 | struct tipc_nl_msg msg; | ||
| 652 | |||
| 653 | if (done) | ||
| 654 | return 0; | ||
| 655 | |||
| 656 | msg.skb = skb; | ||
| 657 | msg.portid = NETLINK_CB(cb->skb).portid; | ||
| 658 | msg.seq = cb->nlh->nlmsg_seq; | ||
| 659 | |||
| 660 | rcu_read_lock(); | ||
| 661 | |||
| 662 | if (last_addr && !tipc_node_find(last_addr)) { | ||
| 663 | rcu_read_unlock(); | ||
| 664 | /* We never set seq or call nl_dump_check_consistent() this | ||
| 665 | * means that setting prev_seq here will cause the consistence | ||
| 666 | * check to fail in the netlink callback handler. Resulting in | ||
| 667 | * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if | ||
| 668 | * the node state changed while we released the lock. | ||
| 669 | */ | ||
| 670 | cb->prev_seq = 1; | ||
| 671 | return -EPIPE; | ||
| 672 | } | ||
| 673 | |||
| 674 | list_for_each_entry_rcu(node, &tipc_node_list, list) { | ||
| 675 | if (last_addr) { | ||
| 676 | if (node->addr == last_addr) | ||
| 677 | last_addr = 0; | ||
| 678 | else | ||
| 679 | continue; | ||
| 680 | } | ||
| 681 | |||
| 682 | tipc_node_lock(node); | ||
| 683 | err = __tipc_nl_add_node(&msg, node); | ||
| 684 | if (err) { | ||
| 685 | last_addr = node->addr; | ||
| 686 | tipc_node_unlock(node); | ||
| 687 | goto out; | ||
| 688 | } | ||
| 689 | |||
| 690 | tipc_node_unlock(node); | ||
| 691 | } | ||
| 692 | done = 1; | ||
| 693 | out: | ||
| 694 | cb->args[0] = done; | ||
| 695 | cb->args[1] = last_addr; | ||
| 696 | rcu_read_unlock(); | ||
| 697 | |||
| 698 | return skb->len; | ||
| 699 | } | ||
diff --git a/net/tipc/node.h b/net/tipc/node.h index 04e91458bb29..005fbcef3212 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * net/tipc/node.h: Include file for TIPC node management routines | 2 | * net/tipc/node.h: Include file for TIPC node management routines |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2000-2006, Ericsson AB | 4 | * Copyright (c) 2000-2006, 2014, Ericsson AB |
| 5 | * Copyright (c) 2005, 2010-2014, Wind River Systems | 5 | * Copyright (c) 2005, 2010-2014, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| @@ -145,6 +145,8 @@ void tipc_node_unlock(struct tipc_node *node); | |||
| 145 | int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port); | 145 | int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port); |
| 146 | void tipc_node_remove_conn(u32 dnode, u32 port); | 146 | void tipc_node_remove_conn(u32 dnode, u32 port); |
| 147 | 147 | ||
| 148 | int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb); | ||
| 149 | |||
| 148 | static inline void tipc_node_lock(struct tipc_node *node) | 150 | static inline void tipc_node_lock(struct tipc_node *node) |
| 149 | { | 151 | { |
| 150 | spin_lock_bh(&node->lock); | 152 | spin_lock_bh(&node->lock); |
