diff options
author | Richard Alpe <richard.alpe@ericsson.com> | 2014-11-20 04:29:20 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-21 15:01:32 -0500 |
commit | 1593123a6a4914ccac4699d7f93cdf8057a7d822 (patch) | |
tree | 4dbd419eabf326702b8467761b7ffc5de62152b9 /net | |
parent | 27c21416727af73df45051acb05331c0f10e50f6 (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.c | 190 | ||||
-rw-r--r-- | net/tipc/name_table.h | 4 | ||||
-rw-r--r-- | net/tipc/netlink.c | 9 |
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 | ||
45 | static const struct nla_policy | ||
46 | tipc_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 | |||
1005 | int __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 | |||
1064 | publ_msg_full: | ||
1065 | nla_nest_cancel(msg->skb, publ); | ||
1066 | attr_msg_full: | ||
1067 | nla_nest_cancel(msg->skb, attrs); | ||
1068 | msg_full: | ||
1069 | genlmsg_cancel(msg->skb, hdr); | ||
1070 | |||
1071 | return -EMSGSIZE; | ||
1072 | } | ||
1073 | |||
1074 | int __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 | |||
1101 | int __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 | |||
1146 | int 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 | ||
85 | extern rwlock_t tipc_nametbl_lock; | 85 | extern rwlock_t tipc_nametbl_lock; |
86 | 86 | ||
87 | int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb); | ||
88 | |||
87 | struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space); | 89 | struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space); |
88 | u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); | 90 | u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); |
89 | int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, | 91 | int 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 | ||