1 /*
2 * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
3 * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
4 * Copyright (c) 2008 Lawrence Livermore National Lab. All rights reserved.
5 * Copyright (c) 2010 HNR Consulting. All rights reserved.
6 *
7 * This software is available to you under a choice of one of two
8 * licenses. You may choose to be licensed under the terms of the GNU
9 * General Public License (GPL) Version 2, available from the file
10 * COPYING in the main directory of this source tree, or the
11 * OpenIB.org BSD license below:
12 *
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
15 * conditions are met:
16 *
17 * - Redistributions of source code must retain the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer.
20 *
21 * - Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials
24 * provided with the distribution.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 * SOFTWARE.
34 *
35 */
36
37 /*========================================================*/
38 /* FABRIC SCANNER SPECIFIC DATA */
39 /*========================================================*/
40
41 #if HAVE_CONFIG_H
42 #include <config.h>
43 #endif /* HAVE_CONFIG_H */
44
45 #include <stdlib.h>
46 #include <inttypes.h>
47
48 #include <infiniband/mad.h>
49
50 #include "internal.h"
51 #include "chassis.h"
52
53 static char *ChassisTypeStr[] =
54 { "", "ISR9288", "ISR9096", "ISR2012", "ISR2004", "ISR4700", "ISR4200" };
55 static char *ChassisSlotTypeStr[] = { "", "Line", "Spine", "SRBD" };
56
57 typedef struct chassis_scan {
58 ibnd_chassis_t *first_chassis;
59 ibnd_chassis_t *current_chassis;
60 ibnd_chassis_t *last_chassis;
61 } chassis_scan_t;
62
ibnd_get_chassis_type(ibnd_node_t * node)63 char *ibnd_get_chassis_type(ibnd_node_t * node)
64 {
65 int chassis_type;
66
67 if (!node) {
68 IBND_DEBUG("node parameter NULL\n");
69 return NULL;
70 }
71
72 if (!node->chassis)
73 return NULL;
74
75 chassis_type = mad_get_field(node->info, 0, IB_NODE_VENDORID_F);
76
77 switch (chassis_type)
78 {
79 case VTR_VENDOR_ID: /* Voltaire chassis */
80 {
81 if (node->ch_type == UNRESOLVED_CT || node->ch_type > ISR4200_CT)
82 return NULL;
83 return ChassisTypeStr[node->ch_type];
84 }
85 case MLX_VENDOR_ID:
86 {
87 if (node->ch_type_str[0] == '\0')
88 return NULL;
89 return node->ch_type_str;
90 }
91 default:
92 {
93 break;
94 }
95 }
96 return NULL;
97 }
98
ibnd_get_chassis_slot_str(ibnd_node_t * node,char * str,size_t size)99 char *ibnd_get_chassis_slot_str(ibnd_node_t * node, char *str, size_t size)
100 {
101 int vendor_id;
102
103 if (!node) {
104 IBND_DEBUG("node parameter NULL\n");
105 return NULL;
106 }
107
108 /* Currently, only if Voltaire or Mellanox chassis */
109 vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
110
111 if ((vendor_id != VTR_VENDOR_ID) && (vendor_id != MLX_VENDOR_ID))
112 return NULL;
113 if (!node->chassis)
114 return NULL;
115 if (node->ch_slot == UNRESOLVED_CS || node->ch_slot > SRBD_CS)
116 return NULL;
117 if (!str)
118 return NULL;
119 snprintf(str, size, "%s %d Chip %d", ChassisSlotTypeStr[node->ch_slot],
120 node->ch_slotnum, node->ch_anafanum);
121 return str;
122 }
123
find_chassisnum(ibnd_fabric_t * fabric,unsigned char chassisnum)124 static ibnd_chassis_t *find_chassisnum(ibnd_fabric_t * fabric,
125 unsigned char chassisnum)
126 {
127 ibnd_chassis_t *current;
128
129 for (current = fabric->chassis; current; current = current->next)
130 if (current->chassisnum == chassisnum)
131 return current;
132
133 return NULL;
134 }
135
topspin_chassisguid(uint64_t guid)136 static uint64_t topspin_chassisguid(uint64_t guid)
137 {
138 /* Byte 3 in system image GUID is chassis type, and */
139 /* Byte 4 is location ID (slot) so just mask off byte 4 */
140 return guid & 0xffffffff00ffffffULL;
141 }
142
ibnd_is_xsigo_guid(uint64_t guid)143 int ibnd_is_xsigo_guid(uint64_t guid)
144 {
145 if ((guid & 0xffffff0000000000ULL) == 0x0013970000000000ULL)
146 return 1;
147 else
148 return 0;
149 }
150
is_xsigo_leafone(uint64_t guid)151 static int is_xsigo_leafone(uint64_t guid)
152 {
153 if ((guid & 0xffffffffff000000ULL) == 0x0013970102000000ULL)
154 return 1;
155 else
156 return 0;
157 }
158
ibnd_is_xsigo_hca(uint64_t guid)159 int ibnd_is_xsigo_hca(uint64_t guid)
160 {
161 /* NodeType 2 is HCA */
162 if ((guid & 0xffffffff00000000ULL) == 0x0013970200000000ULL)
163 return 1;
164 else
165 return 0;
166 }
167
ibnd_is_xsigo_tca(uint64_t guid)168 int ibnd_is_xsigo_tca(uint64_t guid)
169 {
170 /* NodeType 3 is TCA */
171 if ((guid & 0xffffffff00000000ULL) == 0x0013970300000000ULL)
172 return 1;
173 else
174 return 0;
175 }
176
is_xsigo_ca(uint64_t guid)177 static int is_xsigo_ca(uint64_t guid)
178 {
179 if (ibnd_is_xsigo_hca(guid) || ibnd_is_xsigo_tca(guid))
180 return 1;
181 else
182 return 0;
183 }
184
is_xsigo_switch(uint64_t guid)185 static int is_xsigo_switch(uint64_t guid)
186 {
187 if ((guid & 0xffffffff00000000ULL) == 0x0013970100000000ULL)
188 return 1;
189 else
190 return 0;
191 }
192
xsigo_chassisguid(ibnd_node_t * node)193 static uint64_t xsigo_chassisguid(ibnd_node_t * node)
194 {
195 uint64_t sysimgguid =
196 mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
197 uint64_t remote_sysimgguid;
198
199 if (!is_xsigo_ca(sysimgguid)) {
200 /* Byte 3 is NodeType and byte 4 is PortType */
201 /* If NodeType is 1 (switch), PortType is masked */
202 if (is_xsigo_switch(sysimgguid))
203 return sysimgguid & 0xffffffff00ffffffULL;
204 else
205 return sysimgguid;
206 } else {
207 if (!node->ports || !node->ports[1])
208 return 0;
209
210 /* Is there a peer port ? */
211 if (!node->ports[1]->remoteport)
212 return sysimgguid;
213
214 /* If peer port is Leaf 1, use its chassis GUID */
215 remote_sysimgguid =
216 mad_get_field64(node->ports[1]->remoteport->node->info, 0,
217 IB_NODE_SYSTEM_GUID_F);
218 if (is_xsigo_leafone(remote_sysimgguid))
219 return remote_sysimgguid & 0xffffffff00ffffffULL;
220 else
221 return sysimgguid;
222 }
223 }
224
get_chassisguid(ibnd_node_t * node)225 static uint64_t get_chassisguid(ibnd_node_t * node)
226 {
227 uint32_t vendid = mad_get_field(node->info, 0, IB_NODE_VENDORID_F);
228 uint64_t sysimgguid =
229 mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
230
231 if (vendid == TS_VENDOR_ID || vendid == SS_VENDOR_ID)
232 return topspin_chassisguid(sysimgguid);
233 else if (vendid == XS_VENDOR_ID || ibnd_is_xsigo_guid(sysimgguid))
234 return xsigo_chassisguid(node);
235 else
236 return sysimgguid;
237 }
238
find_chassisguid(ibnd_fabric_t * fabric,ibnd_node_t * node)239 static ibnd_chassis_t *find_chassisguid(ibnd_fabric_t * fabric,
240 ibnd_node_t * node)
241 {
242 ibnd_chassis_t *current;
243 uint64_t chguid;
244
245 chguid = get_chassisguid(node);
246 for (current = fabric->chassis; current; current = current->next)
247 if (current->chassisguid == chguid)
248 return current;
249
250 return NULL;
251 }
252
ibnd_get_chassis_guid(ibnd_fabric_t * fabric,unsigned char chassisnum)253 uint64_t ibnd_get_chassis_guid(ibnd_fabric_t * fabric, unsigned char chassisnum)
254 {
255 ibnd_chassis_t *chassis;
256
257 if (!fabric) {
258 IBND_DEBUG("fabric parameter NULL\n");
259 return 0;
260 }
261
262 chassis = find_chassisnum(fabric, chassisnum);
263 if (chassis)
264 return chassis->chassisguid;
265 else
266 return 0;
267 }
268
is_router(ibnd_node_t * n)269 static int is_router(ibnd_node_t * n)
270 {
271 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
272 return (devid == VTR_DEVID_IB_FC_ROUTER ||
273 devid == VTR_DEVID_IB_IP_ROUTER);
274 }
275
is_spine_9096(ibnd_node_t * n)276 static int is_spine_9096(ibnd_node_t * n)
277 {
278 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
279 return (devid == VTR_DEVID_SFB4 || devid == VTR_DEVID_SFB4_DDR);
280 }
281
is_spine_9288(ibnd_node_t * n)282 static int is_spine_9288(ibnd_node_t * n)
283 {
284 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
285 return (devid == VTR_DEVID_SFB12 || devid == VTR_DEVID_SFB12_DDR);
286 }
287
is_spine_2004(ibnd_node_t * n)288 static int is_spine_2004(ibnd_node_t * n)
289 {
290 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
291 return (devid == VTR_DEVID_SFB2004);
292 }
293
is_spine_2012(ibnd_node_t * n)294 static int is_spine_2012(ibnd_node_t * n)
295 {
296 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
297 return (devid == VTR_DEVID_SFB2012);
298 }
299
is_spine_4700(ibnd_node_t * n)300 static int is_spine_4700(ibnd_node_t * n)
301 {
302 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
303 return (devid == VTR_DEVID_SFB4700);
304 }
305
is_spine_4700x2(ibnd_node_t * n)306 static int is_spine_4700x2(ibnd_node_t * n)
307 {
308 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
309 return (devid == VTR_DEVID_SFB4700X2);
310 }
311
is_spine_4200(ibnd_node_t * n)312 static int is_spine_4200(ibnd_node_t * n)
313 {
314 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
315 return (devid == VTR_DEVID_SFB4200);
316 }
317
is_spine(ibnd_node_t * n)318 static int is_spine(ibnd_node_t * n)
319 {
320 return (is_spine_9096(n) || is_spine_9288(n) ||
321 is_spine_2004(n) || is_spine_2012(n) ||
322 is_spine_4700(n) || is_spine_4700x2(n) ||
323 is_spine_4200(n));
324 }
325
is_line_24(ibnd_node_t * n)326 static int is_line_24(ibnd_node_t * n)
327 {
328 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
329 return (devid == VTR_DEVID_SLB24 ||
330 devid == VTR_DEVID_SLB24_DDR || devid == VTR_DEVID_SRB2004);
331 }
332
is_line_8(ibnd_node_t * n)333 static int is_line_8(ibnd_node_t * n)
334 {
335 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
336 return (devid == VTR_DEVID_SLB8);
337 }
338
is_line_2024(ibnd_node_t * n)339 static int is_line_2024(ibnd_node_t * n)
340 {
341 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
342 return (devid == VTR_DEVID_SLB2024);
343 }
344
is_line_4700(ibnd_node_t * n)345 static int is_line_4700(ibnd_node_t * n)
346 {
347 uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
348 return (devid == VTR_DEVID_SLB4018);
349 }
350
is_line(ibnd_node_t * n)351 static int is_line(ibnd_node_t * n)
352 {
353 return (is_line_24(n) || is_line_8(n) ||
354 is_line_2024(n) || is_line_4700(n));
355 }
356
is_chassis_switch(ibnd_node_t * n)357 int is_chassis_switch(ibnd_node_t * n)
358 {
359 return (is_spine(n) || is_line(n));
360 }
361
362 /* these structs help find Line (Anafa) slot number while using spine portnum */
363 char line_slot_2_sfb4[37] = {
364 0,
365 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3,
366 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
367 };
368 char anafa_line_slot_2_sfb4[37] = {
369 0,
370 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2,
371 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
372 };
373
374 char line_slot_2_sfb12[37] = {
375 0,
376 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
377 10, 10, 11, 11, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
378 };
379 char anafa_line_slot_2_sfb12[37] = {
380 0,
381 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
382 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
383 };
384
385 /* LB slot = table[spine port] */
386 char line_slot_2_sfb18[37] = {
387 0,
388 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
389 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18};
390 /* LB asic num = table[spine port] */
391 char anafa_line_slot_2_sfb18[37] = {
392 0,
393 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
394 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
395 };
396
397 /* LB slot = table[spine port] */
398 char line_slot_2_sfb18x2[37] = {
399 0,
400 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
401 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
402 /* LB asic num = table[spine port] */
403 char anafa_line_slot_2_sfb18x2[37] = {
404 0,
405 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
406 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
407 };
408
409 /* LB slot = table[spine port] */
410 char line_slot_2_sfb4200[37] = {
411 0,
412 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5,
413 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9};
414 /* LB asic num = table[spine port] */
415 char anafa_line_slot_2_sfb4200[37] = {
416 0,
417 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
418 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
419 };
420
421 /* IPR FCR modules connectivity while using sFB4 port as reference */
422 char ipr_slot_2_sfb4_port[37] = {
423 0,
424 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1,
425 3, 2, 1, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
426 };
427
428 /* these structs help find Spine (Anafa) slot number while using spine portnum */
429 char spine12_slot_2_slb[37] = {
430 0,
431 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0,
432 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
433 };
434 char anafa_spine12_slot_2_slb[37] = {
435 0,
436 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0,
437 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
438 };
439
440 char spine4_slot_2_slb[37] = {
441 0,
442 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0,
443 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
444 };
445 char anafa_spine4_slot_2_slb[37] = {
446 0,
447 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
448 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
449 };
450
451 /* FB slot = table[line port] */
452 char spine18_slot_2_slb[37] = {
453 0,
454 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
455 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
456 };
457 /* FB asic = table[line port] */
458 char anafa_spine18_slot_2_slb[37] = {
459 0,
460 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
461 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
462 };
463 char anafa_spine18x2_slot_2_slb[37] = {
464 0,
465 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
466 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
467 };
468
469 /* FB slot = table[line port] */
470 char sfb4200_slot_2_slb[37] = {
471 0,
472 1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
473 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
474 };
475 /* FB asic = table[line port] */
476 char anafa_sfb4200_slot_2_slb[37] = {
477 0,
478 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
479 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
480 };
481
482 /* reference { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; */
483
get_sfb_slot(ibnd_node_t * n,ibnd_port_t * lineport)484 static int get_sfb_slot(ibnd_node_t * n, ibnd_port_t * lineport)
485 {
486 n->ch_slot = SPINE_CS;
487 if (is_spine_9096(n)) {
488 n->ch_type = ISR9096_CT;
489 n->ch_slotnum = spine4_slot_2_slb[lineport->portnum];
490 n->ch_anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
491 } else if (is_spine_9288(n)) {
492 n->ch_type = ISR9288_CT;
493 n->ch_slotnum = spine12_slot_2_slb[lineport->portnum];
494 n->ch_anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
495 } else if (is_spine_2012(n)) {
496 n->ch_type = ISR2012_CT;
497 n->ch_slotnum = spine12_slot_2_slb[lineport->portnum];
498 n->ch_anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
499 } else if (is_spine_2004(n)) {
500 n->ch_type = ISR2004_CT;
501 n->ch_slotnum = spine4_slot_2_slb[lineport->portnum];
502 n->ch_anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
503 } else if (is_spine_4700(n)) {
504 n->ch_type = ISR4700_CT;
505 n->ch_slotnum = spine18_slot_2_slb[lineport->portnum];
506 n->ch_anafanum = anafa_spine18_slot_2_slb[lineport->portnum];
507 } else if (is_spine_4700x2(n)) {
508 n->ch_type = ISR4700_CT;
509 n->ch_slotnum = spine18_slot_2_slb[lineport->portnum];
510 n->ch_anafanum = anafa_spine18x2_slot_2_slb[lineport->portnum];
511 } else if (is_spine_4200(n)) {
512 n->ch_type = ISR4200_CT;
513 n->ch_slotnum = sfb4200_slot_2_slb[lineport->portnum];
514 n->ch_anafanum = anafa_sfb4200_slot_2_slb[lineport->portnum];
515 } else {
516 IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
517 n->guid);
518 }
519 return 0;
520 }
521
get_router_slot(ibnd_node_t * n,ibnd_port_t * spineport)522 static int get_router_slot(ibnd_node_t * n, ibnd_port_t * spineport)
523 {
524 uint64_t guessnum = 0;
525
526 n->ch_found = 1;
527
528 n->ch_slot = SRBD_CS;
529 if (is_spine_9096(spineport->node)) {
530 n->ch_type = ISR9096_CT;
531 n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
532 n->ch_anafanum = ipr_slot_2_sfb4_port[spineport->portnum];
533 } else if (is_spine_9288(spineport->node)) {
534 n->ch_type = ISR9288_CT;
535 n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
536 /* this is a smart guess based on nodeguids order on sFB-12 module */
537 guessnum = spineport->node->guid % 4;
538 /* module 1 <--> remote anafa 3 */
539 /* module 2 <--> remote anafa 2 */
540 /* module 3 <--> remote anafa 1 */
541 n->ch_anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2));
542 } else if (is_spine_2012(spineport->node)) {
543 n->ch_type = ISR2012_CT;
544 n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
545 /* this is a smart guess based on nodeguids order on sFB-12 module */
546 guessnum = spineport->node->guid % 4;
547 // module 1 <--> remote anafa 3
548 // module 2 <--> remote anafa 2
549 // module 3 <--> remote anafa 1
550 n->ch_anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2));
551 } else if (is_spine_2004(spineport->node)) {
552 n->ch_type = ISR2004_CT;
553 n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
554 n->ch_anafanum = ipr_slot_2_sfb4_port[spineport->portnum];
555 } else {
556 IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
557 spineport->node->guid);
558 }
559 return 0;
560 }
561
get_slb_slot(ibnd_node_t * n,ibnd_port_t * spineport)562 static int get_slb_slot(ibnd_node_t * n, ibnd_port_t * spineport)
563 {
564 n->ch_slot = LINE_CS;
565 if (is_spine_9096(spineport->node)) {
566 n->ch_type = ISR9096_CT;
567 n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
568 n->ch_anafanum = anafa_line_slot_2_sfb4[spineport->portnum];
569 } else if (is_spine_9288(spineport->node)) {
570 n->ch_type = ISR9288_CT;
571 n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
572 n->ch_anafanum = anafa_line_slot_2_sfb12[spineport->portnum];
573 } else if (is_spine_2012(spineport->node)) {
574 n->ch_type = ISR2012_CT;
575 n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
576 n->ch_anafanum = anafa_line_slot_2_sfb12[spineport->portnum];
577 } else if (is_spine_2004(spineport->node)) {
578 n->ch_type = ISR2004_CT;
579 n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
580 n->ch_anafanum = anafa_line_slot_2_sfb4[spineport->portnum];
581 } else if (is_spine_4700(spineport->node)) {
582 n->ch_type = ISR4700_CT;
583 n->ch_slotnum = line_slot_2_sfb18[spineport->portnum];
584 n->ch_anafanum = anafa_line_slot_2_sfb18[spineport->portnum];
585 } else if (is_spine_4700x2(spineport->node)) {
586 n->ch_type = ISR4700_CT;
587 n->ch_slotnum = line_slot_2_sfb18x2[spineport->portnum];
588 n->ch_anafanum = anafa_line_slot_2_sfb18x2[spineport->portnum];
589 } else if (is_spine_4200(spineport->node)) {
590 n->ch_type = ISR4200_CT;
591 n->ch_slotnum = line_slot_2_sfb4200[spineport->portnum];
592 n->ch_anafanum = anafa_line_slot_2_sfb4200[spineport->portnum];
593 } else {
594 IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
595 spineport->node->guid);
596 }
597 return 0;
598 }
599
600
601 /*
602 This function called for every Mellanox node in fabric
603 */
fill_mellanox_chassis_record(ibnd_node_t * node)604 static int fill_mellanox_chassis_record(ibnd_node_t * node)
605 {
606 int p = 0;
607 ibnd_port_t *port;
608
609 char node_desc[IB_SMP_DATA_SIZE];
610 char *system_name;
611 char *system_type;
612 char *system_slot_name;
613 char *node_index;
614 char *iter;
615 int dev_id;
616
617 /*
618 The node description has the following format:
619
620 'MF0;<system name>:<system type>/<system slot name>[:board type]/U<node index>'
621
622 - System slot name in our systems can be L[01-36] , S[01-18]
623 - Node index is always 1 (we don.t have boards with multiple IS4 chips).
624 - System name is taken from the currently configured host name.
625 -The board type is optional and we don.t set it currently - A leaf or spine slot can currently hold a single type of board.
626 */
627
628 memcpy(node_desc, node->nodedesc, IB_SMP_DATA_SIZE);
629
630 IBND_DEBUG("fill_mellanox_chassis_record: node_desc:%s \n",node_desc);
631
632 if (node->ch_found) /* somehow this node has already been passed */
633 return 0;
634
635 /* All mellanox IS4 switches have the same vendor id*/
636 dev_id = mad_get_field(node->info, 0,IB_NODE_DEVID_F);
637 if (dev_id != MLX_DEVID_IS4)
638 return 0;
639
640 if((node_desc[0] != 'M') ||
641 (node_desc[1] != 'F') ||
642 (node_desc[2] != '0') ||
643 (node_desc[3] != ';')) {
644 IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s \n",node_desc);
645 return 0;
646 }
647
648 /* parse system name*/
649 system_name = &node_desc[4];
650 for (iter = system_name ; (*iter != ':') && (*iter != '\0') ; iter++);
651 if(*iter == '\0'){
652 IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_name failed) \n",node_desc);
653 return 0;
654 }
655 *iter = '\0';
656 iter++;
657 /* parse system type*/
658 system_type = iter;
659 for ( ; (*iter != '/') && (*iter != '\0') ; iter++);
660 if(*iter == '\0'){
661 IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_type failed) \n",node_desc);
662 return 0;
663 }
664 *iter = '\0';
665 iter++;
666 /* parse system slot name*/
667 system_slot_name = iter;
668 for ( ; (*iter != '/') && (*iter != ':') && (*iter != '\0') ; iter++);
669 if(*iter == '\0'){
670 IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_slot_name failed) \n",node_desc);
671 return 0;
672 }
673 if(*iter == ':'){
674 *iter = '\0';
675 iter++;
676 for ( ; (*iter != '/') && (*iter != '\0') ; iter++);
677 if(*iter == '\0'){
678 IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get board type failed) \n",node_desc);
679 return 0;
680 }
681 }
682 *iter = '\0';
683 iter++;
684 node_index = iter;
685 if(node_index[0] != 'U'){
686 IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get node index) \n",node_desc);
687 return 0;
688 }
689
690 /* set Chip number (node index) */
691 node->ch_anafanum = (unsigned char) atoi(&node_index[1]);
692 if(node->ch_anafanum != 1){
693 IBND_DEBUG("Unexpected Chip number:%d \n",node->ch_anafanum);
694 }
695
696
697 /* set Line Spine numbers */
698 if(system_slot_name[0] == 'L')
699 node->ch_slot = LINE_CS;
700 else if(system_slot_name[0] == 'S')
701 node->ch_slot = SPINE_CS;
702 else{
703 IBND_DEBUG("fill_mellanox_chassis_record: Unsupported system_slot_name:%s \n",system_slot_name);
704 return 0;
705 }
706
707 /* The switch will be displayed under Line or Spine and not under Chassis switches */
708 node->ch_found = 1;
709
710 node->ch_slotnum = (unsigned char) atoi(&system_slot_name[1]);
711 if((node->ch_slot == LINE_CS && (node->ch_slotnum > (LINES_MAX_NUM + 1))) ||
712 (node->ch_slot == SPINE_CS && (node->ch_slotnum > (SPINES_MAX_NUM + 1)))){
713 IBND_ERROR("fill_mellanox_chassis_record: invalid slot number:%d \n",node->ch_slotnum);
714 node->ch_slotnum = 0;
715 return 0;
716 }
717
718 /*set ch_type_str*/
719 strncpy(node->ch_type_str , system_type, sizeof(node->ch_type_str)-1);
720
721 /* Line ports 1-18 are mapped to external ports 1-18*/
722 if(node->ch_slot == LINE_CS)
723 {
724 for (p = 1; p <= node->numports && p <= 18 ; p++) {
725 port = node->ports[p];
726 if (!port)
727 continue;
728 port->ext_portnum = p;
729 }
730 }
731
732 return 0;
733 }
734
insert_mellanox_line_and_spine(ibnd_node_t * node,ibnd_chassis_t * chassis)735 static int insert_mellanox_line_and_spine(ibnd_node_t * node, ibnd_chassis_t * chassis)
736 {
737 if (node->ch_slot == LINE_CS){
738
739 if (chassis->linenode[node->ch_slotnum])
740 return 0; /* already filled slot */
741
742 chassis->linenode[node->ch_slotnum] = node;
743 }
744 else if (node->ch_slot == SPINE_CS){
745
746 if (chassis->spinenode[node->ch_slotnum])
747 return 0; /* already filled slot */
748
749 chassis->spinenode[node->ch_slotnum] = node;
750 }
751 else
752 return 0;
753
754 node->chassis = chassis;
755
756 return 0;
757 }
758
759
760 /* forward declare this */
761 static void voltaire_portmap(ibnd_port_t * port);
762 /*
763 This function called for every Voltaire node in fabric
764 It could be optimized so, but time overhead is very small
765 and its only diag.util
766 */
fill_voltaire_chassis_record(ibnd_node_t * node)767 static int fill_voltaire_chassis_record(ibnd_node_t * node)
768 {
769 int p = 0;
770 ibnd_port_t *port;
771 ibnd_node_t *remnode = 0;
772
773 if (node->ch_found) /* somehow this node has already been passed */
774 return 0;
775 node->ch_found = 1;
776
777 /* node is router only in case of using unique lid */
778 /* (which is lid of chassis router port) */
779 /* in such case node->ports is actually a requested port... */
780 if (is_router(node))
781 /* find the remote node */
782 for (p = 1; p <= node->numports; p++) {
783 port = node->ports[p];
784 if (port && is_spine(port->remoteport->node))
785 get_router_slot(node, port->remoteport);
786 }
787 else if (is_spine(node)) {
788 int is_4700x2 = is_spine_4700x2(node);
789
790 for (p = 1; p <= node->numports; p++) {
791 port = node->ports[p];
792 if (!port || !port->remoteport)
793 continue;
794
795 /*
796 * Skip ISR4700 double density fabric boards ports 19-36
797 * as they are chassis external ports
798 */
799 if (is_4700x2 && (port->portnum > 18))
800 continue;
801
802 remnode = port->remoteport->node;
803 if (remnode->type != IB_NODE_SWITCH) {
804 if (!remnode->ch_found)
805 get_router_slot(remnode, port);
806 continue;
807 }
808 if (!node->ch_type)
809 /* we assume here that remoteport belongs to line */
810 get_sfb_slot(node, port->remoteport);
811
812 /* we could break here, but need to find if more routers connected */
813 }
814
815 } else if (is_line(node)) {
816 int is_4700_line = is_line_4700(node);
817
818 for (p = 1; p <= node->numports; p++) {
819 port = node->ports[p];
820 if (!port || !port->remoteport)
821 continue;
822
823 if ((is_4700_line && (port->portnum > 18)) ||
824 (!is_4700_line && (port->portnum > 12)))
825 continue;
826
827 /* we assume here that remoteport belongs to spine */
828 get_slb_slot(node, port->remoteport);
829 break;
830 }
831 }
832
833 /* for each port of this node, map external ports */
834 for (p = 1; p <= node->numports; p++) {
835 port = node->ports[p];
836 if (!port)
837 continue;
838 voltaire_portmap(port);
839 }
840
841 return 0;
842 }
843
get_line_index(ibnd_node_t * node)844 static int get_line_index(ibnd_node_t * node)
845 {
846 int retval;
847
848 if (is_line_4700(node))
849 retval = node->ch_slotnum;
850 else
851 retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum;
852
853 if (retval > LINES_MAX_NUM || retval < 1) {
854 printf("%s: retval = %d\n", __FUNCTION__, retval);
855 IBND_ERROR("Internal error\n");
856 return -1;
857 }
858 return retval;
859 }
860
get_spine_index(ibnd_node_t * node)861 static int get_spine_index(ibnd_node_t * node)
862 {
863 int retval;
864
865 if (is_spine_9288(node) || is_spine_2012(node))
866 retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum;
867 else if (is_spine_4700(node) || is_spine_4700x2(node))
868 retval = 2 * (node->ch_slotnum - 1) + node->ch_anafanum;
869 else
870 retval = node->ch_slotnum;
871
872 if (retval > SPINES_MAX_NUM || retval < 1) {
873 IBND_ERROR("Internal error\n");
874 return -1;
875 }
876 return retval;
877 }
878
insert_line_router(ibnd_node_t * node,ibnd_chassis_t * chassis)879 static int insert_line_router(ibnd_node_t * node, ibnd_chassis_t * chassis)
880 {
881 int i = get_line_index(node);
882
883 if (i < 0)
884 return i;
885
886 if (chassis->linenode[i])
887 return 0; /* already filled slot */
888
889 chassis->linenode[i] = node;
890 node->chassis = chassis;
891 return 0;
892 }
893
insert_spine(ibnd_node_t * node,ibnd_chassis_t * chassis)894 static int insert_spine(ibnd_node_t * node, ibnd_chassis_t * chassis)
895 {
896 int i = get_spine_index(node);
897
898 if (i < 0)
899 return i;
900
901 if (chassis->spinenode[i])
902 return 0; /* already filled slot */
903
904 chassis->spinenode[i] = node;
905 node->chassis = chassis;
906 return 0;
907 }
908
pass_on_lines_catch_spines(ibnd_chassis_t * chassis)909 static int pass_on_lines_catch_spines(ibnd_chassis_t * chassis)
910 {
911 ibnd_node_t *node, *remnode;
912 ibnd_port_t *port;
913 int i, p;
914
915 for (i = 1; i <= LINES_MAX_NUM; i++) {
916 int is_4700_line;
917
918 node = chassis->linenode[i];
919
920 if (!(node && is_line(node)))
921 continue; /* empty slot or router */
922
923 is_4700_line = is_line_4700(node);
924
925 for (p = 1; p <= node->numports; p++) {
926
927 port = node->ports[p];
928 if (!port || !port->remoteport)
929 continue;
930
931 if ((is_4700_line && (port->portnum > 18)) ||
932 (!is_4700_line && (port->portnum > 12)))
933 continue;
934
935 remnode = port->remoteport->node;
936
937 if (!remnode->ch_found)
938 continue; /* some error - spine not initialized ? FIXME */
939 if (insert_spine(remnode, chassis))
940 return -1;
941 }
942 }
943 return 0;
944 }
945
pass_on_spines_catch_lines(ibnd_chassis_t * chassis)946 static int pass_on_spines_catch_lines(ibnd_chassis_t * chassis)
947 {
948 ibnd_node_t *node, *remnode;
949 ibnd_port_t *port;
950 int i, p;
951
952 for (i = 1; i <= SPINES_MAX_NUM; i++) {
953 int is_4700x2;
954
955 node = chassis->spinenode[i];
956 if (!node)
957 continue; /* empty slot */
958
959 is_4700x2 = is_spine_4700x2(node);
960
961 for (p = 1; p <= node->numports; p++) {
962 port = node->ports[p];
963 if (!port || !port->remoteport)
964 continue;
965
966 /*
967 * ISR4700 double density fabric board ports 19-36 are
968 * chassis external ports, so skip them
969 */
970 if (is_4700x2 && (port->portnum > 18))
971 continue;
972
973 remnode = port->remoteport->node;
974
975 if (!remnode->ch_found)
976 continue; /* some error - line/router not initialized ? FIXME */
977
978 if (insert_line_router(remnode, chassis))
979 return -1;
980 }
981 }
982 return 0;
983 }
984
985 /*
986 Stupid interpolation algorithm...
987 But nothing to do - have to be compliant with VoltaireSM/NMS
988 */
pass_on_spines_interpolate_chguid(ibnd_chassis_t * chassis)989 static void pass_on_spines_interpolate_chguid(ibnd_chassis_t * chassis)
990 {
991 ibnd_node_t *node;
992 int i;
993
994 for (i = 1; i <= SPINES_MAX_NUM; i++) {
995 node = chassis->spinenode[i];
996 if (!node)
997 continue; /* skip the empty slots */
998
999 /* take first guid minus one to be consistent with SM */
1000 chassis->chassisguid = node->guid - 1;
1001 break;
1002 }
1003 }
1004
1005 /*
1006 This function fills chassis structure with all nodes
1007 in that chassis
1008 chassis structure = structure of one standalone chassis
1009 */
build_chassis(ibnd_node_t * node,ibnd_chassis_t * chassis)1010 static int build_chassis(ibnd_node_t * node, ibnd_chassis_t * chassis)
1011 {
1012 int p = 0;
1013 ibnd_node_t *remnode = 0;
1014 ibnd_port_t *port = 0;
1015
1016 /* we get here with node = chassis_spine */
1017 if (insert_spine(node, chassis))
1018 return -1;
1019
1020 /* loop: pass on all ports of node */
1021 for (p = 1; p <= node->numports; p++) {
1022
1023 port = node->ports[p];
1024 if (!port || !port->remoteport)
1025 continue;
1026
1027 /*
1028 * ISR4700 double density fabric board ports 19-36 are
1029 * chassis external ports, so skip them
1030 */
1031 if (is_spine_4700x2(node) && (port->portnum > 18))
1032 continue;
1033
1034 remnode = port->remoteport->node;
1035
1036 if (!remnode->ch_found)
1037 continue; /* some error - line or router not initialized ? FIXME */
1038
1039 insert_line_router(remnode, chassis);
1040 }
1041
1042 if (pass_on_lines_catch_spines(chassis))
1043 return -1;
1044 /* this pass needed for to catch routers, since routers connected only */
1045 /* to spines in slot 1 or 4 and we could miss them first time */
1046 if (pass_on_spines_catch_lines(chassis))
1047 return -1;
1048
1049 /* additional 2 passes needed for to overcome a problem of pure "in-chassis" */
1050 /* connectivity - extra pass to ensure that all related chips/modules */
1051 /* inserted into the chassis */
1052 if (pass_on_lines_catch_spines(chassis))
1053 return -1;
1054 if (pass_on_spines_catch_lines(chassis))
1055 return -1;
1056 pass_on_spines_interpolate_chguid(chassis);
1057
1058 return 0;
1059 }
1060
1061 /*========================================================*/
1062 /* INTERNAL TO EXTERNAL PORT MAPPING */
1063 /*========================================================*/
1064
1065 /*
1066 Description : On ISR9288/9096 external ports indexing
1067 is not matching the internal ( anafa ) port
1068 indexes. Use this MAP to translate the data you get from
1069 the OpenIB diagnostics (smpquery, ibroute, ibtracert, etc.)
1070
1071 Module : sLB-24
1072 anafa 1 anafa 2
1073 ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24
1074 int port | 22 23 24 18 17 16 | 22 23 24 18 17 16
1075 ext port | 1 2 3 4 5 6 | 7 8 9 10 11 12
1076 int port | 19 20 21 15 14 13 | 19 20 21 15 14 13
1077 ------------------------------------------------
1078
1079 Module : sLB-8
1080 anafa 1 anafa 2
1081 ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24
1082 int port | 24 23 22 18 17 16 | 24 23 22 18 17 16
1083 ext port | 1 2 3 4 5 6 | 7 8 9 10 11 12
1084 int port | 21 20 19 15 14 13 | 21 20 19 15 14 13
1085
1086 ----------->
1087 anafa 1 anafa 2
1088 ext port | - - 5 - - 6 | - - 7 - - 8
1089 int port | 24 23 22 18 17 16 | 24 23 22 18 17 16
1090 ext port | - - 1 - - 2 | - - 3 - - 4
1091 int port | 21 20 19 15 14 13 | 21 20 19 15 14 13
1092 ------------------------------------------------
1093
1094 Module : sLB-2024
1095
1096 ext port | 13 14 15 16 17 18 19 20 21 22 23 24
1097 A1 int port| 13 14 15 16 17 18 19 20 21 22 23 24
1098 ext port | 1 2 3 4 5 6 7 8 9 10 11 12
1099 A2 int port| 13 14 15 16 17 18 19 20 21 22 23 24
1100 ---------------------------------------------------
1101
1102 Module : sLB-4018
1103
1104 int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
1105 ext port | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
1106 ---------------------------------------------------
1107
1108 Module : sFB-4700X2
1109
1110 12X port -> 3 x 4X ports:
1111
1112 A1 int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
1113 ext port | 7 7 7 8 8 8 9 9 9 10 10 10 11 11 11 12 12 12
1114 A2 int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
1115 ext port | 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6
1116
1117 */
1118
1119 int int2ext_map_slb24[2][25] = {
1120 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 4, 18, 17, 16, 1, 2, 3,
1121 13, 14, 15},
1122 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 11, 10, 24, 23, 22, 7, 8, 9,
1123 19, 20, 21}
1124 };
1125
1126 int int2ext_map_slb8[2][25] = {
1127 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 1, 1, 1, 5, 5,
1128 5},
1129 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 3, 3, 3, 7, 7,
1130 7}
1131 };
1132
1133 int int2ext_map_slb2024[2][25] = {
1134 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20,
1135 21, 22, 23, 24},
1136 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1137 11, 12}
1138 };
1139
1140 int int2ext_map_slb4018[37] = {
1141 0,
1142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1143 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18
1144 };
1145
1146 int int2ext_map_sfb4700x2[2][37] = {
1147 {0,
1148 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1149 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12},
1150 {0,
1151 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1152 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6}
1153 };
1154
1155 /* reference { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; */
1156
1157 /* map internal ports to external ports if appropriate */
voltaire_portmap(ibnd_port_t * port)1158 static void voltaire_portmap(ibnd_port_t * port)
1159 {
1160 int portnum = port->portnum;
1161 int chipnum = 0;
1162 ibnd_node_t *node = port->node;
1163 int is_4700_line = is_line_4700(node);
1164 int is_4700x2_spine = is_spine_4700x2(node);
1165
1166 if (!node->ch_found || (!is_line(node) && !is_4700x2_spine)) {
1167 port->ext_portnum = 0;
1168 return;
1169 }
1170
1171 if (((is_4700_line || is_4700x2_spine) &&
1172 (portnum < 19 || portnum > 36)) ||
1173 ((!is_4700_line && !is_4700x2_spine) &&
1174 (portnum < 13 || portnum > 24))) {
1175 port->ext_portnum = 0;
1176 return;
1177 }
1178
1179 if (port->node->ch_anafanum < 1 || port->node->ch_anafanum > 2) {
1180 port->ext_portnum = 0;
1181 return;
1182 }
1183
1184 chipnum = port->node->ch_anafanum - 1;
1185
1186 if (is_line_24(node))
1187 port->ext_portnum = int2ext_map_slb24[chipnum][portnum];
1188 else if (is_line_2024(node))
1189 port->ext_portnum = int2ext_map_slb2024[chipnum][portnum];
1190 /* sLB-4018: Only one asic per LB */
1191 else if (is_4700_line)
1192 port->ext_portnum = int2ext_map_slb4018[portnum];
1193 /* sFB-4700X2 4X port */
1194 else if (is_4700x2_spine)
1195 port->ext_portnum = int2ext_map_sfb4700x2[chipnum][portnum];
1196 else
1197 port->ext_portnum = int2ext_map_slb8[chipnum][portnum];
1198 }
1199
add_chassis(chassis_scan_t * chassis_scan)1200 static int add_chassis(chassis_scan_t * chassis_scan)
1201 {
1202 if (!(chassis_scan->current_chassis =
1203 calloc(1, sizeof(ibnd_chassis_t)))) {
1204 IBND_ERROR("OOM: failed to allocate chassis object\n");
1205 return -1;
1206 }
1207
1208 if (chassis_scan->first_chassis == NULL) {
1209 chassis_scan->first_chassis = chassis_scan->current_chassis;
1210 chassis_scan->last_chassis = chassis_scan->current_chassis;
1211 } else {
1212 chassis_scan->last_chassis->next =
1213 chassis_scan->current_chassis;
1214 chassis_scan->last_chassis = chassis_scan->current_chassis;
1215 }
1216 return 0;
1217 }
1218
add_node_to_chassis(ibnd_chassis_t * chassis,ibnd_node_t * node)1219 static void add_node_to_chassis(ibnd_chassis_t * chassis, ibnd_node_t * node)
1220 {
1221 node->chassis = chassis;
1222 node->next_chassis_node = chassis->nodes;
1223 chassis->nodes = node;
1224 }
1225
1226 /*
1227 Main grouping function
1228 Algorithm:
1229 1. pass on every Voltaire node
1230 2. catch spine chip for every Voltaire node
1231 2.1 build/interpolate chassis around this chip
1232 2.2 go to 1.
1233 3. pass on non Voltaire nodes (SystemImageGUID based grouping)
1234 4. now group non Voltaire nodes by SystemImageGUID
1235 Returns:
1236 0 on success, -1 on failure
1237 */
group_nodes(ibnd_fabric_t * fabric)1238 int group_nodes(ibnd_fabric_t * fabric)
1239 {
1240 ibnd_node_t *node;
1241 int chassisnum = 0;
1242 ibnd_chassis_t *chassis;
1243 ibnd_chassis_t *ch, *ch_next;
1244 chassis_scan_t chassis_scan;
1245 int vendor_id;
1246
1247 chassis_scan.first_chassis = NULL;
1248 chassis_scan.current_chassis = NULL;
1249 chassis_scan.last_chassis = NULL;
1250
1251 /* first pass on switches and build for every Voltaire node */
1252 /* an appropriate chassis record (slotnum and position) */
1253 /* according to internal connectivity */
1254 /* not very efficient but clear code so... */
1255 for (node = fabric->switches; node; node = node->type_next) {
1256
1257 vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
1258
1259 if (vendor_id == VTR_VENDOR_ID
1260 && fill_voltaire_chassis_record(node))
1261 goto cleanup;
1262 else if (vendor_id == MLX_VENDOR_ID
1263 && fill_mellanox_chassis_record(node))
1264 goto cleanup;
1265
1266 }
1267
1268 /* separate every Voltaire chassis from each other and build linked list of them */
1269 /* algorithm: catch spine and find all surrounding nodes */
1270 for (node = fabric->switches; node; node = node->type_next) {
1271 if (mad_get_field(node->info, 0,
1272 IB_NODE_VENDORID_F) != VTR_VENDOR_ID)
1273 continue;
1274 if (!node->ch_found
1275 || (node->chassis && node->chassis->chassisnum)
1276 || !is_spine(node))
1277 continue;
1278 if (add_chassis(&chassis_scan))
1279 goto cleanup;
1280 chassis_scan.current_chassis->chassisnum = ++chassisnum;
1281 if (build_chassis(node, chassis_scan.current_chassis))
1282 goto cleanup;
1283 }
1284
1285 /* now make pass on nodes for chassis which are not Voltaire */
1286 /* grouped by common SystemImageGUID */
1287 for (node = fabric->nodes; node; node = node->next) {
1288 if (mad_get_field(node->info, 0,
1289 IB_NODE_VENDORID_F) == VTR_VENDOR_ID)
1290 continue;
1291 if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) {
1292 chassis = find_chassisguid(fabric, node);
1293 if (chassis)
1294 chassis->nodecount++;
1295 else {
1296 /* Possible new chassis */
1297 if (add_chassis(&chassis_scan))
1298 goto cleanup;
1299 chassis_scan.current_chassis->chassisguid =
1300 get_chassisguid(node);
1301 chassis_scan.current_chassis->nodecount = 1;
1302 if (!fabric->chassis)
1303 fabric->chassis = chassis_scan.first_chassis;
1304 }
1305 }
1306 }
1307
1308 /* now, make another pass to see which nodes are part of chassis */
1309 /* (defined as chassis->nodecount > 1) */
1310 for (node = fabric->nodes; node; node = node->next) {
1311
1312 vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
1313
1314 if (vendor_id == VTR_VENDOR_ID)
1315 continue;
1316 if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) {
1317 chassis = find_chassisguid(fabric, node);
1318 if (chassis && chassis->nodecount > 1) {
1319 if (!chassis->chassisnum)
1320 chassis->chassisnum = ++chassisnum;
1321 if (!node->ch_found) {
1322 node->ch_found = 1;
1323 add_node_to_chassis(chassis, node);
1324 }
1325 else if (vendor_id == MLX_VENDOR_ID){
1326 insert_mellanox_line_and_spine(node, chassis);
1327 }
1328 }
1329 }
1330 }
1331
1332 fabric->chassis = chassis_scan.first_chassis;
1333 return 0;
1334
1335 cleanup:
1336 ch = chassis_scan.first_chassis;
1337 while (ch) {
1338 ch_next = ch->next;
1339 free(ch);
1340 ch = ch_next;
1341 }
1342 fabric->chassis = NULL;
1343 return -1;
1344 }
1345