Blame src/ibcacheedit.c

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
}