1 /*
2 * Copyright (c) 2010 Lawrence Livermore National Lab. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 *
32 */
33
34 #if HAVE_CONFIG_H
35 # include <config.h>
36 #endif /* HAVE_CONFIG_H */
37
38 #define _GNU_SOURCE
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <getopt.h>
43 #include <inttypes.h>
44
45 #include <infiniband/mad.h>
46 #include <infiniband/ibnetdisc.h>
47
48 #include "ibdiag_common.h"
49
50 uint64_t switchguid_before = 0;
51 uint64_t switchguid_after = 0;
52 int switchguid_flag = 0;
53
54 uint64_t caguid_before = 0;
55 uint64_t caguid_after = 0;
56 int caguid_flag = 0;
57
58 uint64_t sysimgguid_before = 0;
59 uint64_t sysimgguid_after = 0;
60 int sysimgguid_flag = 0;
61
62 uint64_t portguid_nodeguid = 0;
63 uint64_t portguid_before = 0;
64 uint64_t portguid_after = 0;
65 int portguid_flag = 0;
66
67 struct guids {
68 uint64_t searchguid;
69 int searchguid_found;
70 uint64_t before;
71 uint64_t after;
72 int found;
73 };
74
parse_beforeafter(char * arg,uint64_t * before,uint64_t * after)75 static int parse_beforeafter(char *arg, uint64_t *before, uint64_t *after)
76 {
77 char *ptr;
78 char *before_str;
79 char *after_str;
80
81 ptr = strchr(optarg, ':');
82 if (!ptr || !(*(ptr + 1))) {
83 fprintf(stderr, "invalid input '%s'\n", arg);
84 return -1;
85 }
86 (*ptr) = '\0';
87 before_str = arg;
88 after_str = ptr + 1;
89
90 (*before) = strtoull(before_str, 0, 0);
91 (*after) = strtoull(after_str, 0, 0);
92 return 0;
93 }
94
parse_guidbeforeafter(char * arg,uint64_t * guid,uint64_t * before,uint64_t * after)95 static int parse_guidbeforeafter(char *arg,
96 uint64_t *guid,
97 uint64_t *before,
98 uint64_t *after)
99 {
100 char *ptr1;
101 char *ptr2;
102 char *guid_str;
103 char *before_str;
104 char *after_str;
105
106 ptr1 = strchr(optarg, ':');
107 if (!ptr1 || !(*(ptr1 + 1))) {
108 fprintf(stderr, "invalid input '%s'\n", arg);
109 return -1;
110 }
111 guid_str = arg;
112 before_str = ptr1 + 1;
113
114 ptr2 = strchr(before_str, ':');
115 if (!ptr2 || !(*(ptr2 + 1))) {
116 fprintf(stderr, "invalid input '%s'\n", arg);
117 return -1;
118 }
119 (*ptr1) = '\0';
120 (*ptr2) = '\0';
121 after_str = ptr2 + 1;
122
123 (*guid) = strtoull(guid_str, 0, 0);
124 (*before) = strtoull(before_str, 0, 0);
125 (*after) = strtoull(after_str, 0, 0);
126 return 0;
127 }
128
process_opt(void * context,int ch,char * optarg)129 static int process_opt(void *context, int ch, char *optarg)
130 {
131 switch (ch) {
132 case 1:
133 if (parse_beforeafter(optarg,
134 &switchguid_before,
135 &switchguid_after) < 0)
136 return -1;
137 switchguid_flag++;
138 break;
139 case 2:
140 if (parse_beforeafter(optarg,
141 &caguid_before,
142 &caguid_after) < 0)
143 return -1;
144 caguid_flag++;
145 break;
146 case 3:
147 if (parse_beforeafter(optarg,
148 &sysimgguid_before,
149 &sysimgguid_after) < 0)
150 return -1;
151 sysimgguid_flag++;
152 break;
153 case 4:
154 if (parse_guidbeforeafter(optarg,
155 &portguid_nodeguid,
156 &portguid_before,
157 &portguid_after) < 0)
158 return -1;
159 portguid_flag++;
160 break;
161 default:
162 return -1;
163 }
164
165 return 0;
166 }
167
update_switchportguids(ibnd_node_t * node)168 static void update_switchportguids(ibnd_node_t *node)
169 {
170 ibnd_port_t *port;
171 int p;
172
173 for (p = 0; p <= node->numports; p++) {
174 port = node->ports[p];
175 if (port)
176 port->guid = node->guid;
177 }
178 }
179
replace_node_guid(ibnd_node_t * node,void * user_data)180 static void replace_node_guid(ibnd_node_t *node, void *user_data)
181 {
182 struct guids *guids;
183
184 guids = (struct guids *)user_data;
185
186 if (node->guid == guids->before) {
187
188 node->guid = guids->after;
189
190 /* port guids are identical to switch guids on
191 * switches, so update port guids too
192 */
193 if (node->type == IB_NODE_SWITCH)
194 update_switchportguids(node);
195
196 guids->found++;
197 }
198 }
199
replace_sysimgguid(ibnd_node_t * node,void * user_data)200 static void replace_sysimgguid(ibnd_node_t *node, void *user_data)
201 {
202 struct guids *guids;
203 uint64_t sysimgguid;
204
205 guids = (struct guids *)user_data;
206
207 sysimgguid = mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
208 if (sysimgguid == guids->before) {
209 mad_set_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F,
210 guids->after);
211 guids->found++;
212 }
213 }
214
replace_portguid(ibnd_node_t * node,void * user_data)215 static void replace_portguid(ibnd_node_t *node, void *user_data)
216 {
217 struct guids *guids;
218
219 guids = (struct guids *)user_data;
220
221 if (node->guid != guids->searchguid)
222 return;
223
224 guids->searchguid_found++;
225
226 if (node->type == IB_NODE_SWITCH) {
227 /* port guids are identical to switch guids on
228 * switches, so update switch guid too
229 */
230 if (node->guid == guids->before) {
231 node->guid = guids->after;
232 update_switchportguids(node);
233 guids->found++;
234 }
235 }
236 else {
237 ibnd_port_t *port;
238 int p;
239
240 for (p = 1; p <= node->numports; p++) {
241 port = node->ports[p];
242 if (port
243 && port->guid == guids->before) {
244 port->guid = guids->after;
245 guids->found++;
246 break;
247 }
248 }
249 }
250 }
251
main(int argc,char ** argv)252 int main(int argc, char **argv)
253 {
254 ibnd_fabric_t *fabric = NULL;
255 char *orig_cache_file = NULL;
256 char *new_cache_file = NULL;
257 struct guids guids;
258
259 const struct ibdiag_opt opts[] = {
260 {"switchguid", 1, 1, "BEFOREGUID:AFTERGUID",
261 "Specify before and after switchguid to edit"},
262 {"caguid", 2, 1, "BEFOREGUID:AFTERGUID",
263 "Specify before and after caguid to edit"},
264 {"sysimgguid", 3, 1, "BEFOREGUID:AFTERGUID",
265 "Specify before and after sysimgguid to edit"},
266 {"portguid", 4, 1, "NODEGUID:BEFOREGUID:AFTERGUID",
267 "Specify before and after port guid to edit"},
268 {0}
269 };
270 char *usage_args = "<orig.cache> <new.cache>";
271
272 ibdiag_process_opts(argc, argv, NULL, "CDdeGKLPstvy",
273 opts, process_opt, usage_args,
274 NULL);
275
276 argc -= optind;
277 argv += optind;
278
279 orig_cache_file = argv[0];
280 new_cache_file = argv[1];
281
282 if (!orig_cache_file)
283 IBEXIT("original cache file not specified");
284
285 if (!new_cache_file)
286 IBEXIT("new cache file not specified");
287
288 if ((fabric = ibnd_load_fabric(orig_cache_file, 0)) == NULL)
289 IBEXIT("loading original cached fabric failed");
290
291 if (switchguid_flag) {
292 guids.before = switchguid_before;
293 guids.after = switchguid_after;
294 guids.found = 0;
295 ibnd_iter_nodes_type(fabric,
296 replace_node_guid,
297 IB_NODE_SWITCH,
298 &guids);
299
300 if (!guids.found)
301 IBEXIT("switchguid = %" PRIx64 " not found",
302 switchguid_before);
303 }
304
305 if (caguid_flag) {
306 guids.before = caguid_before;
307 guids.after = caguid_after;
308 guids.found = 0;
309 ibnd_iter_nodes_type(fabric,
310 replace_node_guid,
311 IB_NODE_CA,
312 &guids);
313
314 if (!guids.found)
315 IBEXIT("caguid = %" PRIx64 " not found",
316 caguid_before);
317 }
318
319 if (sysimgguid_flag) {
320 guids.before = sysimgguid_before;
321 guids.after = sysimgguid_after;
322 guids.found = 0;
323 ibnd_iter_nodes(fabric,
324 replace_sysimgguid,
325 &guids);
326
327 if (!guids.found)
328 IBEXIT("sysimgguid = %" PRIx64 " not found",
329 sysimgguid_before);
330 }
331
332 if (portguid_flag) {
333 guids.searchguid = portguid_nodeguid;
334 guids.searchguid_found = 0;
335 guids.before = portguid_before;
336 guids.after = portguid_after;
337 guids.found = 0;
338 ibnd_iter_nodes(fabric,
339 replace_portguid,
340 &guids);
341
342 if (!guids.searchguid_found)
343 IBEXIT("nodeguid = %" PRIx64 " not found",
344 portguid_nodeguid);
345
346 if (!guids.found)
347 IBEXIT("portguid = %" PRIx64 " not found",
348 portguid_before);
349 }
350
351 if (ibnd_cache_fabric(fabric, new_cache_file, 0) < 0)
352 IBEXIT("caching new cache data failed");
353
354 ibnd_destroy_fabric(fabric);
355 exit(0);
356 }
357