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 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 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 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 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 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 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 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 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