|
Packit |
db064d |
/*
|
|
Packit |
db064d |
* Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
|
|
Packit |
db064d |
* Copyright (c) 2009 HNR Consulting. All rights reserved.
|
|
Packit |
db064d |
* Copyright (c) 2010,2011 Mellanox Technologies LTD. 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 <unistd.h>
|
|
Packit |
db064d |
#include <ctype.h>
|
|
Packit |
db064d |
#include <netinet/in.h>
|
|
Packit |
db064d |
#include <inttypes.h>
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#include <infiniband/umad.h>
|
|
Packit |
db064d |
#include <infiniband/mad.h>
|
|
Packit |
db064d |
#include <complib/cl_nodenamemap.h>
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#include "ibdiag_common.h"
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static struct ibmad_port *srcport;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#define MAXHOPS 63
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static const char * const node_type_str[] = {
|
|
Packit |
db064d |
"???",
|
|
Packit |
db064d |
"ca",
|
|
Packit |
db064d |
"switch",
|
|
Packit |
db064d |
"router",
|
|
Packit |
db064d |
"iwarp rnic"
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int timeout = 0; /* ms */
|
|
Packit |
db064d |
static int force;
|
|
Packit |
db064d |
static FILE *f;
|
|
Packit |
db064d |
static FILE *ports_fd;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static char *node_name_map_file = NULL;
|
|
Packit |
db064d |
static char *ports_file = NULL;
|
|
Packit |
db064d |
static nn_map_t *node_name_map = NULL;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
typedef struct Port Port;
|
|
Packit |
db064d |
typedef struct Switch Switch;
|
|
Packit |
db064d |
typedef struct Node Node;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
struct Port {
|
|
Packit |
db064d |
Port *next;
|
|
Packit |
db064d |
Port *remoteport;
|
|
Packit |
db064d |
uint64_t portguid;
|
|
Packit |
db064d |
int portnum;
|
|
Packit |
db064d |
int lid;
|
|
Packit |
db064d |
int lmc;
|
|
Packit |
db064d |
int state;
|
|
Packit |
db064d |
int physstate;
|
|
Packit |
db064d |
char portinfo[64];
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
|
|
Packit |
db064d |
struct Switch {
|
|
Packit |
db064d |
int linearcap;
|
|
Packit |
db064d |
int mccap;
|
|
Packit |
db064d |
int linearFDBtop;
|
|
Packit |
db064d |
int fdb_base;
|
|
Packit |
db064d |
int enhsp0;
|
|
Packit |
db064d |
int8_t fdb[64];
|
|
Packit |
db064d |
char switchinfo[64];
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
|
|
Packit |
db064d |
struct Node {
|
|
Packit |
db064d |
Node *htnext;
|
|
Packit |
db064d |
Node *dnext;
|
|
Packit |
db064d |
Port *ports;
|
|
Packit |
db064d |
ib_portid_t path;
|
|
Packit |
db064d |
int type;
|
|
Packit |
db064d |
int dist;
|
|
Packit |
db064d |
int numports;
|
|
Packit |
db064d |
int upport;
|
|
Packit |
db064d |
Node *upnode;
|
|
Packit |
db064d |
uint64_t nodeguid; /* also portguid */
|
|
Packit |
db064d |
char nodedesc[64];
|
|
Packit |
db064d |
char nodeinfo[64];
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static Node *nodesdist[MAXHOPS];
|
|
Packit |
db064d |
static uint64_t target_portguid;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
/*
|
|
Packit |
db064d |
* is_port_inactive
|
|
Packit |
db064d |
* Checks whether or not the port state is other than active.
|
|
Packit |
db064d |
* The "sw" argument is only relevant when the port is on a
|
|
Packit |
db064d |
* switch; for HCAs and routers, this argument is ignored.
|
|
Packit |
db064d |
* Returns 1 when port is not active and 0 when active.
|
|
Packit |
db064d |
* Base switch port 0 is considered always active.
|
|
Packit |
db064d |
*/
|
|
Packit |
db064d |
static int is_port_inactive(Node * node, Port * port, Switch * sw)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
int res = 0;
|
|
Packit |
db064d |
if (port->state != 4 &&
|
|
Packit |
db064d |
(node->type != IB_NODE_SWITCH ||
|
|
Packit |
db064d |
(node->type == IB_NODE_SWITCH && sw->enhsp0)))
|
|
Packit |
db064d |
res = 1;
|
|
Packit |
db064d |
return res;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int get_node(Node * node, Port * port, ib_portid_t * portid)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
void *pi = port->portinfo, *ni = node->nodeinfo, *nd = node->nodedesc;
|
|
Packit |
db064d |
char *s, *e;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(ni, 0, sizeof(node->nodeinfo));
|
|
Packit |
db064d |
if (!smp_query_via(ni, portid, IB_ATTR_NODE_INFO, 0, timeout, srcport))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(nd, 0, sizeof(node->nodedesc));
|
|
Packit |
db064d |
if (!smp_query_via(nd, portid, IB_ATTR_NODE_DESC, 0, timeout, srcport))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
for (s = nd, e = s + 64; s < e; s++) {
|
|
Packit |
db064d |
if (!*s)
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
if (!isprint(*s))
|
|
Packit |
db064d |
*s = ' ';
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(pi, 0, sizeof(port->portinfo));
|
|
Packit |
db064d |
if (!smp_query_via(pi, portid, IB_ATTR_PORT_INFO, 0, timeout, srcport))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad_decode_field(ni, IB_NODE_GUID_F, &node->nodeguid);
|
|
Packit |
db064d |
mad_decode_field(ni, IB_NODE_TYPE_F, &node->type);
|
|
Packit |
db064d |
mad_decode_field(ni, IB_NODE_NPORTS_F, &node->numports);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad_decode_field(ni, IB_NODE_PORT_GUID_F, &port->portguid);
|
|
Packit |
db064d |
mad_decode_field(ni, IB_NODE_LOCAL_PORT_F, &port->portnum);
|
|
Packit |
db064d |
mad_decode_field(pi, IB_PORT_LID_F, &port->lid);
|
|
Packit |
db064d |
mad_decode_field(pi, IB_PORT_LMC_F, &port->lmc);
|
|
Packit |
db064d |
mad_decode_field(pi, IB_PORT_STATE_F, &port->state);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("portid %s: got node %" PRIx64 " '%s'", portid2str(portid),
|
|
Packit |
db064d |
node->nodeguid, node->nodedesc);
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int switch_lookup(Switch * sw, ib_portid_t * portid, int lid)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
void *si = sw->switchinfo, *fdb = sw->fdb;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(si, 0, sizeof(sw->switchinfo));
|
|
Packit |
db064d |
if (!smp_query_via(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout,
|
|
Packit |
db064d |
srcport))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad_decode_field(si, IB_SW_LINEAR_FDB_CAP_F, &sw->linearcap);
|
|
Packit |
db064d |
mad_decode_field(si, IB_SW_LINEAR_FDB_TOP_F, &sw->linearFDBtop);
|
|
Packit |
db064d |
mad_decode_field(si, IB_SW_ENHANCED_PORT0_F, &sw->enhsp0);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (lid >= sw->linearcap && lid > sw->linearFDBtop)
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(fdb, 0, sizeof(sw->fdb));
|
|
Packit |
db064d |
if (!smp_query_via(fdb, portid, IB_ATTR_LINEARFORWTBL, lid / 64,
|
|
Packit |
db064d |
timeout, srcport))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("portid %s: forward lid %d to port %d",
|
|
Packit |
db064d |
portid2str(portid), lid, sw->fdb[lid % 64]);
|
|
Packit |
db064d |
return sw->fdb[lid % 64];
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int sameport(Port * a, Port * b)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
return a->portguid == b->portguid || (force && a->lid == b->lid);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int extend_dpath(ib_dr_path_t * path, int nextport)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
if (path->cnt + 2 >= sizeof(path->p))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
++path->cnt;
|
|
Packit |
db064d |
path->p[path->cnt] = (uint8_t) nextport;
|
|
Packit |
db064d |
return path->cnt;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static void dump_endnode(int dump, const char *prompt, Node *node, Port *port)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char *nodename = NULL;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!dump)
|
|
Packit |
db064d |
return;
|
|
Packit |
db064d |
if (dump == 1) {
|
|
Packit |
db064d |
fprintf(f, "%s {0x%016" PRIx64 "}[%d]\n",
|
|
Packit |
db064d |
prompt, node->nodeguid,
|
|
Packit |
db064d |
node->type == IB_NODE_SWITCH ? 0 : port->portnum);
|
|
Packit |
db064d |
return;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
nodename =
|
|
Packit |
db064d |
remap_node_name(node_name_map, node->nodeguid, node->nodedesc);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
fprintf(f, "%s %s {0x%016" PRIx64 "} portnum %d lid %u-%u \"%s\"\n",
|
|
Packit |
db064d |
prompt,
|
|
Packit |
db064d |
(node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"),
|
|
Packit |
db064d |
node->nodeguid,
|
|
Packit |
db064d |
node->type == IB_NODE_SWITCH ? 0 : port->portnum, port->lid,
|
|
Packit |
db064d |
port->lid + (1 << port->lmc) - 1, nodename);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
free(nodename);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static void dump_route(int dump, Node * node, int outport, Port * port)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char *nodename = NULL;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!dump && !ibverbose)
|
|
Packit |
db064d |
return;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
nodename =
|
|
Packit |
db064d |
remap_node_name(node_name_map, node->nodeguid, node->nodedesc);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (dump == 1)
|
|
Packit |
db064d |
fprintf(f, "[%d] -> {0x%016" PRIx64 "}[%d]\n",
|
|
Packit |
db064d |
outport, port->portguid, port->portnum);
|
|
Packit |
db064d |
else
|
|
Packit |
db064d |
fprintf(f, "[%d] -> %s port {0x%016" PRIx64
|
|
Packit |
db064d |
"}[%d] lid %u-%u \"%s\"\n", outport,
|
|
Packit |
db064d |
(node->type <=
|
|
Packit |
db064d |
IB_NODE_MAX ? node_type_str[node->type] : "???"),
|
|
Packit |
db064d |
port->portguid, port->portnum, port->lid,
|
|
Packit |
db064d |
port->lid + (1 << port->lmc) - 1, nodename);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
free(nodename);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int find_route(ib_portid_t * from, ib_portid_t * to, int dump)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
Node *node, fromnode, tonode, nextnode;
|
|
Packit |
db064d |
Port *port, fromport, toport, nextport;
|
|
Packit |
db064d |
Switch sw;
|
|
Packit |
db064d |
int maxhops = MAXHOPS;
|
|
Packit |
db064d |
int portnum, outport = 255, next_sw_outport = 255;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(&fromnode,0,sizeof(Node));
|
|
Packit |
db064d |
memset(&tonode,0,sizeof(Node));
|
|
Packit |
db064d |
memset(&nextnode,0,sizeof(Node));
|
|
Packit |
db064d |
memset(&fromport,0,sizeof(Port));
|
|
Packit |
db064d |
memset(&toport,0,sizeof(Port));
|
|
Packit |
db064d |
memset(&nextport,0,sizeof(Port));
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("from %s", portid2str(from));
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (get_node(&fromnode, &fromport, from) < 0 ||
|
|
Packit |
db064d |
get_node(&tonode, &toport, to) < 0) {
|
|
Packit |
db064d |
IBWARN("can't reach to/from ports");
|
|
Packit |
db064d |
if (!force)
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
if (to->lid > 0)
|
|
Packit |
db064d |
toport.lid = to->lid;
|
|
Packit |
db064d |
IBWARN("Force: look for lid %d", to->lid);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
node = &fromnode;
|
|
Packit |
db064d |
port = &fromport;
|
|
Packit |
db064d |
portnum = port->portnum;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
dump_endnode(dump, "From", node, port);
|
|
Packit |
db064d |
if (node->type == IB_NODE_SWITCH) {
|
|
Packit |
db064d |
next_sw_outport = switch_lookup(&sw, from, to->lid);
|
|
Packit |
db064d |
if (next_sw_outport < 0 || next_sw_outport > node->numports) {
|
|
Packit |
db064d |
/* needed to print the port in badtbl */
|
|
Packit |
db064d |
outport = next_sw_outport;
|
|
Packit |
db064d |
goto badtbl;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
while (maxhops--) {
|
|
Packit |
db064d |
if (is_port_inactive(node, port, &sw))
|
|
Packit |
db064d |
goto badport;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (sameport(port, &toport))
|
|
Packit |
db064d |
break; /* found */
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (node->type == IB_NODE_SWITCH) {
|
|
Packit |
db064d |
DEBUG("switch node");
|
|
Packit |
db064d |
outport = next_sw_outport;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (extend_dpath(&from->drpath, outport) < 0)
|
|
Packit |
db064d |
goto badpath;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (get_node(&nextnode, &nextport, from) < 0) {
|
|
Packit |
db064d |
IBWARN("can't reach port at %s",
|
|
Packit |
db064d |
portid2str(from));
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
if (outport == 0) {
|
|
Packit |
db064d |
if (!sameport(&nextport, &toport))
|
|
Packit |
db064d |
goto badtbl;
|
|
Packit |
db064d |
else
|
|
Packit |
db064d |
break; /* found SMA port */
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
} else if ((node->type == IB_NODE_CA) ||
|
|
Packit |
db064d |
(node->type == IB_NODE_ROUTER)) {
|
|
Packit |
db064d |
int ca_src = 0;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
outport = portnum;
|
|
Packit |
db064d |
DEBUG("ca or router node");
|
|
Packit |
db064d |
if (!sameport(port, &fromport)) {
|
|
Packit |
db064d |
IBWARN
|
|
Packit |
db064d |
("can't continue: reached CA or router port %"
|
|
Packit |
db064d |
PRIx64 ", lid %d", port->portguid,
|
|
Packit |
db064d |
port->lid);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
/* we are at CA or router "from" - go one hop back to (hopefully) a switch */
|
|
Packit |
db064d |
if (from->drpath.cnt > 0) {
|
|
Packit |
db064d |
DEBUG("ca or router node - return back 1 hop");
|
|
Packit |
db064d |
from->drpath.cnt--;
|
|
Packit |
db064d |
} else {
|
|
Packit |
db064d |
ca_src = 1;
|
|
Packit |
db064d |
if (portnum
|
|
Packit |
db064d |
&& extend_dpath(&from->drpath, portnum) < 0)
|
|
Packit |
db064d |
goto badpath;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
if (get_node(&nextnode, &nextport, from) < 0) {
|
|
Packit |
db064d |
IBWARN("can't reach port at %s",
|
|
Packit |
db064d |
portid2str(from));
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
/* fix port num to be seen from the CA or router side */
|
|
Packit |
db064d |
if (!ca_src)
|
|
Packit |
db064d |
nextport.portnum =
|
|
Packit |
db064d |
from->drpath.p[from->drpath.cnt + 1];
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
/* only if the next node is a switch, get switch info */
|
|
Packit |
db064d |
if (nextnode.type == IB_NODE_SWITCH) {
|
|
Packit |
db064d |
next_sw_outport = switch_lookup(&sw, from, to->lid);
|
|
Packit |
db064d |
if (next_sw_outport < 0 ||
|
|
Packit |
db064d |
next_sw_outport > nextnode.numports) {
|
|
Packit |
db064d |
/* needed to print the port in badtbl */
|
|
Packit |
db064d |
outport = next_sw_outport;
|
|
Packit |
db064d |
goto badtbl;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
port = &nextport;
|
|
Packit |
db064d |
if (is_port_inactive(&nextnode, port, &sw))
|
|
Packit |
db064d |
goto badoutport;
|
|
Packit |
db064d |
node = &nextnode;
|
|
Packit |
db064d |
portnum = port->portnum;
|
|
Packit |
db064d |
dump_route(dump, node, outport, port);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (maxhops <= 0) {
|
|
Packit |
db064d |
IBWARN("no route found after %d hops", MAXHOPS);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
dump_endnode(dump, "To", node, port);
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
badport:
|
|
Packit |
db064d |
IBWARN("Bad port state found: node \"%s\" port %d state %d",
|
|
Packit |
db064d |
clean_nodedesc(node->nodedesc), portnum, port->state);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
badoutport:
|
|
Packit |
db064d |
IBWARN("Bad out port state found: node \"%s\" outport %d state %d",
|
|
Packit |
db064d |
clean_nodedesc(node->nodedesc), outport, port->state);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
badtbl:
|
|
Packit |
db064d |
IBWARN
|
|
Packit |
db064d |
("Bad forwarding table entry found at: node \"%s\" lid entry %d is %d (top %d)",
|
|
Packit |
db064d |
clean_nodedesc(node->nodedesc), to->lid, outport, sw.linearFDBtop);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
badpath:
|
|
Packit |
db064d |
IBWARN("Direct path too long!");
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
/**************************
|
|
Packit |
db064d |
* MC span part
|
|
Packit |
db064d |
*/
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#define HASHGUID(guid) ((uint32_t)(((uint32_t)(guid) * 101) ^ ((uint32_t)((guid) >> 32) * 103)))
|
|
Packit |
db064d |
#define HTSZ 137
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int insert_node(Node * new)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
static Node *nodestbl[HTSZ];
|
|
Packit |
db064d |
int hash = HASHGUID(new->nodeguid) % HTSZ;
|
|
Packit |
db064d |
Node *node;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
for (node = nodestbl[hash]; node; node = node->htnext)
|
|
Packit |
db064d |
if (node->nodeguid == new->nodeguid) {
|
|
Packit |
db064d |
DEBUG("node %" PRIx64 " already exists", new->nodeguid);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
new->htnext = nodestbl[hash];
|
|
Packit |
db064d |
nodestbl[hash] = new;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int get_port(Port * port, int portnum, ib_portid_t * portid)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char portinfo[64] = { 0 };
|
|
Packit |
db064d |
void *pi = portinfo;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
port->portnum = portnum;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!smp_query_via(pi, portid, IB_ATTR_PORT_INFO, portnum, timeout,
|
|
Packit |
db064d |
srcport))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad_decode_field(pi, IB_PORT_LID_F, &port->lid);
|
|
Packit |
db064d |
mad_decode_field(pi, IB_PORT_LMC_F, &port->lmc);
|
|
Packit |
db064d |
mad_decode_field(pi, IB_PORT_STATE_F, &port->state);
|
|
Packit |
db064d |
mad_decode_field(pi, IB_PORT_PHYS_STATE_F, &port->physstate);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
VERBOSE("portid %s portnum %d: lid %d state %d physstate %d",
|
|
Packit |
db064d |
portid2str(portid), portnum, port->lid, port->state,
|
|
Packit |
db064d |
port->physstate);
|
|
Packit |
db064d |
return 1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static void link_port(Port * port, Node * node)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
port->next = node->ports;
|
|
Packit |
db064d |
node->ports = port;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int new_node(Node * node, Port * port, ib_portid_t * path, int dist)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
if (port->portguid == target_portguid) {
|
|
Packit |
db064d |
node->dist = -1; /* tag as target */
|
|
Packit |
db064d |
link_port(port, node);
|
|
Packit |
db064d |
dump_endnode(ibverbose, "found target", node, port);
|
|
Packit |
db064d |
return 1; /* found; */
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
/* BFS search start with my self */
|
|
Packit |
db064d |
if (insert_node(node) < 0)
|
|
Packit |
db064d |
return -1; /* known switch */
|
|
Packit |
db064d |
|
|
Packit |
db064d |
VERBOSE("insert dist %d node %p port %d lid %d", dist, node,
|
|
Packit |
db064d |
port->portnum, port->lid);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
link_port(port, node);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
node->dist = dist;
|
|
Packit |
db064d |
node->path = *path;
|
|
Packit |
db064d |
node->dnext = nodesdist[dist];
|
|
Packit |
db064d |
nodesdist[dist] = node;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int switch_mclookup(Node * node, ib_portid_t * portid, int mlid,
|
|
Packit |
db064d |
char *map)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
Switch sw;
|
|
Packit |
db064d |
char mdb[64];
|
|
Packit |
db064d |
void *si = sw.switchinfo;
|
|
Packit |
db064d |
__be16 *msets = (__be16 *) mdb;
|
|
Packit |
db064d |
int maxsets, block, i, set;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(map, 0, 256);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(si, 0, sizeof(sw.switchinfo));
|
|
Packit |
db064d |
if (!smp_query_via(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout,
|
|
Packit |
db064d |
srcport))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mlid -= 0xc000;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad_decode_field(si, IB_SW_MCAST_FDB_CAP_F, &sw.mccap);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (mlid >= sw.mccap)
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
block = mlid / 32;
|
|
Packit |
db064d |
maxsets = (node->numports + 15) / 16; /* round up */
|
|
Packit |
db064d |
|
|
Packit |
db064d |
for (set = 0; set < maxsets; set++) {
|
|
Packit |
db064d |
memset(mdb, 0, sizeof(mdb));
|
|
Packit |
db064d |
if (!smp_query_via(mdb, portid, IB_ATTR_MULTICASTFORWTBL,
|
|
Packit |
db064d |
block | (set << 28), timeout, srcport))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
for (i = 0; i < 16; i++, map++) {
|
|
Packit |
db064d |
uint16_t mask = ntohs(msets[mlid % 32]);
|
|
Packit |
db064d |
if (mask & (1 << i))
|
|
Packit |
db064d |
*map = 1;
|
|
Packit |
db064d |
else
|
|
Packit |
db064d |
continue;
|
|
Packit |
db064d |
VERBOSE("Switch guid 0x%" PRIx64
|
|
Packit |
db064d |
": mlid 0x%x is forwarded to port %d",
|
|
Packit |
db064d |
node->nodeguid, mlid + 0xc000, i + set * 16);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
/*
|
|
Packit |
db064d |
* Return 1 if found, 0 if not, -1 on errors.
|
|
Packit |
db064d |
*/
|
|
Packit |
db064d |
static Node *find_mcpath(ib_portid_t * from, int mlid)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
Node *node, *remotenode;
|
|
Packit |
db064d |
Port *port, *remoteport;
|
|
Packit |
db064d |
char map[256];
|
|
Packit |
db064d |
int r, i;
|
|
Packit |
db064d |
int dist = 0, leafport = 0;
|
|
Packit |
db064d |
ib_portid_t *path;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("from %s", portid2str(from));
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!(node = calloc(1, sizeof(Node))))
|
|
Packit |
db064d |
IBEXIT("out of memory");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!(port = calloc(1, sizeof(Port))))
|
|
Packit |
db064d |
IBEXIT("out of memory");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (get_node(node, port, from) < 0) {
|
|
Packit |
db064d |
IBWARN("can't reach node %s", portid2str(from));
|
|
Packit |
db064d |
return NULL;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
node->upnode = NULL; /* root */
|
|
Packit |
db064d |
if ((r = new_node(node, port, from, 0)) > 0) {
|
|
Packit |
db064d |
if (node->type != IB_NODE_SWITCH) {
|
|
Packit |
db064d |
IBWARN("ibtracert from CA to CA is unsupported");
|
|
Packit |
db064d |
return NULL; /* ibtracert from host to itself is unsupported */
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (switch_mclookup(node, from, mlid, map) < 0 || !map[0])
|
|
Packit |
db064d |
return NULL;
|
|
Packit |
db064d |
return node;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
for (dist = 0; dist < MAXHOPS; dist++) {
|
|
Packit |
db064d |
|
|
Packit |
db064d |
for (node = nodesdist[dist]; node; node = node->dnext) {
|
|
Packit |
db064d |
|
|
Packit |
db064d |
path = &node->path;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
VERBOSE("dist %d node %p", dist, node);
|
|
Packit |
db064d |
dump_endnode(ibverbose, "processing", node,
|
|
Packit |
db064d |
node->ports);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(map, 0, sizeof(map));
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (node->type != IB_NODE_SWITCH) {
|
|
Packit |
db064d |
if (dist)
|
|
Packit |
db064d |
continue;
|
|
Packit |
db064d |
leafport = path->drpath.p[path->drpath.cnt];
|
|
Packit |
db064d |
map[port->portnum] = 1;
|
|
Packit |
db064d |
node->upport = 0; /* starting here */
|
|
Packit |
db064d |
DEBUG("Starting from CA 0x%" PRIx64
|
|
Packit |
db064d |
" lid %d port %d (leafport %d)",
|
|
Packit |
db064d |
node->nodeguid, port->lid, port->portnum,
|
|
Packit |
db064d |
leafport);
|
|
Packit |
db064d |
} else { /* switch */
|
|
Packit |
db064d |
|
|
Packit |
db064d |
/* if starting from a leaf port fix up port (up port) */
|
|
Packit |
db064d |
if (dist == 1 && leafport)
|
|
Packit |
db064d |
node->upport = leafport;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (switch_mclookup(node, path, mlid, map) < 0) {
|
|
Packit |
db064d |
IBWARN("skipping bad Switch 0x%" PRIx64
|
|
Packit |
db064d |
"", node->nodeguid);
|
|
Packit |
db064d |
continue;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
for (i = 1; i <= node->numports; i++) {
|
|
Packit |
db064d |
if (!map[i] || i == node->upport)
|
|
Packit |
db064d |
continue;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (dist == 0 && leafport) {
|
|
Packit |
db064d |
if (from->drpath.cnt > 0)
|
|
Packit |
db064d |
path->drpath.cnt--;
|
|
Packit |
db064d |
} else {
|
|
Packit |
db064d |
if (!(port = calloc(1, sizeof(Port))))
|
|
Packit |
db064d |
IBEXIT("out of memory");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (get_port(port, i, path) < 0) {
|
|
Packit |
db064d |
IBWARN
|
|
Packit |
db064d |
("can't reach node %s port %d",
|
|
Packit |
db064d |
portid2str(path), i);
|
|
Packit |
db064d |
free(port);
|
|
Packit |
db064d |
return NULL;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (port->physstate != 5) { /* LinkUP */
|
|
Packit |
db064d |
free(port);
|
|
Packit |
db064d |
continue;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
#if 0
|
|
Packit |
db064d |
link_port(port, node);
|
|
Packit |
db064d |
#endif
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (extend_dpath(&path->drpath, i) < 0) {
|
|
Packit |
db064d |
free(port);
|
|
Packit |
db064d |
return NULL;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!(remotenode = calloc(1, sizeof(Node))))
|
|
Packit |
db064d |
IBEXIT("out of memory");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!(remoteport = calloc(1, sizeof(Port))))
|
|
Packit |
db064d |
IBEXIT("out of memory");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (get_node(remotenode, remoteport, path) < 0) {
|
|
Packit |
db064d |
IBWARN
|
|
Packit |
db064d |
("NodeInfo on %s port %d failed, skipping port",
|
|
Packit |
db064d |
portid2str(path), i);
|
|
Packit |
db064d |
path->drpath.cnt--; /* restore path */
|
|
Packit |
db064d |
free(remotenode);
|
|
Packit |
db064d |
free(remoteport);
|
|
Packit |
db064d |
continue;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
remotenode->upnode = node;
|
|
Packit |
db064d |
remotenode->upport = remoteport->portnum;
|
|
Packit |
db064d |
remoteport->remoteport = port;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if ((r = new_node(remotenode, remoteport, path,
|
|
Packit |
db064d |
dist + 1)) > 0)
|
|
Packit |
db064d |
return remotenode;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (r == 0)
|
|
Packit |
db064d |
dump_endnode(ibverbose, "new remote",
|
|
Packit |
db064d |
remotenode, remoteport);
|
|
Packit |
db064d |
else if (remotenode->type == IB_NODE_SWITCH)
|
|
Packit |
db064d |
dump_endnode(2,
|
|
Packit |
db064d |
"ERR: circle discovered at",
|
|
Packit |
db064d |
remotenode, remoteport);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
path->drpath.cnt--; /* restore path */
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return NULL; /* not found */
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static uint64_t find_target_portguid(ib_portid_t * to)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
Node tonode;
|
|
Packit |
db064d |
Port toport;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (get_node(&tonode, &toport, to) < 0) {
|
|
Packit |
db064d |
IBWARN("can't find to port\n");
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return toport.portguid;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static void dump_mcpath(Node * node, int dumplevel)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char *nodename = NULL;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (node->upnode)
|
|
Packit |
db064d |
dump_mcpath(node->upnode, dumplevel);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
nodename =
|
|
Packit |
db064d |
remap_node_name(node_name_map, node->nodeguid, node->nodedesc);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!node->dist) {
|
|
Packit |
db064d |
printf("From %s 0x%" PRIx64 " port %d lid %u-%u \"%s\"\n",
|
|
Packit |
db064d |
(node->type <=
|
|
Packit |
db064d |
IB_NODE_MAX ? node_type_str[node->type] : "???"),
|
|
Packit |
db064d |
node->nodeguid, node->ports->portnum, node->ports->lid,
|
|
Packit |
db064d |
node->ports->lid + (1 << node->ports->lmc) - 1,
|
|
Packit |
db064d |
nodename);
|
|
Packit |
db064d |
goto free_name;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (node->dist) {
|
|
Packit |
db064d |
if (dumplevel == 1)
|
|
Packit |
db064d |
printf("[%d] -> %s {0x%016" PRIx64 "}[%d]\n",
|
|
Packit |
db064d |
node->ports->remoteport->portnum,
|
|
Packit |
db064d |
(node->type <=
|
|
Packit |
db064d |
IB_NODE_MAX ? node_type_str[node->type] :
|
|
Packit |
db064d |
"???"), node->nodeguid, node->upport);
|
|
Packit |
db064d |
else
|
|
Packit |
db064d |
printf("[%d] -> %s 0x%" PRIx64 "[%d] lid %u \"%s\"\n",
|
|
Packit |
db064d |
node->ports->remoteport->portnum,
|
|
Packit |
db064d |
(node->type <=
|
|
Packit |
db064d |
IB_NODE_MAX ? node_type_str[node->type] :
|
|
Packit |
db064d |
"???"), node->nodeguid, node->upport,
|
|
Packit |
db064d |
node->ports->lid, nodename);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (node->dist < 0)
|
|
Packit |
db064d |
/* target node */
|
|
Packit |
db064d |
printf("To %s 0x%" PRIx64 " port %d lid %u-%u \"%s\"\n",
|
|
Packit |
db064d |
(node->type <=
|
|
Packit |
db064d |
IB_NODE_MAX ? node_type_str[node->type] : "???"),
|
|
Packit |
db064d |
node->nodeguid, node->ports->portnum, node->ports->lid,
|
|
Packit |
db064d |
node->ports->lid + (1 << node->ports->lmc) - 1,
|
|
Packit |
db064d |
nodename);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
free_name:
|
|
Packit |
db064d |
free(nodename);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int resolve_lid(ib_portid_t *portid)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
uint8_t portinfo[64] = { 0 };
|
|
Packit |
db064d |
uint16_t lid;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!smp_query_via(portinfo, portid, IB_ATTR_PORT_INFO, 0, 0, NULL))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
mad_decode_field(portinfo, IB_PORT_LID_F, &lid);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
ib_portid_set(portid, lid, 0, 0);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int dumplevel = 2, multicast, mlid;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int process_opt(void *context, int ch)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
switch (ch) {
|
|
Packit |
db064d |
case 1:
|
|
Packit |
db064d |
node_name_map_file = strdup(optarg);
|
|
Packit |
db064d |
if (node_name_map_file == NULL)
|
|
Packit |
db064d |
IBEXIT("out of memory, strdup for node_name_map_file name failed");
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case 2:
|
|
Packit |
db064d |
ports_file = strdup(optarg);
|
|
Packit |
db064d |
if (ports_file == NULL)
|
|
Packit |
db064d |
IBEXIT("out of memory, strdup for ports_file name failed");
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case 'm':
|
|
Packit |
db064d |
multicast++;
|
|
Packit |
db064d |
mlid = strtoul(optarg, NULL, 0);
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case 'f':
|
|
Packit |
db064d |
force++;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case 'n':
|
|
Packit |
db064d |
dumplevel = 1;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
default:
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int get_route(char *srcid, char *dstid) {
|
|
Packit |
db064d |
ib_portid_t my_portid = { 0 };
|
|
Packit |
db064d |
ib_portid_t src_portid = { 0 };
|
|
Packit |
db064d |
ib_portid_t dest_portid = { 0 };
|
|
Packit |
db064d |
Node *endnode;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (resolve_portid_str(ibd_ca, ibd_ca_port, &src_portid, srcid,
|
|
Packit |
db064d |
ibd_dest_type, ibd_sm_id, srcport) < 0) {
|
|
Packit |
db064d |
IBWARN("can't resolve source port %s", srcid);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (resolve_portid_str(ibd_ca, ibd_ca_port, &dest_portid, dstid,
|
|
Packit |
db064d |
ibd_dest_type, ibd_sm_id, srcport) < 0) {
|
|
Packit |
db064d |
IBWARN("can't resolve destination port %s", dstid);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (ibd_dest_type == IB_DEST_DRPATH) {
|
|
Packit |
db064d |
if (resolve_lid(&src_portid) < 0) {
|
|
Packit |
db064d |
IBWARN("cannot resolve lid for port \'%s\'",
|
|
Packit |
db064d |
portid2str(&src_portid));
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
if (resolve_lid(&dest_portid) < 0) {
|
|
Packit |
db064d |
IBWARN("cannot resolve lid for port \'%s\'",
|
|
Packit |
db064d |
portid2str(&dest_portid));
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (dest_portid.lid == 0 || src_portid.lid == 0) {
|
|
Packit |
db064d |
IBWARN("bad src/dest lid");
|
|
Packit |
db064d |
ibdiag_show_usage();
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (ibd_dest_type != IB_DEST_DRPATH) {
|
|
Packit |
db064d |
/* first find a direct path to the src port */
|
|
Packit |
db064d |
if (find_route(&my_portid, &src_portid, 0) < 0) {
|
|
Packit |
db064d |
IBWARN("can't find a route to the src port");
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
src_portid = my_portid;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!multicast) {
|
|
Packit |
db064d |
if (find_route(&src_portid, &dest_portid, dumplevel) < 0) {
|
|
Packit |
db064d |
IBWARN("can't find a route from src to dest");
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
} else {
|
|
Packit |
db064d |
if (mlid < 0xc000)
|
|
Packit |
db064d |
IBWARN("invalid MLID; must be 0xc000 or larger");
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!(target_portguid = find_target_portguid(&dest_portid))) {
|
|
Packit |
db064d |
IBWARN("can't reach target lid %d", dest_portid.lid);
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!(endnode = find_mcpath(&src_portid, mlid))) {
|
|
Packit |
db064d |
IBWARN("can't find a multicast route from src to dest");
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
/* dump multicast path */
|
|
Packit |
db064d |
dump_mcpath(endnode, dumplevel);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
int main(int argc, char **argv)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char dstbuf[20];
|
|
Packit |
db064d |
char srcbuf[20];
|
|
Packit |
db064d |
char portsbuf[80];
|
|
Packit |
db064d |
char *p_first;
|
|
Packit |
db064d |
int len, i;
|
|
Packit |
db064d |
int line_count = 0;
|
|
Packit |
db064d |
int num_port_pairs = 0;
|
|
Packit |
db064d |
int mgmt_classes[3] =
|
|
Packit |
db064d |
{ IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
|
|
Packit |
db064d |
|
|
Packit |
db064d |
const struct ibdiag_opt opts[] = {
|
|
Packit |
db064d |
{"force", 'f', 0, NULL, "force"},
|
|
Packit |
db064d |
{"no_info", 'n', 0, NULL, "simple format"},
|
|
Packit |
db064d |
{"mlid", 'm', 1, "<mlid>", "multicast trace of the mlid"},
|
|
Packit |
db064d |
{"node-name-map", 1, 1, "<file>", "node name map file"},
|
|
Packit |
db064d |
{"ports-file", 2, 1, "<file>", "port pairs file"},
|
|
Packit |
db064d |
{}
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
char usage_args[] = "<src-addr> <dest-addr>";
|
|
Packit |
db064d |
const char *usage_examples[] = {
|
|
Packit |
db064d |
"- Unicast examples:",
|
|
Packit |
db064d |
"4 16\t\t\t# show path between lids 4 and 16",
|
|
Packit |
db064d |
"-n 4 16\t\t# same, but using simple output format",
|
|
Packit |
db064d |
"-G 0x8f1040396522d 0x002c9000100d051\t# use guid addresses",
|
|
Packit |
db064d |
|
|
Packit |
db064d |
" - Multicast examples:",
|
|
Packit |
db064d |
"-m 0xc000 4 16\t# show multicast path of mlid 0xc000 between lids 4 and 16",
|
|
Packit |
db064d |
NULL,
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
|
|
Packit |
db064d |
ibdiag_process_opts(argc, argv, NULL, "DK", opts, process_opt,
|
|
Packit |
db064d |
usage_args, usage_examples);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
f = stdout;
|
|
Packit |
db064d |
argc -= optind;
|
|
Packit |
db064d |
argv += optind;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (argc < 2 && ports_file == NULL)
|
|
Packit |
db064d |
ibdiag_show_usage();
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (ibd_timeout)
|
|
Packit |
db064d |
timeout = ibd_timeout;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
|
|
Packit |
db064d |
if (!srcport)
|
|
Packit |
db064d |
IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
smp_mkey_set(srcport, ibd_mkey);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
node_name_map = open_node_name_map(node_name_map_file);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (ports_file == NULL) {
|
|
Packit |
db064d |
/* single get_route call when lids/guids on command line */
|
|
Packit |
db064d |
if (get_route(argv[0], argv[1]) != 0)
|
|
Packit |
db064d |
IBEXIT("Failed to get route information");
|
|
Packit |
db064d |
} else {
|
|
Packit |
db064d |
/* multiple get_route calls when reading lids/guids from a file */
|
|
Packit |
db064d |
ports_fd = fopen(ports_file, "r");
|
|
Packit |
db064d |
if (!ports_fd)
|
|
Packit |
db064d |
IBEXIT("cannot open ports-file %s", ports_file);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
while (fgets(portsbuf, sizeof(portsbuf), ports_fd) != NULL) {
|
|
Packit |
db064d |
line_count++;
|
|
Packit |
db064d |
p_first = strtok(portsbuf, "\n");
|
|
Packit |
db064d |
if (!p_first)
|
|
Packit |
db064d |
continue; /* ignore blank lines */
|
|
Packit |
db064d |
|
|
Packit |
db064d |
len = (int) strlen(p_first);
|
|
Packit |
db064d |
for (i = 0; i < len; i++) {
|
|
Packit |
db064d |
if (!isspace(p_first[i]))
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
if (i == len) /* ignore all spaces */
|
|
Packit |
db064d |
continue;
|
|
Packit |
db064d |
if (p_first[i] == '#')
|
|
Packit |
db064d |
continue; /* ignore comment lines */
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (sscanf(portsbuf, "%20s %20s", srcbuf, dstbuf) != 2)
|
|
Packit |
db064d |
IBEXIT("ports-file, %s, at line %i contains bad data",
|
|
Packit |
db064d |
ports_file, line_count);
|
|
Packit |
db064d |
num_port_pairs++;
|
|
Packit |
db064d |
if (get_route(srcbuf, dstbuf) != 0)
|
|
Packit |
db064d |
IBEXIT("Failed to get route information at line %i",
|
|
Packit |
db064d |
line_count);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
printf("%i lid/guid pairs processed from %s\n",
|
|
Packit |
db064d |
num_port_pairs, ports_file);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
close_node_name_map(node_name_map);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad_rpc_close_port(srcport);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
exit(0);
|
|
Packit |
db064d |
}
|