aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorRichard Alpe <richard.alpe@ericsson.com>2014-11-20 04:29:20 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-21 15:01:32 -0500
commit1593123a6a4914ccac4699d7f93cdf8057a7d822 (patch)
tree4dbd419eabf326702b8467761b7ffc5de62152b9 /net
parent27c21416727af73df45051acb05331c0f10e50f6 (diff)
tipc: add name table dump to new netlink api
Add TIPC_NL_NAME_TABLE_GET command to the new tipc netlink API. This command supports dumping the name table of all nodes. Netlink logical layout of name table response message: -> name table -> publication -> type -> lower -> upper -> scope -> node -> ref -> key 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')
-rw-r--r--net/tipc/name_table.c190
-rw-r--r--net/tipc/name_table.h4
-rw-r--r--net/tipc/netlink.c9
3 files changed, 200 insertions, 3 deletions
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 3a6a0a7c0759..30ca8e0e0f84 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/name_table.c: TIPC name table code 2 * net/tipc/name_table.c: TIPC name table code
3 * 3 *
4 * Copyright (c) 2000-2006, Ericsson AB 4 * Copyright (c) 2000-2006, 2014, Ericsson AB
5 * Copyright (c) 2004-2008, 2010-2011, Wind River Systems 5 * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -42,6 +42,12 @@
42 42
43#define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */ 43#define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */
44 44
45static const struct nla_policy
46tipc_nl_name_table_policy[TIPC_NLA_NAME_TABLE_MAX + 1] = {
47 [TIPC_NLA_NAME_TABLE_UNSPEC] = { .type = NLA_UNSPEC },
48 [TIPC_NLA_NAME_TABLE_PUBL] = { .type = NLA_NESTED }
49};
50
45/** 51/**
46 * struct name_info - name sequence publication info 52 * struct name_info - name sequence publication info
47 * @node_list: circular list of publications made by own node 53 * @node_list: circular list of publications made by own node
@@ -995,3 +1001,185 @@ void tipc_nametbl_stop(void)
995 table.types = NULL; 1001 table.types = NULL;
996 write_unlock_bh(&tipc_nametbl_lock); 1002 write_unlock_bh(&tipc_nametbl_lock);
997} 1003}
1004
1005int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, struct name_seq *seq,
1006 struct sub_seq *sseq, u32 *last_publ)
1007{
1008 void *hdr;
1009 struct nlattr *attrs;
1010 struct nlattr *publ;
1011 struct publication *p;
1012
1013 if (*last_publ) {
1014 list_for_each_entry(p, &sseq->info->zone_list, zone_list)
1015 if (p->key == *last_publ)
1016 break;
1017 if (p->key != *last_publ)
1018 return -EPIPE;
1019 } else {
1020 p = list_first_entry(&sseq->info->zone_list, struct publication,
1021 zone_list);
1022 }
1023
1024 list_for_each_entry_from(p, &sseq->info->zone_list, zone_list) {
1025 *last_publ = p->key;
1026
1027 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq,
1028 &tipc_genl_v2_family, NLM_F_MULTI,
1029 TIPC_NL_NAME_TABLE_GET);
1030 if (!hdr)
1031 return -EMSGSIZE;
1032
1033 attrs = nla_nest_start(msg->skb, TIPC_NLA_NAME_TABLE);
1034 if (!attrs)
1035 goto msg_full;
1036
1037 publ = nla_nest_start(msg->skb, TIPC_NLA_NAME_TABLE_PUBL);
1038 if (!publ)
1039 goto attr_msg_full;
1040
1041 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_TYPE, seq->type))
1042 goto publ_msg_full;
1043 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_LOWER, sseq->lower))
1044 goto publ_msg_full;
1045 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_UPPER, sseq->upper))
1046 goto publ_msg_full;
1047 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_SCOPE, p->scope))
1048 goto publ_msg_full;
1049 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_NODE, p->node))
1050 goto publ_msg_full;
1051 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_REF, p->ref))
1052 goto publ_msg_full;
1053 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_KEY, p->key))
1054 goto publ_msg_full;
1055
1056 nla_nest_end(msg->skb, publ);
1057 nla_nest_end(msg->skb, attrs);
1058 genlmsg_end(msg->skb, hdr);
1059 }
1060 *last_publ = 0;
1061
1062 return 0;
1063
1064publ_msg_full:
1065 nla_nest_cancel(msg->skb, publ);
1066attr_msg_full:
1067 nla_nest_cancel(msg->skb, attrs);
1068msg_full:
1069 genlmsg_cancel(msg->skb, hdr);
1070
1071 return -EMSGSIZE;
1072}
1073
1074int __tipc_nl_subseq_list(struct tipc_nl_msg *msg, struct name_seq *seq,
1075 u32 *last_lower, u32 *last_publ)
1076{
1077 struct sub_seq *sseq;
1078 struct sub_seq *sseq_start;
1079 int err;
1080
1081 if (*last_lower) {
1082 sseq_start = nameseq_find_subseq(seq, *last_lower);
1083 if (!sseq_start)
1084 return -EPIPE;
1085 } else {
1086 sseq_start = seq->sseqs;
1087 }
1088
1089 for (sseq = sseq_start; sseq != &seq->sseqs[seq->first_free]; sseq++) {
1090 err = __tipc_nl_add_nametable_publ(msg, seq, sseq, last_publ);
1091 if (err) {
1092 *last_lower = sseq->lower;
1093 return err;
1094 }
1095 }
1096 *last_lower = 0;
1097
1098 return 0;
1099}
1100
1101int __tipc_nl_seq_list(struct tipc_nl_msg *msg, u32 *last_type, u32 *last_lower,
1102 u32 *last_publ)
1103{
1104 struct hlist_head *seq_head;
1105 struct name_seq *seq;
1106 int err;
1107 int i;
1108
1109 if (*last_type)
1110 i = hash(*last_type);
1111 else
1112 i = 0;
1113
1114 for (; i < TIPC_NAMETBL_SIZE; i++) {
1115 seq_head = &table.types[i];
1116
1117 if (*last_type) {
1118 seq = nametbl_find_seq(*last_type);
1119 if (!seq)
1120 return -EPIPE;
1121 } else {
1122 seq = hlist_entry_safe((seq_head)->first,
1123 struct name_seq, ns_list);
1124 if (!seq)
1125 continue;
1126 }
1127
1128 hlist_for_each_entry_from(seq, ns_list) {
1129 spin_lock_bh(&seq->lock);
1130
1131 err = __tipc_nl_subseq_list(msg, seq, last_lower,
1132 last_publ);
1133
1134 if (err) {
1135 *last_type = seq->type;
1136 spin_unlock_bh(&seq->lock);
1137 return err;
1138 }
1139 spin_unlock_bh(&seq->lock);
1140 }
1141 *last_type = 0;
1142 }
1143 return 0;
1144}
1145
1146int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
1147{
1148 int err;
1149 int done = cb->args[3];
1150 u32 last_type = cb->args[0];
1151 u32 last_lower = cb->args[1];
1152 u32 last_publ = cb->args[2];
1153 struct tipc_nl_msg msg;
1154
1155 if (done)
1156 return 0;
1157
1158 msg.skb = skb;
1159 msg.portid = NETLINK_CB(cb->skb).portid;
1160 msg.seq = cb->nlh->nlmsg_seq;
1161
1162 read_lock_bh(&tipc_nametbl_lock);
1163
1164 err = __tipc_nl_seq_list(&msg, &last_type, &last_lower, &last_publ);
1165 if (!err) {
1166 done = 1;
1167 } else if (err != -EMSGSIZE) {
1168 /* We never set seq or call nl_dump_check_consistent() this
1169 * means that setting prev_seq here will cause the consistence
1170 * check to fail in the netlink callback handler. Resulting in
1171 * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if
1172 * we got an error.
1173 */
1174 cb->prev_seq = 1;
1175 }
1176
1177 read_unlock_bh(&tipc_nametbl_lock);
1178
1179 cb->args[0] = last_type;
1180 cb->args[1] = last_lower;
1181 cb->args[2] = last_publ;
1182 cb->args[3] = done;
1183
1184 return skb->len;
1185}
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index f02f48b9a216..b38ebecac766 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/name_table.h: Include file for TIPC name table code 2 * net/tipc/name_table.h: Include file for TIPC name table code
3 * 3 *
4 * Copyright (c) 2000-2006, Ericsson AB 4 * Copyright (c) 2000-2006, 2014, Ericsson AB
5 * Copyright (c) 2004-2005, 2010-2011, Wind River Systems 5 * Copyright (c) 2004-2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -84,6 +84,8 @@ struct publication {
84 84
85extern rwlock_t tipc_nametbl_lock; 85extern rwlock_t tipc_nametbl_lock;
86 86
87int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb);
88
87struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space); 89struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space);
88u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); 90u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node);
89int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, 91int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index cb37d30378a8..b891e3905bc4 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -37,6 +37,7 @@
37#include "core.h" 37#include "core.h"
38#include "config.h" 38#include "config.h"
39#include "socket.h" 39#include "socket.h"
40#include "name_table.h"
40#include "bearer.h" 41#include "bearer.h"
41#include "link.h" 42#include "link.h"
42#include "node.h" 43#include "node.h"
@@ -81,7 +82,8 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
81 [TIPC_NLA_LINK] = { .type = NLA_NESTED, }, 82 [TIPC_NLA_LINK] = { .type = NLA_NESTED, },
82 [TIPC_NLA_MEDIA] = { .type = NLA_NESTED, }, 83 [TIPC_NLA_MEDIA] = { .type = NLA_NESTED, },
83 [TIPC_NLA_NODE] = { .type = NLA_NESTED, }, 84 [TIPC_NLA_NODE] = { .type = NLA_NESTED, },
84 [TIPC_NLA_NET] = { .type = NLA_NESTED, } 85 [TIPC_NLA_NET] = { .type = NLA_NESTED, },
86 [TIPC_NLA_NAME_TABLE] = { .type = NLA_NESTED, }
85}; 87};
86 88
87/* Legacy ASCII API */ 89/* Legacy ASCII API */
@@ -185,6 +187,11 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
185 .cmd = TIPC_NL_NET_SET, 187 .cmd = TIPC_NL_NET_SET,
186 .doit = tipc_nl_net_set, 188 .doit = tipc_nl_net_set,
187 .policy = tipc_nl_policy, 189 .policy = tipc_nl_policy,
190 },
191 {
192 .cmd = TIPC_NL_NAME_TABLE_GET,
193 .dumpit = tipc_nl_name_table_dump,
194 .policy = tipc_nl_policy,
188 } 195 }
189}; 196};
190 197