aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Alpe <richard.alpe@ericsson.com>2014-11-20 04:29:17 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-21 15:01:31 -0500
commit3e4b6ab58d614934e7ca99bdf448089695d34ffa (patch)
treed802397c1372ddba7e63eb784afb13261381d106
parent1e55417d8fc6f6d93b1cc6995b911d48ded2adfb (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>
-rw-r--r--include/uapi/linux/tipc_netlink.h12
-rw-r--r--net/tipc/netlink.c7
-rw-r--r--net/tipc/node.c96
-rw-r--r--net/tipc/node.h4
4 files changed, 118 insertions, 1 deletions
diff --git a/include/uapi/linux/tipc_netlink.h b/include/uapi/linux/tipc_netlink.h
index 43beef28d67f..08a793374e8c 100644
--- a/include/uapi/linux/tipc_netlink.h
+++ b/include/uapi/linux/tipc_netlink.h
@@ -52,6 +52,7 @@ enum {
52 TIPC_NL_LINK_RESET_STATS, 52 TIPC_NL_LINK_RESET_STATS,
53 TIPC_NL_MEDIA_GET, 53 TIPC_NL_MEDIA_GET,
54 TIPC_NL_MEDIA_SET, 54 TIPC_NL_MEDIA_SET,
55 TIPC_NL_NODE_GET,
55 56
56 __TIPC_NL_CMD_MAX, 57 __TIPC_NL_CMD_MAX,
57 TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1 58 TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@@ -65,6 +66,7 @@ enum {
65 TIPC_NLA_PUBL, /* nest */ 66 TIPC_NLA_PUBL, /* nest */
66 TIPC_NLA_LINK, /* nest */ 67 TIPC_NLA_LINK, /* nest */
67 TIPC_NLA_MEDIA, /* nest */ 68 TIPC_NLA_MEDIA, /* nest */
69 TIPC_NLA_NODE, /* nest */
68 70
69 __TIPC_NLA_MAX, 71 __TIPC_NLA_MAX,
70 TIPC_NLA_MAX = __TIPC_NLA_MAX - 1 72 TIPC_NLA_MAX = __TIPC_NLA_MAX - 1
@@ -121,6 +123,16 @@ enum {
121 TIPC_NLA_MEDIA_MAX = __TIPC_NLA_MEDIA_MAX - 1 123 TIPC_NLA_MEDIA_MAX = __TIPC_NLA_MEDIA_MAX - 1
122}; 124};
123 125
126/* Node info */
127enum {
128 TIPC_NLA_NODE_UNSPEC,
129 TIPC_NLA_NODE_ADDR, /* u32 */
130 TIPC_NLA_NODE_UP, /* flag */
131
132 __TIPC_NLA_NODE_MAX,
133 TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1
134};
135
124/* Publication info */ 136/* Publication info */
125enum { 137enum {
126 TIPC_NLA_PUBL_UNSPEC, 138 TIPC_NLA_PUBL_UNSPEC,
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
44static int handle_cmd(struct sk_buff *skb, struct genl_info *info) 45static 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
61static 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 */
612int __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
637attr_msg_full:
638 nla_nest_cancel(msg->skb, attrs);
639msg_full:
640 genlmsg_cancel(msg->skb, hdr);
641
642 return -EMSGSIZE;
643}
644
645int 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;
693out:
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);
145int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port); 145int tipc_node_add_conn(u32 dnode, u32 port, u32 peer_port);
146void tipc_node_remove_conn(u32 dnode, u32 port); 146void tipc_node_remove_conn(u32 dnode, u32 port);
147 147
148int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb);
149
148static inline void tipc_node_lock(struct tipc_node *node) 150static inline void tipc_node_lock(struct tipc_node *node)
149{ 151{
150 spin_lock_bh(&node->lock); 152 spin_lock_bh(&node->lock);