1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
3*d6b92ffaSHans Petter Selasky * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
4*d6b92ffaSHans Petter Selasky * Copyright (c) 2008 Lawrence Livermore National Laboratory
5*d6b92ffaSHans Petter Selasky * Copyright (c) 2010-2011 Mellanox Technologies LTD. All rights reserved.
6*d6b92ffaSHans Petter Selasky *
7*d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two
8*d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU
9*d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file
10*d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the
11*d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below:
12*d6b92ffaSHans Petter Selasky *
13*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or
14*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following
15*d6b92ffaSHans Petter Selasky * conditions are met:
16*d6b92ffaSHans Petter Selasky *
17*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above
18*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
19*d6b92ffaSHans Petter Selasky * disclaimer.
20*d6b92ffaSHans Petter Selasky *
21*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above
22*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
23*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials
24*d6b92ffaSHans Petter Selasky * provided with the distribution.
25*d6b92ffaSHans Petter Selasky *
26*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33*d6b92ffaSHans Petter Selasky * SOFTWARE.
34*d6b92ffaSHans Petter Selasky *
35*d6b92ffaSHans Petter Selasky */
36*d6b92ffaSHans Petter Selasky
37*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
38*d6b92ffaSHans Petter Selasky #include <config.h>
39*d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */
40*d6b92ffaSHans Petter Selasky
41*d6b92ffaSHans Petter Selasky #define _GNU_SOURCE
42*d6b92ffaSHans Petter Selasky #include <stdio.h>
43*d6b92ffaSHans Petter Selasky #include <stdlib.h>
44*d6b92ffaSHans Petter Selasky #include <unistd.h>
45*d6b92ffaSHans Petter Selasky #include <string.h>
46*d6b92ffaSHans Petter Selasky #include <errno.h>
47*d6b92ffaSHans Petter Selasky #include <inttypes.h>
48*d6b92ffaSHans Petter Selasky
49*d6b92ffaSHans Petter Selasky #include <infiniband/umad.h>
50*d6b92ffaSHans Petter Selasky #include <infiniband/mad.h>
51*d6b92ffaSHans Petter Selasky
52*d6b92ffaSHans Petter Selasky #include <infiniband/ibnetdisc.h>
53*d6b92ffaSHans Petter Selasky #include <complib/cl_nodenamemap.h>
54*d6b92ffaSHans Petter Selasky
55*d6b92ffaSHans Petter Selasky #include "internal.h"
56*d6b92ffaSHans Petter Selasky #include "chassis.h"
57*d6b92ffaSHans Petter Selasky
58*d6b92ffaSHans Petter Selasky /* forward declarations */
59*d6b92ffaSHans Petter Selasky struct ni_cbdata
60*d6b92ffaSHans Petter Selasky {
61*d6b92ffaSHans Petter Selasky ibnd_node_t *node;
62*d6b92ffaSHans Petter Selasky int port_num;
63*d6b92ffaSHans Petter Selasky };
64*d6b92ffaSHans Petter Selasky static int query_node_info(smp_engine_t * engine, ib_portid_t * portid,
65*d6b92ffaSHans Petter Selasky struct ni_cbdata * cbdata);
66*d6b92ffaSHans Petter Selasky static int query_port_info(smp_engine_t * engine, ib_portid_t * portid,
67*d6b92ffaSHans Petter Selasky ibnd_node_t * node, int portnum);
68*d6b92ffaSHans Petter Selasky ibnd_port_t *ibnd_find_port_dr(ibnd_fabric_t * fabric, char *dr_str);
69*d6b92ffaSHans Petter Selasky
recv_switch_info(smp_engine_t * engine,ibnd_smp_t * smp,uint8_t * mad,void * cb_data)70*d6b92ffaSHans Petter Selasky static int recv_switch_info(smp_engine_t * engine, ibnd_smp_t * smp,
71*d6b92ffaSHans Petter Selasky uint8_t * mad, void *cb_data)
72*d6b92ffaSHans Petter Selasky {
73*d6b92ffaSHans Petter Selasky uint8_t *switch_info = mad + IB_SMP_DATA_OFFS;
74*d6b92ffaSHans Petter Selasky ibnd_node_t *node = cb_data;
75*d6b92ffaSHans Petter Selasky memcpy(node->switchinfo, switch_info, sizeof(node->switchinfo));
76*d6b92ffaSHans Petter Selasky mad_decode_field(node->switchinfo, IB_SW_ENHANCED_PORT0_F,
77*d6b92ffaSHans Petter Selasky &node->smaenhsp0);
78*d6b92ffaSHans Petter Selasky return 0;
79*d6b92ffaSHans Petter Selasky }
80*d6b92ffaSHans Petter Selasky
query_switch_info(smp_engine_t * engine,ib_portid_t * portid,ibnd_node_t * node)81*d6b92ffaSHans Petter Selasky static int query_switch_info(smp_engine_t * engine, ib_portid_t * portid,
82*d6b92ffaSHans Petter Selasky ibnd_node_t * node)
83*d6b92ffaSHans Petter Selasky {
84*d6b92ffaSHans Petter Selasky node->smaenhsp0 = 0; /* assume base SP0 */
85*d6b92ffaSHans Petter Selasky return issue_smp(engine, portid, IB_ATTR_SWITCH_INFO, 0,
86*d6b92ffaSHans Petter Selasky recv_switch_info, node);
87*d6b92ffaSHans Petter Selasky }
88*d6b92ffaSHans Petter Selasky
add_port_to_dpath(ib_dr_path_t * path,int nextport)89*d6b92ffaSHans Petter Selasky static int add_port_to_dpath(ib_dr_path_t * path, int nextport)
90*d6b92ffaSHans Petter Selasky {
91*d6b92ffaSHans Petter Selasky if (path->cnt > sizeof(path->p) - 2)
92*d6b92ffaSHans Petter Selasky return -1;
93*d6b92ffaSHans Petter Selasky ++path->cnt;
94*d6b92ffaSHans Petter Selasky path->p[path->cnt] = (uint8_t) nextport;
95*d6b92ffaSHans Petter Selasky return path->cnt;
96*d6b92ffaSHans Petter Selasky }
97*d6b92ffaSHans Petter Selasky
retract_dpath(smp_engine_t * engine,ib_portid_t * portid)98*d6b92ffaSHans Petter Selasky static int retract_dpath(smp_engine_t * engine, ib_portid_t * portid)
99*d6b92ffaSHans Petter Selasky {
100*d6b92ffaSHans Petter Selasky ibnd_scan_t *scan = engine->user_data;
101*d6b92ffaSHans Petter Selasky f_internal_t *f_int = scan->f_int;
102*d6b92ffaSHans Petter Selasky
103*d6b92ffaSHans Petter Selasky if (scan->cfg->max_hops &&
104*d6b92ffaSHans Petter Selasky f_int->fabric.maxhops_discovered > scan->cfg->max_hops)
105*d6b92ffaSHans Petter Selasky return 0;
106*d6b92ffaSHans Petter Selasky
107*d6b92ffaSHans Petter Selasky /* this may seem wrong but the only time we would retract the path is
108*d6b92ffaSHans Petter Selasky * if the user specified a CA for the DR path and we are retracting
109*d6b92ffaSHans Petter Selasky * from that to find the node it is connected to. This counts as a
110*d6b92ffaSHans Petter Selasky * positive hop discovered
111*d6b92ffaSHans Petter Selasky */
112*d6b92ffaSHans Petter Selasky f_int->fabric.maxhops_discovered++;
113*d6b92ffaSHans Petter Selasky portid->drpath.p[portid->drpath.cnt] = 0;
114*d6b92ffaSHans Petter Selasky portid->drpath.cnt--;
115*d6b92ffaSHans Petter Selasky return 1;
116*d6b92ffaSHans Petter Selasky }
117*d6b92ffaSHans Petter Selasky
extend_dpath(smp_engine_t * engine,ib_portid_t * portid,int nextport)118*d6b92ffaSHans Petter Selasky static int extend_dpath(smp_engine_t * engine, ib_portid_t * portid,
119*d6b92ffaSHans Petter Selasky int nextport)
120*d6b92ffaSHans Petter Selasky {
121*d6b92ffaSHans Petter Selasky ibnd_scan_t *scan = engine->user_data;
122*d6b92ffaSHans Petter Selasky f_internal_t *f_int = scan->f_int;
123*d6b92ffaSHans Petter Selasky
124*d6b92ffaSHans Petter Selasky if (scan->cfg->max_hops &&
125*d6b92ffaSHans Petter Selasky f_int->fabric.maxhops_discovered > scan->cfg->max_hops)
126*d6b92ffaSHans Petter Selasky return 0;
127*d6b92ffaSHans Petter Selasky
128*d6b92ffaSHans Petter Selasky if (portid->lid) {
129*d6b92ffaSHans Petter Selasky /* If we were LID routed we need to set up the drslid */
130*d6b92ffaSHans Petter Selasky portid->drpath.drslid = (uint16_t) scan->selfportid.lid;
131*d6b92ffaSHans Petter Selasky portid->drpath.drdlid = 0xFFFF;
132*d6b92ffaSHans Petter Selasky }
133*d6b92ffaSHans Petter Selasky
134*d6b92ffaSHans Petter Selasky if (add_port_to_dpath(&portid->drpath, nextport) < 0) {
135*d6b92ffaSHans Petter Selasky IBND_ERROR("add port %d to DR path failed; %s\n", nextport,
136*d6b92ffaSHans Petter Selasky portid2str(portid));
137*d6b92ffaSHans Petter Selasky return -1;
138*d6b92ffaSHans Petter Selasky }
139*d6b92ffaSHans Petter Selasky
140*d6b92ffaSHans Petter Selasky if (((unsigned) portid->drpath.cnt - scan->initial_hops) >
141*d6b92ffaSHans Petter Selasky f_int->fabric.maxhops_discovered)
142*d6b92ffaSHans Petter Selasky f_int->fabric.maxhops_discovered++;
143*d6b92ffaSHans Petter Selasky
144*d6b92ffaSHans Petter Selasky return 1;
145*d6b92ffaSHans Petter Selasky }
146*d6b92ffaSHans Petter Selasky
recv_node_desc(smp_engine_t * engine,ibnd_smp_t * smp,uint8_t * mad,void * cb_data)147*d6b92ffaSHans Petter Selasky static int recv_node_desc(smp_engine_t * engine, ibnd_smp_t * smp,
148*d6b92ffaSHans Petter Selasky uint8_t * mad, void *cb_data)
149*d6b92ffaSHans Petter Selasky {
150*d6b92ffaSHans Petter Selasky uint8_t *node_desc = mad + IB_SMP_DATA_OFFS;
151*d6b92ffaSHans Petter Selasky ibnd_node_t *node = cb_data;
152*d6b92ffaSHans Petter Selasky memcpy(node->nodedesc, node_desc, sizeof(node->nodedesc));
153*d6b92ffaSHans Petter Selasky return 0;
154*d6b92ffaSHans Petter Selasky }
155*d6b92ffaSHans Petter Selasky
query_node_desc(smp_engine_t * engine,ib_portid_t * portid,ibnd_node_t * node)156*d6b92ffaSHans Petter Selasky static int query_node_desc(smp_engine_t * engine, ib_portid_t * portid,
157*d6b92ffaSHans Petter Selasky ibnd_node_t * node)
158*d6b92ffaSHans Petter Selasky {
159*d6b92ffaSHans Petter Selasky return issue_smp(engine, portid, IB_ATTR_NODE_DESC, 0,
160*d6b92ffaSHans Petter Selasky recv_node_desc, node);
161*d6b92ffaSHans Petter Selasky }
162*d6b92ffaSHans Petter Selasky
debug_port(ib_portid_t * portid,ibnd_port_t * port)163*d6b92ffaSHans Petter Selasky static void debug_port(ib_portid_t * portid, ibnd_port_t * port)
164*d6b92ffaSHans Petter Selasky {
165*d6b92ffaSHans Petter Selasky char width[64], speed[64];
166*d6b92ffaSHans Petter Selasky int iwidth;
167*d6b92ffaSHans Petter Selasky int ispeed, fdr10, espeed;
168*d6b92ffaSHans Petter Selasky uint8_t *info;
169*d6b92ffaSHans Petter Selasky uint32_t cap_mask;
170*d6b92ffaSHans Petter Selasky
171*d6b92ffaSHans Petter Selasky iwidth = mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F);
172*d6b92ffaSHans Petter Selasky ispeed = mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
173*d6b92ffaSHans Petter Selasky fdr10 = mad_get_field(port->ext_info, 0,
174*d6b92ffaSHans Petter Selasky IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F);
175*d6b92ffaSHans Petter Selasky
176*d6b92ffaSHans Petter Selasky if (port->node->type == IB_NODE_SWITCH)
177*d6b92ffaSHans Petter Selasky info = (uint8_t *)&port->node->ports[0]->info;
178*d6b92ffaSHans Petter Selasky else
179*d6b92ffaSHans Petter Selasky info = (uint8_t *)&port->info;
180*d6b92ffaSHans Petter Selasky cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
181*d6b92ffaSHans Petter Selasky if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
182*d6b92ffaSHans Petter Selasky espeed = mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
183*d6b92ffaSHans Petter Selasky else
184*d6b92ffaSHans Petter Selasky espeed = 0;
185*d6b92ffaSHans Petter Selasky IBND_DEBUG
186*d6b92ffaSHans Petter Selasky ("portid %s portnum %d: base lid %d state %d physstate %d %s %s %s %s\n",
187*d6b92ffaSHans Petter Selasky portid2str(portid), port->portnum, port->base_lid,
188*d6b92ffaSHans Petter Selasky mad_get_field(port->info, 0, IB_PORT_STATE_F),
189*d6b92ffaSHans Petter Selasky mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F),
190*d6b92ffaSHans Petter Selasky mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, width, 64, &iwidth),
191*d6b92ffaSHans Petter Selasky mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, speed, 64, &ispeed),
192*d6b92ffaSHans Petter Selasky (fdr10 & FDR10) ? "FDR10" : "",
193*d6b92ffaSHans Petter Selasky mad_dump_val(IB_PORT_LINK_SPEED_EXT_ACTIVE_F, speed, 64, &espeed));
194*d6b92ffaSHans Petter Selasky }
195*d6b92ffaSHans Petter Selasky
is_mlnx_ext_port_info_supported(ibnd_port_t * port)196*d6b92ffaSHans Petter Selasky static int is_mlnx_ext_port_info_supported(ibnd_port_t * port)
197*d6b92ffaSHans Petter Selasky {
198*d6b92ffaSHans Petter Selasky uint16_t devid = (uint16_t) mad_get_field(port->node->info, 0, IB_NODE_DEVID_F);
199*d6b92ffaSHans Petter Selasky uint32_t vendorid = (uint32_t) mad_get_field(port->node->info, 0, IB_NODE_VENDORID_F);
200*d6b92ffaSHans Petter Selasky
201*d6b92ffaSHans Petter Selasky if ((devid >= 0xc738 && devid <= 0xc73b) || devid == 0xcb20 || devid == 0xcf08 ||
202*d6b92ffaSHans Petter Selasky ((vendorid == 0x119f) &&
203*d6b92ffaSHans Petter Selasky /* Bull SwitchX */
204*d6b92ffaSHans Petter Selasky (devid == 0x1b02 || devid == 0x1b50 ||
205*d6b92ffaSHans Petter Selasky /* Bull SwitchIB and SwitchIB2 */
206*d6b92ffaSHans Petter Selasky devid == 0x1ba0 ||
207*d6b92ffaSHans Petter Selasky (devid >= 0x1bd0 && devid <= 0x1bd5))))
208*d6b92ffaSHans Petter Selasky return 1;
209*d6b92ffaSHans Petter Selasky if ((devid >= 0x1003 && devid <= 0x1017) ||
210*d6b92ffaSHans Petter Selasky ((vendorid == 0x119f) &&
211*d6b92ffaSHans Petter Selasky /* Bull ConnectX3 */
212*d6b92ffaSHans Petter Selasky (devid == 0x1b33 || devid == 0x1b73 ||
213*d6b92ffaSHans Petter Selasky devid == 0x1b40 || devid == 0x1b41 ||
214*d6b92ffaSHans Petter Selasky devid == 0x1b60 || devid == 0x1b61 ||
215*d6b92ffaSHans Petter Selasky /* Bull ConnectIB */
216*d6b92ffaSHans Petter Selasky devid == 0x1b83 ||
217*d6b92ffaSHans Petter Selasky devid == 0x1b93 || devid == 0x1b94 ||
218*d6b92ffaSHans Petter Selasky /* Bull ConnectX4 */
219*d6b92ffaSHans Petter Selasky devid == 0x1bb4 || devid == 0x1bb5 ||
220*d6b92ffaSHans Petter Selasky devid == 0x1bc4)))
221*d6b92ffaSHans Petter Selasky return 1;
222*d6b92ffaSHans Petter Selasky return 0;
223*d6b92ffaSHans Petter Selasky }
224*d6b92ffaSHans Petter Selasky
mlnx_ext_port_info_err(smp_engine_t * engine,ibnd_smp_t * smp,uint8_t * mad,void * cb_data)225*d6b92ffaSHans Petter Selasky int mlnx_ext_port_info_err(smp_engine_t * engine, ibnd_smp_t * smp,
226*d6b92ffaSHans Petter Selasky uint8_t * mad, void *cb_data)
227*d6b92ffaSHans Petter Selasky {
228*d6b92ffaSHans Petter Selasky f_internal_t *f_int = ((ibnd_scan_t *) engine->user_data)->f_int;
229*d6b92ffaSHans Petter Selasky ibnd_node_t *node = cb_data;
230*d6b92ffaSHans Petter Selasky ibnd_port_t *port;
231*d6b92ffaSHans Petter Selasky uint8_t port_num, local_port;
232*d6b92ffaSHans Petter Selasky
233*d6b92ffaSHans Petter Selasky port_num = (uint8_t) mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
234*d6b92ffaSHans Petter Selasky port = node->ports[port_num];
235*d6b92ffaSHans Petter Selasky if (!port) {
236*d6b92ffaSHans Petter Selasky IBND_ERROR("Failed to find 0x%" PRIx64 " port %u\n",
237*d6b92ffaSHans Petter Selasky node->guid, port_num);
238*d6b92ffaSHans Petter Selasky return -1;
239*d6b92ffaSHans Petter Selasky }
240*d6b92ffaSHans Petter Selasky
241*d6b92ffaSHans Petter Selasky local_port = (uint8_t) mad_get_field(port->info, 0, IB_PORT_LOCAL_PORT_F);
242*d6b92ffaSHans Petter Selasky debug_port(&smp->path, port);
243*d6b92ffaSHans Petter Selasky
244*d6b92ffaSHans Petter Selasky if (port_num && mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F)
245*d6b92ffaSHans Petter Selasky == IB_PORT_PHYS_STATE_LINKUP
246*d6b92ffaSHans Petter Selasky && ((node->type == IB_NODE_SWITCH && port_num != local_port) ||
247*d6b92ffaSHans Petter Selasky (node == f_int->fabric.from_node && port_num == f_int->fabric.from_portnum))) {
248*d6b92ffaSHans Petter Selasky int rc = 0;
249*d6b92ffaSHans Petter Selasky ib_portid_t path = smp->path;
250*d6b92ffaSHans Petter Selasky
251*d6b92ffaSHans Petter Selasky if (node->type != IB_NODE_SWITCH &&
252*d6b92ffaSHans Petter Selasky node == f_int->fabric.from_node &&
253*d6b92ffaSHans Petter Selasky path.drpath.cnt > 1)
254*d6b92ffaSHans Petter Selasky rc = retract_dpath(engine, &path);
255*d6b92ffaSHans Petter Selasky else {
256*d6b92ffaSHans Petter Selasky /* we can't proceed through an HCA with DR */
257*d6b92ffaSHans Petter Selasky if (path.lid == 0 || node->type == IB_NODE_SWITCH)
258*d6b92ffaSHans Petter Selasky rc = extend_dpath(engine, &path, port_num);
259*d6b92ffaSHans Petter Selasky }
260*d6b92ffaSHans Petter Selasky
261*d6b92ffaSHans Petter Selasky if (rc > 0) {
262*d6b92ffaSHans Petter Selasky struct ni_cbdata * cbdata = malloc(sizeof(*cbdata));
263*d6b92ffaSHans Petter Selasky cbdata->node = node;
264*d6b92ffaSHans Petter Selasky cbdata->port_num = port_num;
265*d6b92ffaSHans Petter Selasky query_node_info(engine, &path, cbdata);
266*d6b92ffaSHans Petter Selasky }
267*d6b92ffaSHans Petter Selasky }
268*d6b92ffaSHans Petter Selasky
269*d6b92ffaSHans Petter Selasky return 0;
270*d6b92ffaSHans Petter Selasky }
271*d6b92ffaSHans Petter Selasky
recv_mlnx_ext_port_info(smp_engine_t * engine,ibnd_smp_t * smp,uint8_t * mad,void * cb_data)272*d6b92ffaSHans Petter Selasky static int recv_mlnx_ext_port_info(smp_engine_t * engine, ibnd_smp_t * smp,
273*d6b92ffaSHans Petter Selasky uint8_t * mad, void *cb_data)
274*d6b92ffaSHans Petter Selasky {
275*d6b92ffaSHans Petter Selasky f_internal_t *f_int = ((ibnd_scan_t *) engine->user_data)->f_int;
276*d6b92ffaSHans Petter Selasky ibnd_node_t *node = cb_data;
277*d6b92ffaSHans Petter Selasky ibnd_port_t *port;
278*d6b92ffaSHans Petter Selasky uint8_t *ext_port_info = mad + IB_SMP_DATA_OFFS;
279*d6b92ffaSHans Petter Selasky uint8_t port_num, local_port;
280*d6b92ffaSHans Petter Selasky
281*d6b92ffaSHans Petter Selasky port_num = (uint8_t) mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
282*d6b92ffaSHans Petter Selasky port = node->ports[port_num];
283*d6b92ffaSHans Petter Selasky if (!port) {
284*d6b92ffaSHans Petter Selasky IBND_ERROR("Failed to find 0x%" PRIx64 " port %u\n",
285*d6b92ffaSHans Petter Selasky node->guid, port_num);
286*d6b92ffaSHans Petter Selasky return -1;
287*d6b92ffaSHans Petter Selasky }
288*d6b92ffaSHans Petter Selasky
289*d6b92ffaSHans Petter Selasky memcpy(port->ext_info, ext_port_info, sizeof(port->ext_info));
290*d6b92ffaSHans Petter Selasky local_port = (uint8_t) mad_get_field(port->info, 0, IB_PORT_LOCAL_PORT_F);
291*d6b92ffaSHans Petter Selasky debug_port(&smp->path, port);
292*d6b92ffaSHans Petter Selasky
293*d6b92ffaSHans Petter Selasky if (port_num && mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F)
294*d6b92ffaSHans Petter Selasky == IB_PORT_PHYS_STATE_LINKUP
295*d6b92ffaSHans Petter Selasky && ((node->type == IB_NODE_SWITCH && port_num != local_port) ||
296*d6b92ffaSHans Petter Selasky (node == f_int->fabric.from_node && port_num == f_int->fabric.from_portnum))) {
297*d6b92ffaSHans Petter Selasky int rc = 0;
298*d6b92ffaSHans Petter Selasky ib_portid_t path = smp->path;
299*d6b92ffaSHans Petter Selasky
300*d6b92ffaSHans Petter Selasky if (node->type != IB_NODE_SWITCH &&
301*d6b92ffaSHans Petter Selasky node == f_int->fabric.from_node &&
302*d6b92ffaSHans Petter Selasky path.drpath.cnt > 1)
303*d6b92ffaSHans Petter Selasky rc = retract_dpath(engine, &path);
304*d6b92ffaSHans Petter Selasky else {
305*d6b92ffaSHans Petter Selasky /* we can't proceed through an HCA with DR */
306*d6b92ffaSHans Petter Selasky if (path.lid == 0 || node->type == IB_NODE_SWITCH)
307*d6b92ffaSHans Petter Selasky rc = extend_dpath(engine, &path, port_num);
308*d6b92ffaSHans Petter Selasky }
309*d6b92ffaSHans Petter Selasky
310*d6b92ffaSHans Petter Selasky if (rc > 0) {
311*d6b92ffaSHans Petter Selasky struct ni_cbdata * cbdata = malloc(sizeof(*cbdata));
312*d6b92ffaSHans Petter Selasky cbdata->node = node;
313*d6b92ffaSHans Petter Selasky cbdata->port_num = port_num;
314*d6b92ffaSHans Petter Selasky query_node_info(engine, &path, cbdata);
315*d6b92ffaSHans Petter Selasky }
316*d6b92ffaSHans Petter Selasky }
317*d6b92ffaSHans Petter Selasky
318*d6b92ffaSHans Petter Selasky return 0;
319*d6b92ffaSHans Petter Selasky }
320*d6b92ffaSHans Petter Selasky
query_mlnx_ext_port_info(smp_engine_t * engine,ib_portid_t * portid,ibnd_node_t * node,int portnum)321*d6b92ffaSHans Petter Selasky static int query_mlnx_ext_port_info(smp_engine_t * engine, ib_portid_t * portid,
322*d6b92ffaSHans Petter Selasky ibnd_node_t * node, int portnum)
323*d6b92ffaSHans Petter Selasky {
324*d6b92ffaSHans Petter Selasky IBND_DEBUG("Query MLNX Extended Port Info; %s (0x%" PRIx64 "):%d\n",
325*d6b92ffaSHans Petter Selasky portid2str(portid), node->guid, portnum);
326*d6b92ffaSHans Petter Selasky return issue_smp(engine, portid, IB_ATTR_MLNX_EXT_PORT_INFO, portnum,
327*d6b92ffaSHans Petter Selasky recv_mlnx_ext_port_info, node);
328*d6b92ffaSHans Petter Selasky }
329*d6b92ffaSHans Petter Selasky
recv_port_info(smp_engine_t * engine,ibnd_smp_t * smp,uint8_t * mad,void * cb_data)330*d6b92ffaSHans Petter Selasky static int recv_port_info(smp_engine_t * engine, ibnd_smp_t * smp,
331*d6b92ffaSHans Petter Selasky uint8_t * mad, void *cb_data)
332*d6b92ffaSHans Petter Selasky {
333*d6b92ffaSHans Petter Selasky ibnd_scan_t *scan = (ibnd_scan_t *)engine->user_data;
334*d6b92ffaSHans Petter Selasky f_internal_t *f_int = scan->f_int;
335*d6b92ffaSHans Petter Selasky ibnd_node_t *node = cb_data;
336*d6b92ffaSHans Petter Selasky ibnd_port_t *port;
337*d6b92ffaSHans Petter Selasky uint8_t *port_info = mad + IB_SMP_DATA_OFFS;
338*d6b92ffaSHans Petter Selasky uint8_t port_num, local_port;
339*d6b92ffaSHans Petter Selasky int phystate, ispeed, espeed;
340*d6b92ffaSHans Petter Selasky uint8_t *info;
341*d6b92ffaSHans Petter Selasky uint32_t cap_mask;
342*d6b92ffaSHans Petter Selasky
343*d6b92ffaSHans Petter Selasky port_num = (uint8_t) mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
344*d6b92ffaSHans Petter Selasky local_port = (uint8_t) mad_get_field(port_info, 0, IB_PORT_LOCAL_PORT_F);
345*d6b92ffaSHans Petter Selasky
346*d6b92ffaSHans Petter Selasky /* this may have been created before */
347*d6b92ffaSHans Petter Selasky port = node->ports[port_num];
348*d6b92ffaSHans Petter Selasky if (!port) {
349*d6b92ffaSHans Petter Selasky port = node->ports[port_num] = calloc(1, sizeof(*port));
350*d6b92ffaSHans Petter Selasky if (!port) {
351*d6b92ffaSHans Petter Selasky IBND_ERROR("Failed to allocate 0x%" PRIx64 " port %u\n",
352*d6b92ffaSHans Petter Selasky node->guid, port_num);
353*d6b92ffaSHans Petter Selasky return -1;
354*d6b92ffaSHans Petter Selasky }
355*d6b92ffaSHans Petter Selasky port->guid =
356*d6b92ffaSHans Petter Selasky mad_get_field64(node->info, 0, IB_NODE_PORT_GUID_F);
357*d6b92ffaSHans Petter Selasky }
358*d6b92ffaSHans Petter Selasky
359*d6b92ffaSHans Petter Selasky memcpy(port->info, port_info, sizeof(port->info));
360*d6b92ffaSHans Petter Selasky port->node = node;
361*d6b92ffaSHans Petter Selasky port->portnum = port_num;
362*d6b92ffaSHans Petter Selasky port->ext_portnum = 0;
363*d6b92ffaSHans Petter Selasky port->base_lid = (uint16_t) mad_get_field(port->info, 0, IB_PORT_LID_F);
364*d6b92ffaSHans Petter Selasky port->lmc = (uint8_t) mad_get_field(port->info, 0, IB_PORT_LMC_F);
365*d6b92ffaSHans Petter Selasky
366*d6b92ffaSHans Petter Selasky if (port_num == 0) {
367*d6b92ffaSHans Petter Selasky node->smalid = port->base_lid;
368*d6b92ffaSHans Petter Selasky node->smalmc = port->lmc;
369*d6b92ffaSHans Petter Selasky } else if (node->type == IB_NODE_SWITCH) {
370*d6b92ffaSHans Petter Selasky port->base_lid = node->smalid;
371*d6b92ffaSHans Petter Selasky port->lmc = node->smalmc;
372*d6b92ffaSHans Petter Selasky }
373*d6b92ffaSHans Petter Selasky
374*d6b92ffaSHans Petter Selasky int rc1 = add_to_portguid_hash(port, f_int->fabric.portstbl);
375*d6b92ffaSHans Petter Selasky if (rc1)
376*d6b92ffaSHans Petter Selasky IBND_ERROR("Error Occurred when trying"
377*d6b92ffaSHans Petter Selasky " to insert new port guid 0x%016" PRIx64 " to DB\n",
378*d6b92ffaSHans Petter Selasky port->guid);
379*d6b92ffaSHans Petter Selasky
380*d6b92ffaSHans Petter Selasky add_to_portlid_hash(port, f_int->lid2guid);
381*d6b92ffaSHans Petter Selasky
382*d6b92ffaSHans Petter Selasky if ((scan->cfg->flags & IBND_CONFIG_MLX_EPI)
383*d6b92ffaSHans Petter Selasky && is_mlnx_ext_port_info_supported(port)) {
384*d6b92ffaSHans Petter Selasky phystate = mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F);
385*d6b92ffaSHans Petter Selasky ispeed = mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
386*d6b92ffaSHans Petter Selasky if (port->node->type == IB_NODE_SWITCH)
387*d6b92ffaSHans Petter Selasky info = (uint8_t *)&port->node->ports[0]->info;
388*d6b92ffaSHans Petter Selasky else
389*d6b92ffaSHans Petter Selasky info = (uint8_t *)&port->info;
390*d6b92ffaSHans Petter Selasky cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
391*d6b92ffaSHans Petter Selasky if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
392*d6b92ffaSHans Petter Selasky espeed = mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
393*d6b92ffaSHans Petter Selasky else
394*d6b92ffaSHans Petter Selasky espeed = 0;
395*d6b92ffaSHans Petter Selasky
396*d6b92ffaSHans Petter Selasky if (phystate == IB_PORT_PHYS_STATE_LINKUP &&
397*d6b92ffaSHans Petter Selasky ispeed == IB_LINK_SPEED_ACTIVE_10 &&
398*d6b92ffaSHans Petter Selasky espeed == IB_LINK_SPEED_EXT_ACTIVE_NONE) { /* LinkUp/QDR */
399*d6b92ffaSHans Petter Selasky query_mlnx_ext_port_info(engine, &smp->path,
400*d6b92ffaSHans Petter Selasky node, port_num);
401*d6b92ffaSHans Petter Selasky return 0;
402*d6b92ffaSHans Petter Selasky }
403*d6b92ffaSHans Petter Selasky }
404*d6b92ffaSHans Petter Selasky
405*d6b92ffaSHans Petter Selasky debug_port(&smp->path, port);
406*d6b92ffaSHans Petter Selasky
407*d6b92ffaSHans Petter Selasky if (port_num && mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F)
408*d6b92ffaSHans Petter Selasky == IB_PORT_PHYS_STATE_LINKUP
409*d6b92ffaSHans Petter Selasky && ((node->type == IB_NODE_SWITCH && port_num != local_port) ||
410*d6b92ffaSHans Petter Selasky (node == f_int->fabric.from_node && port_num == f_int->fabric.from_portnum))) {
411*d6b92ffaSHans Petter Selasky
412*d6b92ffaSHans Petter Selasky int rc = 0;
413*d6b92ffaSHans Petter Selasky ib_portid_t path = smp->path;
414*d6b92ffaSHans Petter Selasky
415*d6b92ffaSHans Petter Selasky if (node->type != IB_NODE_SWITCH &&
416*d6b92ffaSHans Petter Selasky node == f_int->fabric.from_node &&
417*d6b92ffaSHans Petter Selasky path.drpath.cnt > 1)
418*d6b92ffaSHans Petter Selasky rc = retract_dpath(engine, &path);
419*d6b92ffaSHans Petter Selasky else {
420*d6b92ffaSHans Petter Selasky /* we can't proceed through an HCA with DR */
421*d6b92ffaSHans Petter Selasky if (path.lid == 0 || node->type == IB_NODE_SWITCH)
422*d6b92ffaSHans Petter Selasky rc = extend_dpath(engine, &path, port_num);
423*d6b92ffaSHans Petter Selasky }
424*d6b92ffaSHans Petter Selasky
425*d6b92ffaSHans Petter Selasky if (rc > 0) {
426*d6b92ffaSHans Petter Selasky struct ni_cbdata * cbdata = malloc(sizeof(*cbdata));
427*d6b92ffaSHans Petter Selasky cbdata->node = node;
428*d6b92ffaSHans Petter Selasky cbdata->port_num = port_num;
429*d6b92ffaSHans Petter Selasky query_node_info(engine, &path, cbdata);
430*d6b92ffaSHans Petter Selasky }
431*d6b92ffaSHans Petter Selasky }
432*d6b92ffaSHans Petter Selasky
433*d6b92ffaSHans Petter Selasky return 0;
434*d6b92ffaSHans Petter Selasky }
435*d6b92ffaSHans Petter Selasky
recv_port0_info(smp_engine_t * engine,ibnd_smp_t * smp,uint8_t * mad,void * cb_data)436*d6b92ffaSHans Petter Selasky static int recv_port0_info(smp_engine_t * engine, ibnd_smp_t * smp,
437*d6b92ffaSHans Petter Selasky uint8_t * mad, void *cb_data)
438*d6b92ffaSHans Petter Selasky {
439*d6b92ffaSHans Petter Selasky ibnd_node_t *node = cb_data;
440*d6b92ffaSHans Petter Selasky int i, status;
441*d6b92ffaSHans Petter Selasky
442*d6b92ffaSHans Petter Selasky status = recv_port_info(engine, smp, mad, cb_data);
443*d6b92ffaSHans Petter Selasky /* Query PortInfo on switch external/physical ports */
444*d6b92ffaSHans Petter Selasky for (i = 1; i <= node->numports; i++)
445*d6b92ffaSHans Petter Selasky query_port_info(engine, &smp->path, node, i);
446*d6b92ffaSHans Petter Selasky
447*d6b92ffaSHans Petter Selasky return status;
448*d6b92ffaSHans Petter Selasky }
449*d6b92ffaSHans Petter Selasky
query_port_info(smp_engine_t * engine,ib_portid_t * portid,ibnd_node_t * node,int portnum)450*d6b92ffaSHans Petter Selasky static int query_port_info(smp_engine_t * engine, ib_portid_t * portid,
451*d6b92ffaSHans Petter Selasky ibnd_node_t * node, int portnum)
452*d6b92ffaSHans Petter Selasky {
453*d6b92ffaSHans Petter Selasky IBND_DEBUG("Query Port Info; %s (0x%" PRIx64 "):%d\n",
454*d6b92ffaSHans Petter Selasky portid2str(portid), node->guid, portnum);
455*d6b92ffaSHans Petter Selasky return issue_smp(engine, portid, IB_ATTR_PORT_INFO, portnum,
456*d6b92ffaSHans Petter Selasky portnum ? recv_port_info : recv_port0_info, node);
457*d6b92ffaSHans Petter Selasky }
458*d6b92ffaSHans Petter Selasky
create_node(smp_engine_t * engine,ib_portid_t * path,uint8_t * node_info)459*d6b92ffaSHans Petter Selasky static ibnd_node_t *create_node(smp_engine_t * engine, ib_portid_t * path,
460*d6b92ffaSHans Petter Selasky uint8_t * node_info)
461*d6b92ffaSHans Petter Selasky {
462*d6b92ffaSHans Petter Selasky f_internal_t *f_int = ((ibnd_scan_t *) engine->user_data)->f_int;
463*d6b92ffaSHans Petter Selasky ibnd_node_t *rc = calloc(1, sizeof(*rc));
464*d6b92ffaSHans Petter Selasky if (!rc) {
465*d6b92ffaSHans Petter Selasky IBND_ERROR("OOM: node creation failed\n");
466*d6b92ffaSHans Petter Selasky return NULL;
467*d6b92ffaSHans Petter Selasky }
468*d6b92ffaSHans Petter Selasky
469*d6b92ffaSHans Petter Selasky /* decode just a couple of fields for quicker reference. */
470*d6b92ffaSHans Petter Selasky mad_decode_field(node_info, IB_NODE_GUID_F, &rc->guid);
471*d6b92ffaSHans Petter Selasky mad_decode_field(node_info, IB_NODE_TYPE_F, &rc->type);
472*d6b92ffaSHans Petter Selasky mad_decode_field(node_info, IB_NODE_NPORTS_F, &rc->numports);
473*d6b92ffaSHans Petter Selasky
474*d6b92ffaSHans Petter Selasky rc->ports = calloc(rc->numports + 1, sizeof(*rc->ports));
475*d6b92ffaSHans Petter Selasky if (!rc->ports) {
476*d6b92ffaSHans Petter Selasky free(rc);
477*d6b92ffaSHans Petter Selasky IBND_ERROR("OOM: Failed to allocate the ports array\n");
478*d6b92ffaSHans Petter Selasky return NULL;
479*d6b92ffaSHans Petter Selasky }
480*d6b92ffaSHans Petter Selasky
481*d6b92ffaSHans Petter Selasky rc->path_portid = *path;
482*d6b92ffaSHans Petter Selasky memcpy(rc->info, node_info, sizeof(rc->info));
483*d6b92ffaSHans Petter Selasky
484*d6b92ffaSHans Petter Selasky int rc1 = add_to_nodeguid_hash(rc, f_int->fabric.nodestbl);
485*d6b92ffaSHans Petter Selasky if (rc1)
486*d6b92ffaSHans Petter Selasky IBND_ERROR("Error Occurred when trying"
487*d6b92ffaSHans Petter Selasky " to insert new node guid 0x%016" PRIx64 " to DB\n",
488*d6b92ffaSHans Petter Selasky rc->guid);
489*d6b92ffaSHans Petter Selasky
490*d6b92ffaSHans Petter Selasky /* add this to the all nodes list */
491*d6b92ffaSHans Petter Selasky rc->next = f_int->fabric.nodes;
492*d6b92ffaSHans Petter Selasky f_int->fabric.nodes = rc;
493*d6b92ffaSHans Petter Selasky
494*d6b92ffaSHans Petter Selasky add_to_type_list(rc, f_int);
495*d6b92ffaSHans Petter Selasky
496*d6b92ffaSHans Petter Selasky return rc;
497*d6b92ffaSHans Petter Selasky }
498*d6b92ffaSHans Petter Selasky
link_ports(ibnd_node_t * node,ibnd_port_t * port,ibnd_node_t * remotenode,ibnd_port_t * remoteport)499*d6b92ffaSHans Petter Selasky static void link_ports(ibnd_node_t * node, ibnd_port_t * port,
500*d6b92ffaSHans Petter Selasky ibnd_node_t * remotenode, ibnd_port_t * remoteport)
501*d6b92ffaSHans Petter Selasky {
502*d6b92ffaSHans Petter Selasky IBND_DEBUG("linking: 0x%" PRIx64 " %p->%p:%u and 0x%" PRIx64
503*d6b92ffaSHans Petter Selasky " %p->%p:%u\n", node->guid, node, port, port->portnum,
504*d6b92ffaSHans Petter Selasky remotenode->guid, remotenode, remoteport,
505*d6b92ffaSHans Petter Selasky remoteport->portnum);
506*d6b92ffaSHans Petter Selasky if (port->remoteport)
507*d6b92ffaSHans Petter Selasky port->remoteport->remoteport = NULL;
508*d6b92ffaSHans Petter Selasky if (remoteport->remoteport)
509*d6b92ffaSHans Petter Selasky remoteport->remoteport->remoteport = NULL;
510*d6b92ffaSHans Petter Selasky port->remoteport = remoteport;
511*d6b92ffaSHans Petter Selasky remoteport->remoteport = port;
512*d6b92ffaSHans Petter Selasky }
513*d6b92ffaSHans Petter Selasky
dump_endnode(ib_portid_t * path,char * prompt,ibnd_node_t * node,ibnd_port_t * port)514*d6b92ffaSHans Petter Selasky static void dump_endnode(ib_portid_t * path, char *prompt,
515*d6b92ffaSHans Petter Selasky ibnd_node_t * node, ibnd_port_t * port)
516*d6b92ffaSHans Petter Selasky {
517*d6b92ffaSHans Petter Selasky char type[64];
518*d6b92ffaSHans Petter Selasky mad_dump_node_type(type, sizeof(type), &node->type, sizeof(int));
519*d6b92ffaSHans Petter Selasky printf("%s -> %s %s {%016" PRIx64 "} portnum %d lid %d-%d \"%s\"\n",
520*d6b92ffaSHans Petter Selasky portid2str(path), prompt, type, node->guid,
521*d6b92ffaSHans Petter Selasky node->type == IB_NODE_SWITCH ? 0 : port->portnum,
522*d6b92ffaSHans Petter Selasky port->base_lid, port->base_lid + (1 << port->lmc) - 1,
523*d6b92ffaSHans Petter Selasky node->nodedesc);
524*d6b92ffaSHans Petter Selasky }
525*d6b92ffaSHans Petter Selasky
recv_node_info(smp_engine_t * engine,ibnd_smp_t * smp,uint8_t * mad,void * cb_data)526*d6b92ffaSHans Petter Selasky static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp,
527*d6b92ffaSHans Petter Selasky uint8_t * mad, void *cb_data)
528*d6b92ffaSHans Petter Selasky {
529*d6b92ffaSHans Petter Selasky ibnd_scan_t *scan = engine->user_data;
530*d6b92ffaSHans Petter Selasky f_internal_t *f_int = scan->f_int;
531*d6b92ffaSHans Petter Selasky uint8_t *node_info = mad + IB_SMP_DATA_OFFS;
532*d6b92ffaSHans Petter Selasky struct ni_cbdata *ni_cbdata = (struct ni_cbdata *)cb_data;
533*d6b92ffaSHans Petter Selasky ibnd_node_t *rem_node = NULL;
534*d6b92ffaSHans Petter Selasky int rem_port_num = 0;
535*d6b92ffaSHans Petter Selasky ibnd_node_t *node;
536*d6b92ffaSHans Petter Selasky int node_is_new = 0;
537*d6b92ffaSHans Petter Selasky uint64_t node_guid = mad_get_field64(node_info, 0, IB_NODE_GUID_F);
538*d6b92ffaSHans Petter Selasky uint64_t port_guid = mad_get_field64(node_info, 0, IB_NODE_PORT_GUID_F);
539*d6b92ffaSHans Petter Selasky int port_num = mad_get_field(node_info, 0, IB_NODE_LOCAL_PORT_F);
540*d6b92ffaSHans Petter Selasky ibnd_port_t *port = NULL;
541*d6b92ffaSHans Petter Selasky
542*d6b92ffaSHans Petter Selasky if (ni_cbdata) {
543*d6b92ffaSHans Petter Selasky rem_node = ni_cbdata->node;
544*d6b92ffaSHans Petter Selasky rem_port_num = ni_cbdata->port_num;
545*d6b92ffaSHans Petter Selasky free(ni_cbdata);
546*d6b92ffaSHans Petter Selasky }
547*d6b92ffaSHans Petter Selasky
548*d6b92ffaSHans Petter Selasky node = ibnd_find_node_guid(&f_int->fabric, node_guid);
549*d6b92ffaSHans Petter Selasky if (!node) {
550*d6b92ffaSHans Petter Selasky node = create_node(engine, &smp->path, node_info);
551*d6b92ffaSHans Petter Selasky if (!node)
552*d6b92ffaSHans Petter Selasky return -1;
553*d6b92ffaSHans Petter Selasky node_is_new = 1;
554*d6b92ffaSHans Petter Selasky }
555*d6b92ffaSHans Petter Selasky IBND_DEBUG("Found %s node GUID 0x%" PRIx64 " (%s)\n",
556*d6b92ffaSHans Petter Selasky node_is_new ? "new" : "old", node->guid,
557*d6b92ffaSHans Petter Selasky portid2str(&smp->path));
558*d6b92ffaSHans Petter Selasky
559*d6b92ffaSHans Petter Selasky port = node->ports[port_num];
560*d6b92ffaSHans Petter Selasky if (!port) {
561*d6b92ffaSHans Petter Selasky /* If we have not see this port before create a shell for it */
562*d6b92ffaSHans Petter Selasky port = node->ports[port_num] = calloc(1, sizeof(*port));
563*d6b92ffaSHans Petter Selasky if (!port)
564*d6b92ffaSHans Petter Selasky return -1;
565*d6b92ffaSHans Petter Selasky port->node = node;
566*d6b92ffaSHans Petter Selasky port->portnum = port_num;
567*d6b92ffaSHans Petter Selasky }
568*d6b92ffaSHans Petter Selasky port->guid = port_guid;
569*d6b92ffaSHans Petter Selasky
570*d6b92ffaSHans Petter Selasky if (scan->cfg->show_progress)
571*d6b92ffaSHans Petter Selasky dump_endnode(&smp->path, node_is_new ? "new" : "known",
572*d6b92ffaSHans Petter Selasky node, port);
573*d6b92ffaSHans Petter Selasky
574*d6b92ffaSHans Petter Selasky if (rem_node == NULL) { /* this is the start node */
575*d6b92ffaSHans Petter Selasky f_int->fabric.from_node = node;
576*d6b92ffaSHans Petter Selasky f_int->fabric.from_portnum = port_num;
577*d6b92ffaSHans Petter Selasky } else {
578*d6b92ffaSHans Petter Selasky /* link ports... */
579*d6b92ffaSHans Petter Selasky if (!rem_node->ports[rem_port_num]) {
580*d6b92ffaSHans Petter Selasky IBND_ERROR("Internal Error; "
581*d6b92ffaSHans Petter Selasky "Node(%p) 0x%" PRIx64
582*d6b92ffaSHans Petter Selasky " Port %d no port created!?!?!?\n\n",
583*d6b92ffaSHans Petter Selasky rem_node, rem_node->guid, rem_port_num);
584*d6b92ffaSHans Petter Selasky return -1;
585*d6b92ffaSHans Petter Selasky }
586*d6b92ffaSHans Petter Selasky
587*d6b92ffaSHans Petter Selasky link_ports(node, port, rem_node, rem_node->ports[rem_port_num]);
588*d6b92ffaSHans Petter Selasky }
589*d6b92ffaSHans Petter Selasky
590*d6b92ffaSHans Petter Selasky if (node_is_new) {
591*d6b92ffaSHans Petter Selasky query_node_desc(engine, &smp->path, node);
592*d6b92ffaSHans Petter Selasky
593*d6b92ffaSHans Petter Selasky if (node->type == IB_NODE_SWITCH) {
594*d6b92ffaSHans Petter Selasky query_switch_info(engine, &smp->path, node);
595*d6b92ffaSHans Petter Selasky /* Query PortInfo on Switch Port 0 first */
596*d6b92ffaSHans Petter Selasky query_port_info(engine, &smp->path, node, 0);
597*d6b92ffaSHans Petter Selasky }
598*d6b92ffaSHans Petter Selasky }
599*d6b92ffaSHans Petter Selasky
600*d6b92ffaSHans Petter Selasky if (node->type != IB_NODE_SWITCH)
601*d6b92ffaSHans Petter Selasky query_port_info(engine, &smp->path, node, port_num);
602*d6b92ffaSHans Petter Selasky
603*d6b92ffaSHans Petter Selasky return 0;
604*d6b92ffaSHans Petter Selasky }
605*d6b92ffaSHans Petter Selasky
query_node_info(smp_engine_t * engine,ib_portid_t * portid,struct ni_cbdata * cbdata)606*d6b92ffaSHans Petter Selasky static int query_node_info(smp_engine_t * engine, ib_portid_t * portid,
607*d6b92ffaSHans Petter Selasky struct ni_cbdata * cbdata)
608*d6b92ffaSHans Petter Selasky {
609*d6b92ffaSHans Petter Selasky IBND_DEBUG("Query Node Info; %s\n", portid2str(portid));
610*d6b92ffaSHans Petter Selasky return issue_smp(engine, portid, IB_ATTR_NODE_INFO, 0,
611*d6b92ffaSHans Petter Selasky recv_node_info, (void *)cbdata);
612*d6b92ffaSHans Petter Selasky }
613*d6b92ffaSHans Petter Selasky
ibnd_find_node_guid(ibnd_fabric_t * fabric,uint64_t guid)614*d6b92ffaSHans Petter Selasky ibnd_node_t *ibnd_find_node_guid(ibnd_fabric_t * fabric, uint64_t guid)
615*d6b92ffaSHans Petter Selasky {
616*d6b92ffaSHans Petter Selasky int hash = HASHGUID(guid) % HTSZ;
617*d6b92ffaSHans Petter Selasky ibnd_node_t *node;
618*d6b92ffaSHans Petter Selasky
619*d6b92ffaSHans Petter Selasky if (!fabric) {
620*d6b92ffaSHans Petter Selasky IBND_DEBUG("fabric parameter NULL\n");
621*d6b92ffaSHans Petter Selasky return NULL;
622*d6b92ffaSHans Petter Selasky }
623*d6b92ffaSHans Petter Selasky
624*d6b92ffaSHans Petter Selasky for (node = fabric->nodestbl[hash]; node; node = node->htnext)
625*d6b92ffaSHans Petter Selasky if (node->guid == guid)
626*d6b92ffaSHans Petter Selasky return node;
627*d6b92ffaSHans Petter Selasky
628*d6b92ffaSHans Petter Selasky return NULL;
629*d6b92ffaSHans Petter Selasky }
630*d6b92ffaSHans Petter Selasky
ibnd_find_node_dr(ibnd_fabric_t * fabric,char * dr_str)631*d6b92ffaSHans Petter Selasky ibnd_node_t *ibnd_find_node_dr(ibnd_fabric_t * fabric, char *dr_str)
632*d6b92ffaSHans Petter Selasky {
633*d6b92ffaSHans Petter Selasky ibnd_port_t *rc = ibnd_find_port_dr(fabric, dr_str);
634*d6b92ffaSHans Petter Selasky return rc->node;
635*d6b92ffaSHans Petter Selasky }
636*d6b92ffaSHans Petter Selasky
add_to_nodeguid_hash(ibnd_node_t * node,ibnd_node_t * hash[])637*d6b92ffaSHans Petter Selasky int add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[])
638*d6b92ffaSHans Petter Selasky {
639*d6b92ffaSHans Petter Selasky int rc = 0;
640*d6b92ffaSHans Petter Selasky ibnd_node_t *tblnode;
641*d6b92ffaSHans Petter Selasky int hash_idx = HASHGUID(node->guid) % HTSZ;
642*d6b92ffaSHans Petter Selasky
643*d6b92ffaSHans Petter Selasky for (tblnode = hash[hash_idx]; tblnode; tblnode = tblnode->htnext) {
644*d6b92ffaSHans Petter Selasky if (tblnode == node) {
645*d6b92ffaSHans Petter Selasky IBND_ERROR("Duplicate Node: Node with guid 0x%016"
646*d6b92ffaSHans Petter Selasky PRIx64 " already exists in nodes DB\n",
647*d6b92ffaSHans Petter Selasky node->guid);
648*d6b92ffaSHans Petter Selasky return 1;
649*d6b92ffaSHans Petter Selasky }
650*d6b92ffaSHans Petter Selasky }
651*d6b92ffaSHans Petter Selasky node->htnext = hash[hash_idx];
652*d6b92ffaSHans Petter Selasky hash[hash_idx] = node;
653*d6b92ffaSHans Petter Selasky return rc;
654*d6b92ffaSHans Petter Selasky }
655*d6b92ffaSHans Petter Selasky
add_to_portguid_hash(ibnd_port_t * port,ibnd_port_t * hash[])656*d6b92ffaSHans Petter Selasky int add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[])
657*d6b92ffaSHans Petter Selasky {
658*d6b92ffaSHans Petter Selasky int rc = 0;
659*d6b92ffaSHans Petter Selasky ibnd_port_t *tblport;
660*d6b92ffaSHans Petter Selasky int hash_idx = HASHGUID(port->guid) % HTSZ;
661*d6b92ffaSHans Petter Selasky
662*d6b92ffaSHans Petter Selasky for (tblport = hash[hash_idx]; tblport; tblport = tblport->htnext) {
663*d6b92ffaSHans Petter Selasky if (tblport == port) {
664*d6b92ffaSHans Petter Selasky IBND_ERROR("Duplicate Port: Port with guid 0x%016"
665*d6b92ffaSHans Petter Selasky PRIx64 " already exists in ports DB\n",
666*d6b92ffaSHans Petter Selasky port->guid);
667*d6b92ffaSHans Petter Selasky return 1;
668*d6b92ffaSHans Petter Selasky }
669*d6b92ffaSHans Petter Selasky }
670*d6b92ffaSHans Petter Selasky port->htnext = hash[hash_idx];
671*d6b92ffaSHans Petter Selasky hash[hash_idx] = port;
672*d6b92ffaSHans Petter Selasky return rc;
673*d6b92ffaSHans Petter Selasky }
674*d6b92ffaSHans Petter Selasky
create_lid2guid(f_internal_t * f_int)675*d6b92ffaSHans Petter Selasky void create_lid2guid(f_internal_t *f_int)
676*d6b92ffaSHans Petter Selasky {
677*d6b92ffaSHans Petter Selasky f_int->lid2guid = g_hash_table_new_full(g_direct_hash, g_direct_equal,
678*d6b92ffaSHans Petter Selasky NULL, NULL);
679*d6b92ffaSHans Petter Selasky }
680*d6b92ffaSHans Petter Selasky
destroy_lid2guid(f_internal_t * f_int)681*d6b92ffaSHans Petter Selasky void destroy_lid2guid(f_internal_t *f_int)
682*d6b92ffaSHans Petter Selasky {
683*d6b92ffaSHans Petter Selasky if (f_int->lid2guid) {
684*d6b92ffaSHans Petter Selasky g_hash_table_destroy(f_int->lid2guid);
685*d6b92ffaSHans Petter Selasky }
686*d6b92ffaSHans Petter Selasky }
687*d6b92ffaSHans Petter Selasky
add_to_portlid_hash(ibnd_port_t * port,GHashTable * htable)688*d6b92ffaSHans Petter Selasky void add_to_portlid_hash(ibnd_port_t * port, GHashTable *htable)
689*d6b92ffaSHans Petter Selasky {
690*d6b92ffaSHans Petter Selasky uint16_t base_lid = port->base_lid;
691*d6b92ffaSHans Petter Selasky uint16_t lid_mask = ((1 << port->lmc) -1);
692*d6b92ffaSHans Petter Selasky uint16_t lid = 0;
693*d6b92ffaSHans Petter Selasky /* 0 < valid lid <= 0xbfff */
694*d6b92ffaSHans Petter Selasky if (base_lid > 0 && base_lid <= 0xbfff) {
695*d6b92ffaSHans Petter Selasky /* We add the port for all lids
696*d6b92ffaSHans Petter Selasky * so it is easier to find any "random" lid specified */
697*d6b92ffaSHans Petter Selasky for (lid = base_lid; lid <= (base_lid + lid_mask); lid++) {
698*d6b92ffaSHans Petter Selasky g_hash_table_insert(htable, GINT_TO_POINTER(lid), port);
699*d6b92ffaSHans Petter Selasky }
700*d6b92ffaSHans Petter Selasky }
701*d6b92ffaSHans Petter Selasky }
702*d6b92ffaSHans Petter Selasky
add_to_type_list(ibnd_node_t * node,f_internal_t * f_int)703*d6b92ffaSHans Petter Selasky void add_to_type_list(ibnd_node_t * node, f_internal_t * f_int)
704*d6b92ffaSHans Petter Selasky {
705*d6b92ffaSHans Petter Selasky ibnd_fabric_t *fabric = &f_int->fabric;
706*d6b92ffaSHans Petter Selasky switch (node->type) {
707*d6b92ffaSHans Petter Selasky case IB_NODE_CA:
708*d6b92ffaSHans Petter Selasky node->type_next = fabric->ch_adapters;
709*d6b92ffaSHans Petter Selasky fabric->ch_adapters = node;
710*d6b92ffaSHans Petter Selasky break;
711*d6b92ffaSHans Petter Selasky case IB_NODE_SWITCH:
712*d6b92ffaSHans Petter Selasky node->type_next = fabric->switches;
713*d6b92ffaSHans Petter Selasky fabric->switches = node;
714*d6b92ffaSHans Petter Selasky break;
715*d6b92ffaSHans Petter Selasky case IB_NODE_ROUTER:
716*d6b92ffaSHans Petter Selasky node->type_next = fabric->routers;
717*d6b92ffaSHans Petter Selasky fabric->routers = node;
718*d6b92ffaSHans Petter Selasky break;
719*d6b92ffaSHans Petter Selasky }
720*d6b92ffaSHans Petter Selasky }
721*d6b92ffaSHans Petter Selasky
set_config(struct ibnd_config * config,struct ibnd_config * cfg)722*d6b92ffaSHans Petter Selasky static int set_config(struct ibnd_config *config, struct ibnd_config *cfg)
723*d6b92ffaSHans Petter Selasky {
724*d6b92ffaSHans Petter Selasky if (!config)
725*d6b92ffaSHans Petter Selasky return (-EINVAL);
726*d6b92ffaSHans Petter Selasky
727*d6b92ffaSHans Petter Selasky if (cfg)
728*d6b92ffaSHans Petter Selasky memcpy(config, cfg, sizeof(*config));
729*d6b92ffaSHans Petter Selasky
730*d6b92ffaSHans Petter Selasky if (!config->max_smps)
731*d6b92ffaSHans Petter Selasky config->max_smps = DEFAULT_MAX_SMP_ON_WIRE;
732*d6b92ffaSHans Petter Selasky if (!config->timeout_ms)
733*d6b92ffaSHans Petter Selasky config->timeout_ms = DEFAULT_TIMEOUT;
734*d6b92ffaSHans Petter Selasky if (!config->retries)
735*d6b92ffaSHans Petter Selasky config->retries = DEFAULT_RETRIES;
736*d6b92ffaSHans Petter Selasky
737*d6b92ffaSHans Petter Selasky return (0);
738*d6b92ffaSHans Petter Selasky }
739*d6b92ffaSHans Petter Selasky
allocate_fabric_internal(void)740*d6b92ffaSHans Petter Selasky f_internal_t *allocate_fabric_internal(void)
741*d6b92ffaSHans Petter Selasky {
742*d6b92ffaSHans Petter Selasky f_internal_t *f = calloc(1, sizeof(*f));
743*d6b92ffaSHans Petter Selasky if (f)
744*d6b92ffaSHans Petter Selasky create_lid2guid(f);
745*d6b92ffaSHans Petter Selasky
746*d6b92ffaSHans Petter Selasky return (f);
747*d6b92ffaSHans Petter Selasky }
748*d6b92ffaSHans Petter Selasky
ibnd_discover_fabric(char * ca_name,int ca_port,ib_portid_t * from,struct ibnd_config * cfg)749*d6b92ffaSHans Petter Selasky ibnd_fabric_t *ibnd_discover_fabric(char * ca_name, int ca_port,
750*d6b92ffaSHans Petter Selasky ib_portid_t * from,
751*d6b92ffaSHans Petter Selasky struct ibnd_config *cfg)
752*d6b92ffaSHans Petter Selasky {
753*d6b92ffaSHans Petter Selasky struct ibnd_config config = { 0 };
754*d6b92ffaSHans Petter Selasky f_internal_t *f_int = NULL;
755*d6b92ffaSHans Petter Selasky ib_portid_t my_portid = { 0 };
756*d6b92ffaSHans Petter Selasky smp_engine_t engine;
757*d6b92ffaSHans Petter Selasky ibnd_scan_t scan;
758*d6b92ffaSHans Petter Selasky struct ibmad_port *ibmad_port;
759*d6b92ffaSHans Petter Selasky int nc = 2;
760*d6b92ffaSHans Petter Selasky int mc[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
761*d6b92ffaSHans Petter Selasky
762*d6b92ffaSHans Petter Selasky /* If not specified start from "my" port */
763*d6b92ffaSHans Petter Selasky if (!from)
764*d6b92ffaSHans Petter Selasky from = &my_portid;
765*d6b92ffaSHans Petter Selasky
766*d6b92ffaSHans Petter Selasky if (set_config(&config, cfg)) {
767*d6b92ffaSHans Petter Selasky IBND_ERROR("Invalid ibnd_config\n");
768*d6b92ffaSHans Petter Selasky return NULL;
769*d6b92ffaSHans Petter Selasky }
770*d6b92ffaSHans Petter Selasky
771*d6b92ffaSHans Petter Selasky f_int = allocate_fabric_internal();
772*d6b92ffaSHans Petter Selasky if (!f_int) {
773*d6b92ffaSHans Petter Selasky IBND_ERROR("OOM: failed to calloc ibnd_fabric_t\n");
774*d6b92ffaSHans Petter Selasky return NULL;
775*d6b92ffaSHans Petter Selasky }
776*d6b92ffaSHans Petter Selasky
777*d6b92ffaSHans Petter Selasky memset(&scan.selfportid, 0, sizeof(scan.selfportid));
778*d6b92ffaSHans Petter Selasky scan.f_int = f_int;
779*d6b92ffaSHans Petter Selasky scan.cfg = &config;
780*d6b92ffaSHans Petter Selasky scan.initial_hops = from->drpath.cnt;
781*d6b92ffaSHans Petter Selasky
782*d6b92ffaSHans Petter Selasky ibmad_port = mad_rpc_open_port(ca_name, ca_port, mc, nc);
783*d6b92ffaSHans Petter Selasky if (!ibmad_port) {
784*d6b92ffaSHans Petter Selasky IBND_ERROR("can't open MAD port (%s:%d)\n", ca_name, ca_port);
785*d6b92ffaSHans Petter Selasky return (NULL);
786*d6b92ffaSHans Petter Selasky }
787*d6b92ffaSHans Petter Selasky mad_rpc_set_timeout(ibmad_port, cfg->timeout_ms);
788*d6b92ffaSHans Petter Selasky mad_rpc_set_retries(ibmad_port, cfg->retries);
789*d6b92ffaSHans Petter Selasky smp_mkey_set(ibmad_port, cfg->mkey);
790*d6b92ffaSHans Petter Selasky
791*d6b92ffaSHans Petter Selasky if (ib_resolve_self_via(&scan.selfportid,
792*d6b92ffaSHans Petter Selasky NULL, NULL, ibmad_port) < 0) {
793*d6b92ffaSHans Petter Selasky IBND_ERROR("Failed to resolve self\n");
794*d6b92ffaSHans Petter Selasky mad_rpc_close_port(ibmad_port);
795*d6b92ffaSHans Petter Selasky return NULL;
796*d6b92ffaSHans Petter Selasky }
797*d6b92ffaSHans Petter Selasky mad_rpc_close_port(ibmad_port);
798*d6b92ffaSHans Petter Selasky
799*d6b92ffaSHans Petter Selasky if (smp_engine_init(&engine, ca_name, ca_port, &scan, &config)) {
800*d6b92ffaSHans Petter Selasky free(f_int);
801*d6b92ffaSHans Petter Selasky return (NULL);
802*d6b92ffaSHans Petter Selasky }
803*d6b92ffaSHans Petter Selasky
804*d6b92ffaSHans Petter Selasky IBND_DEBUG("from %s\n", portid2str(from));
805*d6b92ffaSHans Petter Selasky
806*d6b92ffaSHans Petter Selasky if (!query_node_info(&engine, from, NULL))
807*d6b92ffaSHans Petter Selasky if (process_mads(&engine) != 0)
808*d6b92ffaSHans Petter Selasky goto error;
809*d6b92ffaSHans Petter Selasky
810*d6b92ffaSHans Petter Selasky f_int->fabric.total_mads_used = engine.total_smps;
811*d6b92ffaSHans Petter Selasky f_int->fabric.maxhops_discovered += scan.initial_hops;
812*d6b92ffaSHans Petter Selasky
813*d6b92ffaSHans Petter Selasky if (group_nodes(&f_int->fabric))
814*d6b92ffaSHans Petter Selasky goto error;
815*d6b92ffaSHans Petter Selasky
816*d6b92ffaSHans Petter Selasky smp_engine_destroy(&engine);
817*d6b92ffaSHans Petter Selasky return (ibnd_fabric_t *)f_int;
818*d6b92ffaSHans Petter Selasky error:
819*d6b92ffaSHans Petter Selasky smp_engine_destroy(&engine);
820*d6b92ffaSHans Petter Selasky ibnd_destroy_fabric(&f_int->fabric);
821*d6b92ffaSHans Petter Selasky return NULL;
822*d6b92ffaSHans Petter Selasky }
823*d6b92ffaSHans Petter Selasky
destroy_node(ibnd_node_t * node)824*d6b92ffaSHans Petter Selasky void destroy_node(ibnd_node_t * node)
825*d6b92ffaSHans Petter Selasky {
826*d6b92ffaSHans Petter Selasky int p = 0;
827*d6b92ffaSHans Petter Selasky
828*d6b92ffaSHans Petter Selasky if (node->ports) {
829*d6b92ffaSHans Petter Selasky for (p = 0; p <= node->numports; p++)
830*d6b92ffaSHans Petter Selasky free(node->ports[p]);
831*d6b92ffaSHans Petter Selasky free(node->ports);
832*d6b92ffaSHans Petter Selasky }
833*d6b92ffaSHans Petter Selasky free(node);
834*d6b92ffaSHans Petter Selasky }
835*d6b92ffaSHans Petter Selasky
ibnd_destroy_fabric(ibnd_fabric_t * fabric)836*d6b92ffaSHans Petter Selasky void ibnd_destroy_fabric(ibnd_fabric_t * fabric)
837*d6b92ffaSHans Petter Selasky {
838*d6b92ffaSHans Petter Selasky ibnd_node_t *node = NULL;
839*d6b92ffaSHans Petter Selasky ibnd_node_t *next = NULL;
840*d6b92ffaSHans Petter Selasky ibnd_chassis_t *ch, *ch_next;
841*d6b92ffaSHans Petter Selasky
842*d6b92ffaSHans Petter Selasky if (!fabric)
843*d6b92ffaSHans Petter Selasky return;
844*d6b92ffaSHans Petter Selasky
845*d6b92ffaSHans Petter Selasky ch = fabric->chassis;
846*d6b92ffaSHans Petter Selasky while (ch) {
847*d6b92ffaSHans Petter Selasky ch_next = ch->next;
848*d6b92ffaSHans Petter Selasky free(ch);
849*d6b92ffaSHans Petter Selasky ch = ch_next;
850*d6b92ffaSHans Petter Selasky }
851*d6b92ffaSHans Petter Selasky node = fabric->nodes;
852*d6b92ffaSHans Petter Selasky while (node) {
853*d6b92ffaSHans Petter Selasky next = node->next;
854*d6b92ffaSHans Petter Selasky destroy_node(node);
855*d6b92ffaSHans Petter Selasky node = next;
856*d6b92ffaSHans Petter Selasky }
857*d6b92ffaSHans Petter Selasky destroy_lid2guid((f_internal_t *)fabric);
858*d6b92ffaSHans Petter Selasky free(fabric);
859*d6b92ffaSHans Petter Selasky }
860*d6b92ffaSHans Petter Selasky
ibnd_iter_nodes(ibnd_fabric_t * fabric,ibnd_iter_node_func_t func,void * user_data)861*d6b92ffaSHans Petter Selasky void ibnd_iter_nodes(ibnd_fabric_t * fabric, ibnd_iter_node_func_t func,
862*d6b92ffaSHans Petter Selasky void *user_data)
863*d6b92ffaSHans Petter Selasky {
864*d6b92ffaSHans Petter Selasky ibnd_node_t *cur = NULL;
865*d6b92ffaSHans Petter Selasky
866*d6b92ffaSHans Petter Selasky if (!fabric) {
867*d6b92ffaSHans Petter Selasky IBND_DEBUG("fabric parameter NULL\n");
868*d6b92ffaSHans Petter Selasky return;
869*d6b92ffaSHans Petter Selasky }
870*d6b92ffaSHans Petter Selasky
871*d6b92ffaSHans Petter Selasky if (!func) {
872*d6b92ffaSHans Petter Selasky IBND_DEBUG("func parameter NULL\n");
873*d6b92ffaSHans Petter Selasky return;
874*d6b92ffaSHans Petter Selasky }
875*d6b92ffaSHans Petter Selasky
876*d6b92ffaSHans Petter Selasky for (cur = fabric->nodes; cur; cur = cur->next)
877*d6b92ffaSHans Petter Selasky func(cur, user_data);
878*d6b92ffaSHans Petter Selasky }
879*d6b92ffaSHans Petter Selasky
ibnd_iter_nodes_type(ibnd_fabric_t * fabric,ibnd_iter_node_func_t func,int node_type,void * user_data)880*d6b92ffaSHans Petter Selasky void ibnd_iter_nodes_type(ibnd_fabric_t * fabric, ibnd_iter_node_func_t func,
881*d6b92ffaSHans Petter Selasky int node_type, void *user_data)
882*d6b92ffaSHans Petter Selasky {
883*d6b92ffaSHans Petter Selasky ibnd_node_t *list = NULL;
884*d6b92ffaSHans Petter Selasky ibnd_node_t *cur = NULL;
885*d6b92ffaSHans Petter Selasky
886*d6b92ffaSHans Petter Selasky if (!fabric) {
887*d6b92ffaSHans Petter Selasky IBND_DEBUG("fabric parameter NULL\n");
888*d6b92ffaSHans Petter Selasky return;
889*d6b92ffaSHans Petter Selasky }
890*d6b92ffaSHans Petter Selasky
891*d6b92ffaSHans Petter Selasky if (!func) {
892*d6b92ffaSHans Petter Selasky IBND_DEBUG("func parameter NULL\n");
893*d6b92ffaSHans Petter Selasky return;
894*d6b92ffaSHans Petter Selasky }
895*d6b92ffaSHans Petter Selasky
896*d6b92ffaSHans Petter Selasky switch (node_type) {
897*d6b92ffaSHans Petter Selasky case IB_NODE_SWITCH:
898*d6b92ffaSHans Petter Selasky list = fabric->switches;
899*d6b92ffaSHans Petter Selasky break;
900*d6b92ffaSHans Petter Selasky case IB_NODE_CA:
901*d6b92ffaSHans Petter Selasky list = fabric->ch_adapters;
902*d6b92ffaSHans Petter Selasky break;
903*d6b92ffaSHans Petter Selasky case IB_NODE_ROUTER:
904*d6b92ffaSHans Petter Selasky list = fabric->routers;
905*d6b92ffaSHans Petter Selasky break;
906*d6b92ffaSHans Petter Selasky default:
907*d6b92ffaSHans Petter Selasky IBND_DEBUG("Invalid node_type specified %d\n", node_type);
908*d6b92ffaSHans Petter Selasky break;
909*d6b92ffaSHans Petter Selasky }
910*d6b92ffaSHans Petter Selasky
911*d6b92ffaSHans Petter Selasky for (cur = list; cur; cur = cur->type_next)
912*d6b92ffaSHans Petter Selasky func(cur, user_data);
913*d6b92ffaSHans Petter Selasky }
914*d6b92ffaSHans Petter Selasky
ibnd_find_port_lid(ibnd_fabric_t * fabric,uint16_t lid)915*d6b92ffaSHans Petter Selasky ibnd_port_t *ibnd_find_port_lid(ibnd_fabric_t * fabric,
916*d6b92ffaSHans Petter Selasky uint16_t lid)
917*d6b92ffaSHans Petter Selasky {
918*d6b92ffaSHans Petter Selasky ibnd_port_t *port;
919*d6b92ffaSHans Petter Selasky f_internal_t *f = (f_internal_t *)fabric;
920*d6b92ffaSHans Petter Selasky
921*d6b92ffaSHans Petter Selasky port = (ibnd_port_t *)g_hash_table_lookup(f->lid2guid,
922*d6b92ffaSHans Petter Selasky GINT_TO_POINTER(lid));
923*d6b92ffaSHans Petter Selasky
924*d6b92ffaSHans Petter Selasky return port;
925*d6b92ffaSHans Petter Selasky }
926*d6b92ffaSHans Petter Selasky
ibnd_find_port_guid(ibnd_fabric_t * fabric,uint64_t guid)927*d6b92ffaSHans Petter Selasky ibnd_port_t *ibnd_find_port_guid(ibnd_fabric_t * fabric, uint64_t guid)
928*d6b92ffaSHans Petter Selasky {
929*d6b92ffaSHans Petter Selasky int hash = HASHGUID(guid) % HTSZ;
930*d6b92ffaSHans Petter Selasky ibnd_port_t *port;
931*d6b92ffaSHans Petter Selasky
932*d6b92ffaSHans Petter Selasky if (!fabric) {
933*d6b92ffaSHans Petter Selasky IBND_DEBUG("fabric parameter NULL\n");
934*d6b92ffaSHans Petter Selasky return NULL;
935*d6b92ffaSHans Petter Selasky }
936*d6b92ffaSHans Petter Selasky
937*d6b92ffaSHans Petter Selasky for (port = fabric->portstbl[hash]; port; port = port->htnext)
938*d6b92ffaSHans Petter Selasky if (port->guid == guid)
939*d6b92ffaSHans Petter Selasky return port;
940*d6b92ffaSHans Petter Selasky
941*d6b92ffaSHans Petter Selasky return NULL;
942*d6b92ffaSHans Petter Selasky }
943*d6b92ffaSHans Petter Selasky
ibnd_find_port_dr(ibnd_fabric_t * fabric,char * dr_str)944*d6b92ffaSHans Petter Selasky ibnd_port_t *ibnd_find_port_dr(ibnd_fabric_t * fabric, char *dr_str)
945*d6b92ffaSHans Petter Selasky {
946*d6b92ffaSHans Petter Selasky int i = 0;
947*d6b92ffaSHans Petter Selasky ibnd_node_t *cur_node;
948*d6b92ffaSHans Petter Selasky ibnd_port_t *rc = NULL;
949*d6b92ffaSHans Petter Selasky ib_dr_path_t path;
950*d6b92ffaSHans Petter Selasky
951*d6b92ffaSHans Petter Selasky if (!fabric) {
952*d6b92ffaSHans Petter Selasky IBND_DEBUG("fabric parameter NULL\n");
953*d6b92ffaSHans Petter Selasky return NULL;
954*d6b92ffaSHans Petter Selasky }
955*d6b92ffaSHans Petter Selasky
956*d6b92ffaSHans Petter Selasky if (!dr_str) {
957*d6b92ffaSHans Petter Selasky IBND_DEBUG("dr_str parameter NULL\n");
958*d6b92ffaSHans Petter Selasky return NULL;
959*d6b92ffaSHans Petter Selasky }
960*d6b92ffaSHans Petter Selasky
961*d6b92ffaSHans Petter Selasky cur_node = fabric->from_node;
962*d6b92ffaSHans Petter Selasky
963*d6b92ffaSHans Petter Selasky if (str2drpath(&path, dr_str, 0, 0) == -1)
964*d6b92ffaSHans Petter Selasky return NULL;
965*d6b92ffaSHans Petter Selasky
966*d6b92ffaSHans Petter Selasky for (i = 0; i <= path.cnt; i++) {
967*d6b92ffaSHans Petter Selasky ibnd_port_t *remote_port = NULL;
968*d6b92ffaSHans Petter Selasky if (path.p[i] == 0)
969*d6b92ffaSHans Petter Selasky continue;
970*d6b92ffaSHans Petter Selasky if (!cur_node->ports)
971*d6b92ffaSHans Petter Selasky return NULL;
972*d6b92ffaSHans Petter Selasky
973*d6b92ffaSHans Petter Selasky remote_port = cur_node->ports[path.p[i]]->remoteport;
974*d6b92ffaSHans Petter Selasky if (!remote_port)
975*d6b92ffaSHans Petter Selasky return NULL;
976*d6b92ffaSHans Petter Selasky
977*d6b92ffaSHans Petter Selasky rc = remote_port;
978*d6b92ffaSHans Petter Selasky cur_node = remote_port->node;
979*d6b92ffaSHans Petter Selasky }
980*d6b92ffaSHans Petter Selasky
981*d6b92ffaSHans Petter Selasky return rc;
982*d6b92ffaSHans Petter Selasky }
983*d6b92ffaSHans Petter Selasky
ibnd_iter_ports(ibnd_fabric_t * fabric,ibnd_iter_port_func_t func,void * user_data)984*d6b92ffaSHans Petter Selasky void ibnd_iter_ports(ibnd_fabric_t * fabric, ibnd_iter_port_func_t func,
985*d6b92ffaSHans Petter Selasky void *user_data)
986*d6b92ffaSHans Petter Selasky {
987*d6b92ffaSHans Petter Selasky int i = 0;
988*d6b92ffaSHans Petter Selasky ibnd_port_t *cur = NULL;
989*d6b92ffaSHans Petter Selasky
990*d6b92ffaSHans Petter Selasky if (!fabric) {
991*d6b92ffaSHans Petter Selasky IBND_DEBUG("fabric parameter NULL\n");
992*d6b92ffaSHans Petter Selasky return;
993*d6b92ffaSHans Petter Selasky }
994*d6b92ffaSHans Petter Selasky
995*d6b92ffaSHans Petter Selasky if (!func) {
996*d6b92ffaSHans Petter Selasky IBND_DEBUG("func parameter NULL\n");
997*d6b92ffaSHans Petter Selasky return;
998*d6b92ffaSHans Petter Selasky }
999*d6b92ffaSHans Petter Selasky
1000*d6b92ffaSHans Petter Selasky for (i = 0; i<HTSZ; i++)
1001*d6b92ffaSHans Petter Selasky for (cur = fabric->portstbl[i]; cur; cur = cur->htnext)
1002*d6b92ffaSHans Petter Selasky func(cur, user_data);
1003*d6b92ffaSHans Petter Selasky }
1004