|
Packit |
db064d |
/*
|
|
Packit |
db064d |
* Copyright (c) 2010 Lawrence Livermore National Lab. All rights reserved.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* This software is available to you under a choice of one of two
|
|
Packit |
db064d |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
db064d |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
db064d |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
db064d |
* OpenIB.org BSD license below:
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
db064d |
* without modification, are permitted provided that the following
|
|
Packit |
db064d |
* conditions are met:
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* - Redistributions of source code must retain the above
|
|
Packit |
db064d |
* copyright notice, this list of conditions and the following
|
|
Packit |
db064d |
* disclaimer.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
db064d |
* copyright notice, this list of conditions and the following
|
|
Packit |
db064d |
* disclaimer in the documentation and/or other materials
|
|
Packit |
db064d |
* provided with the distribution.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
db064d |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
db064d |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
db064d |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
db064d |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
db064d |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
db064d |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
db064d |
* SOFTWARE.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
*/
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#if HAVE_CONFIG_H
|
|
Packit |
db064d |
# include <config.h>
|
|
Packit |
db064d |
#endif /* HAVE_CONFIG_H */
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#define _GNU_SOURCE
|
|
Packit |
db064d |
#include <stdio.h>
|
|
Packit |
db064d |
#include <stdlib.h>
|
|
Packit |
db064d |
#include <string.h>
|
|
Packit |
db064d |
#include <inttypes.h>
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#include <infiniband/mad.h>
|
|
Packit |
db064d |
#include <infiniband/ibnetdisc.h>
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#include "ibdiag_common.h"
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static uint64_t switchguid_before;
|
|
Packit |
db064d |
static uint64_t switchguid_after;
|
|
Packit |
db064d |
static int switchguid_flag;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static uint64_t caguid_before;
|
|
Packit |
db064d |
static uint64_t caguid_after;
|
|
Packit |
db064d |
static int caguid_flag;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static uint64_t sysimgguid_before;
|
|
Packit |
db064d |
static uint64_t sysimgguid_after;
|
|
Packit |
db064d |
static int sysimgguid_flag;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static uint64_t portguid_nodeguid;
|
|
Packit |
db064d |
static uint64_t portguid_before;
|
|
Packit |
db064d |
static uint64_t portguid_after;
|
|
Packit |
db064d |
static int portguid_flag;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
struct guids {
|
|
Packit |
db064d |
uint64_t searchguid;
|
|
Packit |
db064d |
int searchguid_found;
|
|
Packit |
db064d |
uint64_t before;
|
|
Packit |
db064d |
uint64_t after;
|
|
Packit |
db064d |
int found;
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int parse_beforeafter(char *arg, uint64_t *before, uint64_t *after)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char *ptr;
|
|
Packit |
db064d |
char *before_str;
|
|
Packit |
db064d |
char *after_str;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
ptr = strchr(optarg, ':');
|
|
Packit |
db064d |
if (!ptr || !(*(ptr + 1))) {
|
|
Packit |
db064d |
fprintf(stderr, "invalid input '%s'\n", arg);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
(*ptr) = '\0';
|
|
Packit |
db064d |
before_str = arg;
|
|
Packit |
db064d |
after_str = ptr + 1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
(*before) = strtoull(before_str, NULL, 0);
|
|
Packit |
db064d |
(*after) = strtoull(after_str, NULL, 0);
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int parse_guidbeforeafter(char *arg,
|
|
Packit |
db064d |
uint64_t *guid,
|
|
Packit |
db064d |
uint64_t *before,
|
|
Packit |
db064d |
uint64_t *after)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char *ptr1;
|
|
Packit |
db064d |
char *ptr2;
|
|
Packit |
db064d |
char *guid_str;
|
|
Packit |
db064d |
char *before_str;
|
|
Packit |
db064d |
char *after_str;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
ptr1 = strchr(optarg, ':');
|
|
Packit |
db064d |
if (!ptr1 || !(*(ptr1 + 1))) {
|
|
Packit |
db064d |
fprintf(stderr, "invalid input '%s'\n", arg);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
guid_str = arg;
|
|
Packit |
db064d |
before_str = ptr1 + 1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
ptr2 = strchr(before_str, ':');
|
|
Packit |
db064d |
if (!ptr2 || !(*(ptr2 + 1))) {
|
|
Packit |
db064d |
fprintf(stderr, "invalid input '%s'\n", arg);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
(*ptr1) = '\0';
|
|
Packit |
db064d |
(*ptr2) = '\0';
|
|
Packit |
db064d |
after_str = ptr2 + 1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
(*guid) = strtoull(guid_str, NULL, 0);
|
|
Packit |
db064d |
(*before) = strtoull(before_str, NULL, 0);
|
|
Packit |
db064d |
(*after) = strtoull(after_str, NULL, 0);
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int process_opt(void *context, int ch)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
switch (ch) {
|
|
Packit |
db064d |
case 1:
|
|
Packit |
db064d |
if (parse_beforeafter(optarg,
|
|
Packit |
db064d |
&switchguid_before,
|
|
Packit |
db064d |
&switchguid_after) < 0)
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
switchguid_flag++;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case 2:
|
|
Packit |
db064d |
if (parse_beforeafter(optarg,
|
|
Packit |
db064d |
&caguid_before,
|
|
Packit |
db064d |
&caguid_after) < 0)
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
caguid_flag++;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case 3:
|
|
Packit |
db064d |
if (parse_beforeafter(optarg,
|
|
Packit |
db064d |
&sysimgguid_before,
|
|
Packit |
db064d |
&sysimgguid_after) < 0)
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
sysimgguid_flag++;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case 4:
|
|
Packit |
db064d |
if (parse_guidbeforeafter(optarg,
|
|
Packit |
db064d |
&portguid_nodeguid,
|
|
Packit |
db064d |
&portguid_before,
|
|
Packit |
db064d |
&portguid_after) < 0)
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
portguid_flag++;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
default:
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static void update_switchportguids(ibnd_node_t *node)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
ibnd_port_t *port;
|
|
Packit |
db064d |
int p;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
for (p = 0; p <= node->numports; p++) {
|
|
Packit |
db064d |
port = node->ports[p];
|
|
Packit |
db064d |
if (port)
|
|
Packit |
db064d |
port->guid = node->guid;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static void replace_node_guid(ibnd_node_t *node, void *user_data)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
struct guids *guids;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
guids = (struct guids *)user_data;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (node->guid == guids->before) {
|
|
Packit |
db064d |
|
|
Packit |
db064d |
node->guid = guids->after;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
/* port guids are identical to switch guids on
|
|
Packit |
db064d |
* switches, so update port guids too
|
|
Packit |
db064d |
*/
|
|
Packit |
db064d |
if (node->type == IB_NODE_SWITCH)
|
|
Packit |
db064d |
update_switchportguids(node);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
guids->found++;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static void replace_sysimgguid(ibnd_node_t *node, void *user_data)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
struct guids *guids;
|
|
Packit |
db064d |
uint64_t sysimgguid;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
guids = (struct guids *)user_data;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
sysimgguid = mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
|
|
Packit |
db064d |
if (sysimgguid == guids->before) {
|
|
Packit |
db064d |
mad_set_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F,
|
|
Packit |
db064d |
guids->after);
|
|
Packit |
db064d |
guids->found++;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static void replace_portguid(ibnd_node_t *node, void *user_data)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
struct guids *guids;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
guids = (struct guids *)user_data;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (node->guid != guids->searchguid)
|
|
Packit |
db064d |
return;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
guids->searchguid_found++;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (node->type == IB_NODE_SWITCH) {
|
|
Packit |
db064d |
/* port guids are identical to switch guids on
|
|
Packit |
db064d |
* switches, so update switch guid too
|
|
Packit |
db064d |
*/
|
|
Packit |
db064d |
if (node->guid == guids->before) {
|
|
Packit |
db064d |
node->guid = guids->after;
|
|
Packit |
db064d |
update_switchportguids(node);
|
|
Packit |
db064d |
guids->found++;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
else {
|
|
Packit |
db064d |
ibnd_port_t *port;
|
|
Packit |
db064d |
int p;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
for (p = 1; p <= node->numports; p++) {
|
|
Packit |
db064d |
port = node->ports[p];
|
|
Packit |
db064d |
if (port
|
|
Packit |
db064d |
&& port->guid == guids->before) {
|
|
Packit |
db064d |
port->guid = guids->after;
|
|
Packit |
db064d |
guids->found++;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
int main(int argc, char **argv)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
ibnd_fabric_t *fabric = NULL;
|
|
Packit |
db064d |
char *orig_cache_file = NULL;
|
|
Packit |
db064d |
char *new_cache_file = NULL;
|
|
Packit |
db064d |
struct guids guids;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
const struct ibdiag_opt opts[] = {
|
|
Packit |
db064d |
{"switchguid", 1, 1, "BEFOREGUID:AFTERGUID",
|
|
Packit |
db064d |
"Specify before and after switchguid to edit"},
|
|
Packit |
db064d |
{"caguid", 2, 1, "BEFOREGUID:AFTERGUID",
|
|
Packit |
db064d |
"Specify before and after caguid to edit"},
|
|
Packit |
db064d |
{"sysimgguid", 3, 1, "BEFOREGUID:AFTERGUID",
|
|
Packit |
db064d |
"Specify before and after sysimgguid to edit"},
|
|
Packit |
db064d |
{"portguid", 4, 1, "NODEGUID:BEFOREGUID:AFTERGUID",
|
|
Packit |
db064d |
"Specify before and after port guid to edit"},
|
|
Packit |
db064d |
{}
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
const char *usage_args = "<orig.cache> <new.cache>";
|
|
Packit |
db064d |
|
|
Packit |
db064d |
ibdiag_process_opts(argc, argv, NULL, "CDdeGKLPstvy",
|
|
Packit |
db064d |
opts, process_opt, usage_args,
|
|
Packit |
db064d |
NULL);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
argc -= optind;
|
|
Packit |
db064d |
argv += optind;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
orig_cache_file = argv[0];
|
|
Packit |
db064d |
new_cache_file = argv[1];
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!orig_cache_file)
|
|
Packit |
db064d |
IBEXIT("original cache file not specified");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!new_cache_file)
|
|
Packit |
db064d |
IBEXIT("new cache file not specified");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if ((fabric = ibnd_load_fabric(orig_cache_file, 0)) == NULL)
|
|
Packit |
db064d |
IBEXIT("loading original cached fabric failed");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (switchguid_flag) {
|
|
Packit |
db064d |
guids.before = switchguid_before;
|
|
Packit |
db064d |
guids.after = switchguid_after;
|
|
Packit |
db064d |
guids.found = 0;
|
|
Packit |
db064d |
ibnd_iter_nodes_type(fabric,
|
|
Packit |
db064d |
replace_node_guid,
|
|
Packit |
db064d |
IB_NODE_SWITCH,
|
|
Packit |
db064d |
&guids);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!guids.found)
|
|
Packit |
db064d |
IBEXIT("switchguid = %" PRIx64 " not found",
|
|
Packit |
db064d |
switchguid_before);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (caguid_flag) {
|
|
Packit |
db064d |
guids.before = caguid_before;
|
|
Packit |
db064d |
guids.after = caguid_after;
|
|
Packit |
db064d |
guids.found = 0;
|
|
Packit |
db064d |
ibnd_iter_nodes_type(fabric,
|
|
Packit |
db064d |
replace_node_guid,
|
|
Packit |
db064d |
IB_NODE_CA,
|
|
Packit |
db064d |
&guids);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!guids.found)
|
|
Packit |
db064d |
IBEXIT("caguid = %" PRIx64 " not found",
|
|
Packit |
db064d |
caguid_before);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (sysimgguid_flag) {
|
|
Packit |
db064d |
guids.before = sysimgguid_before;
|
|
Packit |
db064d |
guids.after = sysimgguid_after;
|
|
Packit |
db064d |
guids.found = 0;
|
|
Packit |
db064d |
ibnd_iter_nodes(fabric,
|
|
Packit |
db064d |
replace_sysimgguid,
|
|
Packit |
db064d |
&guids);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!guids.found)
|
|
Packit |
db064d |
IBEXIT("sysimgguid = %" PRIx64 " not found",
|
|
Packit |
db064d |
sysimgguid_before);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (portguid_flag) {
|
|
Packit |
db064d |
guids.searchguid = portguid_nodeguid;
|
|
Packit |
db064d |
guids.searchguid_found = 0;
|
|
Packit |
db064d |
guids.before = portguid_before;
|
|
Packit |
db064d |
guids.after = portguid_after;
|
|
Packit |
db064d |
guids.found = 0;
|
|
Packit |
db064d |
ibnd_iter_nodes(fabric,
|
|
Packit |
db064d |
replace_portguid,
|
|
Packit |
db064d |
&guids);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!guids.searchguid_found)
|
|
Packit |
db064d |
IBEXIT("nodeguid = %" PRIx64 " not found",
|
|
Packit |
db064d |
portguid_nodeguid);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!guids.found)
|
|
Packit |
db064d |
IBEXIT("portguid = %" PRIx64 " not found",
|
|
Packit |
db064d |
portguid_before);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (ibnd_cache_fabric(fabric, new_cache_file, 0) < 0)
|
|
Packit |
db064d |
IBEXIT("caching new cache data failed");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
ibnd_destroy_fabric(fabric);
|
|
Packit |
db064d |
exit(0);
|
|
Packit |
db064d |
}
|