From patchwork Wed Jul 20 23:16:55 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ira Weiny X-Patchwork-Id: 993372 X-Patchwork-Delegate: ira.weiny@intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p6KNGtjp024149 for ; Wed, 20 Jul 2011 23:17:18 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752118Ab1GTXQ4 (ORCPT ); Wed, 20 Jul 2011 19:16:56 -0400 Received: from nspiron-2.llnl.gov ([128.115.41.82]:51195 "EHLO nspiron-2.llnl.gov" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751934Ab1GTXQz (ORCPT ); Wed, 20 Jul 2011 19:16:55 -0400 X-Attachments: None Received: from eris.llnl.gov (HELO trebuchet) ([134.9.2.84]) by nspiron-2.llnl.gov with SMTP; 20 Jul 2011 16:16:55 -0700 Date: Wed, 20 Jul 2011 16:16:55 -0700 From: Ira Weiny To: "linux-rdma@vger.kernel.org" Cc: Jason Gunthorpe , Hal Rosenstock Subject: [PATCH 2/3] infiniband-diags: libibnetdisc Allow a DR Path partial fabric query starting at a CA Message-Id: <20110720161655.1ed38052.weiny2@llnl.gov> X-Mailer: Sylpheed 3.1.1 (GTK+ 2.18.9; x86_64-unknown-linux-gnu) Mime-Version: 1.0 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.6 (demeter1.kernel.org [140.211.167.41]); Wed, 20 Jul 2011 23:17:18 +0000 (UTC) The old algorithm would attempt to extend a DR path through the CA and fail. The new algorithm retracts the path properly. This does not work when combined routing is used with the CA as a starting point. :-( Signed-off-by: Ira Weiny --- libibnetdisc/src/ibnetdisc.c | 83 ++++++++++++++++++++++++++++++++---------- libibnetdisc/src/internal.h | 1 + 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/libibnetdisc/src/ibnetdisc.c b/libibnetdisc/src/ibnetdisc.c index b7fa75a..07f2a3f 100644 --- a/libibnetdisc/src/ibnetdisc.c +++ b/libibnetdisc/src/ibnetdisc.c @@ -56,8 +56,13 @@ #include "chassis.h" /* forward declare */ +struct ni_cbdata +{ + ibnd_node_t *node; + int port_num; +}; static int query_node_info(smp_engine_t * engine, ib_portid_t * portid, - ibnd_node_t * node); + struct ni_cbdata * cbdata); static int recv_switch_info(smp_engine_t * engine, ibnd_smp_t * smp, uint8_t * mad, void *cb_data) @@ -87,6 +92,26 @@ static int add_port_to_dpath(ib_dr_path_t * path, int nextport) return path->cnt; } +static int retract_dpath(smp_engine_t * engine, ib_portid_t * portid) +{ + ibnd_scan_t *scan = engine->user_data; + ibnd_fabric_t *fabric = scan->fabric; + + if (scan->cfg->max_hops && + fabric->maxhops_discovered > scan->cfg->max_hops) + return 0; + + /* this may seem wrong but the only time we would retract the path is + * if the user specified a CA for the DR path and we are retracting + * from that to find the node it is connected to. This counts as a + * positive hop discovered + */ + fabric->maxhops_discovered++; + portid->drpath.p[portid->drpath.cnt] = 0; + portid->drpath.cnt--; + return 1; +} + static int extend_dpath(smp_engine_t * engine, ib_portid_t * portid, int nextport) { @@ -115,8 +140,9 @@ static int extend_dpath(smp_engine_t * engine, ib_portid_t * portid, return -1; } - if ((unsigned) portid->drpath.cnt > fabric->maxhops_discovered) - fabric->maxhops_discovered = portid->drpath.cnt; + if (((unsigned) portid->drpath.cnt - scan->initial_hops) > + fabric->maxhops_discovered) + fabric->maxhops_discovered++; return 1; } @@ -202,9 +228,26 @@ static int recv_port_info(smp_engine_t * engine, ibnd_smp_t * smp, == IB_PORT_PHYS_STATE_LINKUP && ((node->type == IB_NODE_SWITCH && port_num != local_port) || (node == fabric->from_node && port_num == fabric->from_portnum))) { + + int rc = 0; ib_portid_t path = smp->path; - if (extend_dpath(engine, &path, port_num) > 0) - query_node_info(engine, &path, node); + + if (node->type != IB_NODE_SWITCH && + node == fabric->from_node && + path.drpath.cnt > 1) + rc = retract_dpath(engine, &path); + else { + /* we can't proceed through an HCA with DR */ + if (path.lid == 0 || node->type == IB_NODE_SWITCH) + rc = extend_dpath(engine, &path, port_num); + } + + if (rc > 0) { + struct ni_cbdata * cbdata = malloc(sizeof(*cbdata)); + cbdata->node = node; + cbdata->port_num = port_num; + query_node_info(engine, &path, cbdata); + } } return 0; @@ -255,11 +298,6 @@ static ibnd_node_t *create_node(smp_engine_t * engine, ib_portid_t * path, return rc; } -static int get_last_port(ib_portid_t * path) -{ - return path->drpath.p[path->drpath.cnt]; -} - static void link_ports(ibnd_node_t * node, ibnd_port_t * port, ibnd_node_t * remotenode, ibnd_port_t * remoteport) { @@ -294,7 +332,9 @@ static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp, ibnd_fabric_t *fabric = scan->fabric; int i = 0; uint8_t *node_info = mad + IB_SMP_DATA_OFFS; - ibnd_node_t *rem_node = cb_data; + struct ni_cbdata *ni_cbdata = (struct ni_cbdata *)cb_data; + ibnd_node_t *rem_node = NULL; + int rem_port_num = 0; ibnd_node_t *node; int node_is_new = 0; uint64_t node_guid = mad_get_field64(node_info, 0, IB_NODE_GUID_F); @@ -302,6 +342,12 @@ static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp, int port_num = mad_get_field(node_info, 0, IB_NODE_LOCAL_PORT_F); ibnd_port_t *port = NULL; + if (ni_cbdata) { + rem_node = ni_cbdata->node; + rem_port_num = ni_cbdata->port_num; + free(ni_cbdata); + } + node = ibnd_find_node_guid(fabric, node_guid); if (!node) { node = create_node(engine, &smp->path, node_info); @@ -333,8 +379,6 @@ static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp, fabric->from_portnum = port_num; } else { /* link ports... */ - int rem_port_num = get_last_port(&smp->path); - if (!rem_node->ports[rem_port_num]) { IBND_ERROR("Internal Error; " "Node(%p) 0x%" PRIx64 @@ -363,11 +407,11 @@ static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp, } static int query_node_info(smp_engine_t * engine, ib_portid_t * portid, - ibnd_node_t * node) + struct ni_cbdata * cbdata) { IBND_DEBUG("Query Node Info; %s\n", portid2str(portid)); return issue_smp(engine, portid, IB_ATTR_NODE_INFO, 0, - recv_node_info, node); + recv_node_info, (void *)cbdata); } ibnd_node_t *ibnd_find_node_guid(ibnd_fabric_t * fabric, uint64_t guid) @@ -430,8 +474,7 @@ void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric) } } -static int set_config(struct ibnd_config *config, struct ibnd_config *cfg, - int initial_hops) +static int set_config(struct ibnd_config *config, struct ibnd_config *cfg) { if (!config) return (-EINVAL); @@ -445,8 +488,6 @@ static int set_config(struct ibnd_config *config, struct ibnd_config *cfg, config->timeout_ms = DEFAULT_TIMEOUT; if (!config->retries) config->retries = DEFAULT_RETRIES; - if (config->max_hops) - config->max_hops += initial_hops; return (0); } @@ -467,7 +508,7 @@ ibnd_fabric_t *ibnd_discover_fabric(char * ca_name, int ca_port, if (!from) from = &my_portid; - if (set_config(&config, cfg, from->drpath.cnt)) { + if (set_config(&config, cfg)) { IBND_ERROR("Invalid ibnd_config\n"); return NULL; } @@ -483,6 +524,7 @@ ibnd_fabric_t *ibnd_discover_fabric(char * ca_name, int ca_port, memset(&scan.selfportid, 0, sizeof(scan.selfportid)); scan.fabric = fabric; scan.cfg = &config; + scan.initial_hops = from->drpath.cnt; if (smp_engine_init(&engine, ca_name, ca_port, &scan, &config)) { free(fabric); @@ -505,6 +547,7 @@ ibnd_fabric_t *ibnd_discover_fabric(char * ca_name, int ca_port, goto error; fabric->total_mads_used = engine.total_smps; + fabric->maxhops_discovered += scan.initial_hops; if (group_nodes(fabric)) goto error; diff --git a/libibnetdisc/src/internal.h b/libibnetdisc/src/internal.h index 3c599ec..80918c4 100644 --- a/libibnetdisc/src/internal.h +++ b/libibnetdisc/src/internal.h @@ -62,6 +62,7 @@ typedef struct ibnd_scan { ibnd_fabric_t *fabric; struct ibnd_config *cfg; struct ibmad_port *ibmad_port; + unsigned initial_hops; } ibnd_scan_t; typedef struct ibnd_smp ibnd_smp_t;