From patchwork Mon Apr 19 18:43:34 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Chu X-Patchwork-Id: 93548 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o3JIhHKx029158 for ; Mon, 19 Apr 2010 18:43:36 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751526Ab0DSSnf (ORCPT ); Mon, 19 Apr 2010 14:43:35 -0400 Received: from nspiron-2.llnl.gov ([128.115.41.82]:49442 "EHLO nspiron-2.llnl.gov" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751209Ab0DSSne (ORCPT ); Mon, 19 Apr 2010 14:43:34 -0400 X-Attachments: 0003-add-ibcacheedit-tool.patch Received: from auk31.llnl.gov (HELO [134.9.93.159]) ([134.9.93.159]) by nspiron-2.llnl.gov with ESMTP; 19 Apr 2010 11:43:34 -0700 Subject: [infiniband-diags] [3/3] add ibcacheedit tool From: Al Chu To: Sasha Khapyorsky Cc: "linux-rdma@vger.kernel.org" Date: Mon, 19 Apr 2010 11:43:34 -0700 Message-Id: <1271702614.17987.215.camel@auk31.llnl.gov> Mime-Version: 1.0 X-Mailer: Evolution 2.12.3 (2.12.3-19.el5) Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 19 Apr 2010 18:43:37 +0000 (UTC) diff --git a/infiniband-diags/Makefile.am b/infiniband-diags/Makefile.am index 1cdb60e..af90b05 100644 --- a/infiniband-diags/Makefile.am +++ b/infiniband-diags/Makefile.am @@ -13,7 +13,7 @@ sbin_PROGRAMS = src/ibaddr src/ibnetdiscover src/ibping src/ibportstate \ src/ibroute src/ibstat src/ibsysstat src/ibtracert \ src/perfquery src/sminfo src/smpdump src/smpquery \ src/saquery src/vendstat src/iblinkinfo \ - src/ibqueryerrors + src/ibqueryerrors src/ibcacheedit if ENABLE_TEST_UTILS sbin_PROGRAMS += src/ibsendtrap src/mcm_rereg_test @@ -62,6 +62,8 @@ src_iblinkinfo_SOURCES = src/iblinkinfo.c src_iblinkinfo_LDFLAGS = -L$(top_builddir)/libibnetdisc -libnetdisc src_ibqueryerrors_SOURCES = src/ibqueryerrors.c src_ibqueryerrors_LDFLAGS = -L$(top_builddir)/libibnetdisc -libnetdisc +src_ibcacheedit_SOURCES = src/ibcacheedit.c +src_ibcacheedit_LDFLAGS = -L$(top_builddir)/libibnetdisc -libnetdisc man_MANS = man/ibaddr.8 man/ibcheckerrors.8 man/ibcheckerrs.8 \ man/ibchecknet.8 man/ibchecknode.8 man/ibcheckport.8 \ @@ -76,7 +78,7 @@ man_MANS = man/ibaddr.8 man/ibcheckerrors.8 man/ibcheckerrs.8 \ man/ibprintswitch.8 man/ibprintca.8 man/ibfindnodesusing.8 \ man/ibdatacounts.8 man/ibdatacounters.8 \ man/ibrouters.8 man/ibprintrt.8 man/ibidsverify.8 \ - man/check_lft_balance.8 + man/check_lft_balance.8 man/ibcacheedit.8 BUILT_SOURCES = ibdiag_version ibdiag_version: diff --git a/infiniband-diags/man/ibcacheedit.8 b/infiniband-diags/man/ibcacheedit.8 new file mode 100644 index 0000000..b977827 --- /dev/null +++ b/infiniband-diags/man/ibcacheedit.8 @@ -0,0 +1,57 @@ +.TH IBCACHEEDIT 8 "Apr 15, 2010" "OpenIB" "OpenIB Diagnostics" + +.SH NAME +ibcacheedit \- edit an ibnetdiscover cache + +.SH SYNOPSIS +.B ibcacheedit +[\-\-switchguid BEFOREGUID:AFTERGUID] [\-\-caguid BEFORE:AFTER] +[\-\-sysimgguid BEFOREGUID:AFTERGUID] [\-\-portguid NODEGUID:BEFOREGUID:AFTERGUID] +[\-h(elp)] + +.SH DESCRIPTION +.PP +ibcacheedit allows users to edit an ibnetdiscover cache created through the +\fB\-\-cache\fR option in +.B ibnetdiscover(8). + +.SH OPTIONS + +.PP +.TP +\fB\-\-switchguid\fR BEFOREGUID:AFTERGUID +Specify a switchguid that should be changed. The before and after guid +should be separated by a colon. On switches, port guids are identical +to the switch guid, so port guids will be adjusted as well on switches. +.TP +\fB\-\-caguid\fR BEFOREGUID:AFTERGUID +Specify a caguid that should be changed. The before and after guid +should be separated by a colon. +.TP +\fB\-\-sysimgguid\fR BEFOREGUID:AFTERGUID +Specify a sysimgguid that should be changed. The before and after guid +should be spearated by a colon. +.TP +\fB\-\-portguid\fR NODEGUID:BEFOREGUID:AFTERGUID +Specify a portguid that should be changed. The nodeguid of the port +(e.g. switchguid or caguid) should be specified first, followed by a +colon, the before port guid, another colon, then the after port guid. +On switches, port guids are identical to the switch guid, so the +switch guid will be adjusted as well on switches. + +.SH COMMON OPTIONS + +Most OpenIB diagnostics take the following common flags. The exact list of +supported flags per utility can be found in the usage message and can be shown +using the util_name -h syntax. + +# Debugging flags +.PP +\-h show the usage message +.PP +\-V show the version info. + +.SH AUTHORS +.TP +Albert Chu +.RI < chu11@llnl.gov > diff --git a/infiniband-diags/src/ibcacheedit.c b/infiniband-diags/src/ibcacheedit.c new file mode 100644 index 0000000..28b8b21 --- /dev/null +++ b/infiniband-diags/src/ibcacheedit.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2010 Lawrence Livermore National Lab. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#if HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include +#include + +#include "ibdiag_common.h" + +uint64_t switchguid_before = 0; +uint64_t switchguid_after = 0; +int switchguid_flag = 0; + +uint64_t caguid_before = 0; +uint64_t caguid_after = 0; +int caguid_flag = 0; + +uint64_t sysimgguid_before = 0; +uint64_t sysimgguid_after = 0; +int sysimgguid_flag = 0; + +uint64_t portguid_nodeguid = 0; +uint64_t portguid_before = 0; +uint64_t portguid_after = 0; +int portguid_flag = 0; + +struct guids { + uint64_t searchguid; + int searchguid_found; + uint64_t before; + uint64_t after; + int found; +}; + +static int parse_beforeafter(char *arg, uint64_t *before, uint64_t *after) +{ + char *ptr; + char *before_str; + char *after_str; + + ptr = strchr(optarg, ':'); + if (!ptr || !(*(ptr + 1))) { + fprintf(stderr, "invalid input '%s'\n", arg); + return -1; + } + (*ptr) = '\0'; + before_str = arg; + after_str = ptr + 1; + + (*before) = strtoull(before_str, 0, 0); + (*after) = strtoull(after_str, 0, 0); + return 0; +} + +static int parse_guidbeforeafter(char *arg, + uint64_t *guid, + uint64_t *before, + uint64_t *after) +{ + char *ptr1; + char *ptr2; + char *guid_str; + char *before_str; + char *after_str; + + ptr1 = strchr(optarg, ':'); + if (!ptr1 || !(*(ptr1 + 1))) { + fprintf(stderr, "invalid input '%s'\n", arg); + return -1; + } + guid_str = arg; + before_str = ptr1 + 1; + + ptr2 = strchr(before_str, ':'); + if (!ptr2 || !(*(ptr2 + 1))) { + fprintf(stderr, "invalid input '%s'\n", arg); + return -1; + } + (*ptr1) = '\0'; + (*ptr2) = '\0'; + after_str = ptr2 + 1; + + (*guid) = strtoull(guid_str, 0, 0); + (*before) = strtoull(before_str, 0, 0); + (*after) = strtoull(after_str, 0, 0); + return 0; +} + +static int process_opt(void *context, int ch, char *optarg) +{ + switch (ch) { + case 1: + if (parse_beforeafter(optarg, + &switchguid_before, + &switchguid_after) < 0) + return -1; + switchguid_flag++; + break; + case 2: + if (parse_beforeafter(optarg, + &caguid_before, + &caguid_after) < 0) + return -1; + caguid_flag++; + break; + case 3: + if (parse_beforeafter(optarg, + &sysimgguid_before, + &sysimgguid_after) < 0) + return -1; + sysimgguid_flag++; + break; + case 4: + if (parse_guidbeforeafter(optarg, + &portguid_nodeguid, + &portguid_before, + &portguid_after) < 0) + return -1; + portguid_flag++; + break; + default: + return -1; + } + + return 0; +} + +static void update_switchportguids(ibnd_node_t *node, uint64_t guid) +{ + ibnd_port_t *port; + int p; + + for (p = 0; p <= node->numports; p++) { + port = node->ports[p]; + if (port) + port->guid = node->guid; + } +} + +static void replace_node_guid(ibnd_node_t *node, void *user_data) +{ + struct guids *guids; + + guids = (struct guids *)user_data; + + if (node->guid == guids->before) { + + node->guid = guids->after; + + /* port guids are identical to switch guids on + * switches, so update port guids too + */ + if (node->type == IB_NODE_SWITCH) + update_switchportguids(node, guids->after); + + guids->found++; + } +} + +static void replace_sysimgguid(ibnd_node_t *node, void *user_data) +{ + struct guids *guids; + uint64_t sysimgguid; + + guids = (struct guids *)user_data; + + sysimgguid = mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F); + if (sysimgguid == guids->before) { + mad_set_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F, + guids->after); + guids->found++; + } +} + +static void replace_portguid(ibnd_node_t *node, void *user_data) +{ + struct guids *guids; + + guids = (struct guids *)user_data; + + if (node->guid != guids->searchguid) + return; + + guids->searchguid_found++; + + if (node->type == IB_NODE_SWITCH) { + /* port guids are identical to switch guids on + * switches, so update switch guid too + */ + if (node->guid == guids->before) { + node->guid = guids->after; + update_switchportguids(node, guids->after); + guids->found++; + } + } + else { + ibnd_port_t *port; + int p; + + for (p = 1; p <= node->numports; p++) { + port = node->ports[p]; + if (port + && port->guid == guids->before) { + port->guid = guids->after; + guids->found++; + break; + } + } + } +} + +int main(int argc, char **argv) +{ + ibnd_fabric_t *fabric = NULL; + char *orig_cache_file = NULL; + char *new_cache_file = NULL; + struct guids guids; + + const struct ibdiag_opt opts[] = { + {"switchguid", 1, 1, "BEFOREGUID:AFTERGUID", + "Specify before and after switchguid to edit"}, + {"caguid", 2, 1, "BEFOREGUID:AFTERGUID", + "Specify before and after caguid to edit"}, + {"sysimgguid", 3, 1, "BEFOREGUID:AFTERGUID", + "Specify before and after sysimgguid to edit"}, + {"portguid", 4, 1, "NODEGUID:BEFOREGUID:AFTERGUID", + "Specify before and after port guid to edit"}, + {0} + }; + char *usage_args = " "; + + ibdiag_process_opts(argc, argv, NULL, "edCPDLGtsv", + opts, process_opt, usage_args, + NULL); + + argc -= optind; + argv += optind; + + orig_cache_file = argv[0]; + new_cache_file = argv[1]; + + if (!orig_cache_file) + IBERROR("original cache file not specified"); + + if (!new_cache_file) + IBERROR("new cache file not specified"); + + if ((fabric = ibnd_load_fabric(orig_cache_file, 0)) == NULL) + IBERROR("loading original cached fabric failed"); + + if (switchguid_flag) { + guids.before = switchguid_before; + guids.after = switchguid_after; + guids.found = 0; + ibnd_iter_nodes_type(fabric, + replace_node_guid, + IB_NODE_SWITCH, + &guids); + + if (!guids.found) + IBERROR("switchguid = %" PRIx64 " not found", + switchguid_before); + } + + if (caguid_flag) { + guids.before = caguid_before; + guids.after = caguid_after; + guids.found = 0; + ibnd_iter_nodes_type(fabric, + replace_node_guid, + IB_NODE_CA, + &guids); + + if (!guids.found) + IBERROR("caguid = %" PRIx64 " not found", + caguid_before); + } + + if (sysimgguid_flag) { + guids.before = sysimgguid_before; + guids.after = sysimgguid_after; + guids.found = 0; + ibnd_iter_nodes(fabric, + replace_sysimgguid, + &guids); + + if (!guids.found) + IBERROR("sysimgguid = %" PRIx64 " not found", + sysimgguid_before); + } + + if (portguid_flag) { + guids.searchguid = portguid_nodeguid; + guids.searchguid_found = 0; + guids.before = portguid_before; + guids.after = portguid_after; + guids.found = 0; + ibnd_iter_nodes(fabric, + replace_portguid, + &guids); + + if (!guids.searchguid_found) + IBERROR("nodeguid = %" PRIx64 " not found", + portguid_nodeguid); + + if (!guids.found) + IBERROR("portguid = %" PRIx64 " not found", + portguid_before); + } + + if (ibnd_cache_fabric(fabric, new_cache_file, 0) < 0) + IBERROR("caching new cache data failed"); + + ibnd_destroy_fabric(fabric); + exit(0); +}