diff options
| author | Richard Alpe <richard.alpe@ericsson.com> | 2014-11-20 12:29:17 +0300 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-11-21 23:01:31 +0300 | 
| commit | 3e4b6ab58d614934e7ca99bdf448089695d34ffa (patch) | |
| tree | d802397c1372ddba7e63eb784afb13261381d106 /net/tipc/node.c | |
| parent | 1e55417d8fc6f6d93b1cc6995b911d48ded2adfb (diff) | |
| download | linux-3e4b6ab58d614934e7ca99bdf448089695d34ffa.tar.xz | |
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/node.c')
| -rw-r--r-- | net/tipc/node.c | 96 | 
1 files changed, 96 insertions, 0 deletions
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 {  	struct list_head list;  }; +static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { +	[TIPC_NLA_NODE_UNSPEC]		= { .type = NLA_UNSPEC }, +	[TIPC_NLA_NODE_ADDR]		= { .type = NLA_U32 }, +	[TIPC_NLA_NODE_UP]		= { .type = NLA_FLAG } +}; +  /*   * A trivial power-of-two bitmask technique is used for speed, since this   * 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)  		tipc_nametbl_withdraw(TIPC_LINK_STATE, addr,  				      link_id, addr);  } + +/* Caller should hold node lock for the passed node */ +int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node) +{ +	void *hdr; +	struct nlattr *attrs; + +	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family, +			  NLM_F_MULTI, TIPC_NL_NODE_GET); +	if (!hdr) +		return -EMSGSIZE; + +	attrs = nla_nest_start(msg->skb, TIPC_NLA_NODE); +	if (!attrs) +		goto msg_full; + +	if (nla_put_u32(msg->skb, TIPC_NLA_NODE_ADDR, node->addr)) +		goto attr_msg_full; +	if (tipc_node_is_up(node)) +		if (nla_put_flag(msg->skb, TIPC_NLA_NODE_UP)) +			goto attr_msg_full; + +	nla_nest_end(msg->skb, attrs); +	genlmsg_end(msg->skb, hdr); + +	return 0; + +attr_msg_full: +	nla_nest_cancel(msg->skb, attrs); +msg_full: +	genlmsg_cancel(msg->skb, hdr); + +	return -EMSGSIZE; +} + +int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ +	int err; +	int done = cb->args[0]; +	int last_addr = cb->args[1]; +	struct tipc_node *node; +	struct tipc_nl_msg msg; + +	if (done) +		return 0; + +	msg.skb = skb; +	msg.portid = NETLINK_CB(cb->skb).portid; +	msg.seq = cb->nlh->nlmsg_seq; + +	rcu_read_lock(); + +	if (last_addr && !tipc_node_find(last_addr)) { +		rcu_read_unlock(); +		/* We never set seq or call nl_dump_check_consistent() this +		 * means that setting prev_seq here will cause the consistence +		 * check to fail in the netlink callback handler. Resulting in +		 * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if +		 * the node state changed while we released the lock. +		 */ +		cb->prev_seq = 1; +		return -EPIPE; +	} + +	list_for_each_entry_rcu(node, &tipc_node_list, list) { +		if (last_addr) { +			if (node->addr == last_addr) +				last_addr = 0; +			else +				continue; +		} + +		tipc_node_lock(node); +		err = __tipc_nl_add_node(&msg, node); +		if (err) { +			last_addr = node->addr; +			tipc_node_unlock(node); +			goto out; +		} + +		tipc_node_unlock(node); +	} +	done = 1; +out: +	cb->args[0] = done; +	cb->args[1] = last_addr; +	rcu_read_unlock(); + +	return skb->len; +}  | 
