2 * Copyright (c) 2004-2007 Voltaire Inc. All rights reserved.
\r
3 * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
\r
5 * This software is available to you under a choice of one of two
\r
6 * licenses. You may choose to be licensed under the terms of the GNU
\r
7 * General Public License (GPL) Version 2, available from the file
\r
8 * COPYING in the main directory of this source tree, or the
\r
9 * OpenIB.org BSD license below:
\r
11 * Redistribution and use in source and binary forms, with or
\r
12 * without modification, are permitted provided that the following
\r
13 * conditions are met:
\r
15 * - Redistributions of source code must retain the above
\r
16 * copyright notice, this list of conditions and the following
\r
19 * - Redistributions in binary form must reproduce the above
\r
20 * copyright notice, this list of conditions and the following
\r
21 * disclaimer in the documentation and/or other materials
\r
22 * provided with the distribution.
\r
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
35 /*========================================================*/
\r
36 /* FABRIC SCANNER SPECIFIC DATA */
\r
37 /*========================================================*/
\r
40 # include <config.h>
\r
41 #endif /* HAVE_CONFIG_H */
\r
45 #if defined(_WIN32) || defined(_WIN64)
\r
46 #include <windows.h>
\r
47 #include <winsock2.h>
\r
48 #include "..\ibdiag_common.c"
\r
51 #include <inttypes.h>
\r
54 #include <infiniband/common.h>
\r
55 #include <infiniband/mad.h>
\r
57 #include "ibnetdiscover.h"
\r
58 #include "grouping.h"
\r
60 #define OUT_BUFFER_SIZE 16
\r
63 extern Node *nodesdist[MAXHOPS+1]; /* last is CA list */
\r
64 extern Node *mynode;
\r
65 extern Port *myport;
\r
66 extern int maxhops_discovered;
\r
68 AllChassisList mylist;
\r
70 char *ChassisTypeStr[5] = { "", "ISR9288", "ISR9096", "ISR2012", "ISR2004" };
\r
71 char *ChassisSlotStr[4] = { "", "Line", "Spine", "SRBD" };
\r
74 char *get_chassis_type(unsigned char chassistype)
\r
76 if (chassistype == UNRESOLVED_CT || chassistype > ISR2004_CT)
\r
78 return ChassisTypeStr[chassistype];
\r
81 char *get_chassis_slot(unsigned char chassisslot)
\r
83 if (chassisslot == UNRESOLVED_CS || chassisslot > SRBD_CS)
\r
85 return ChassisSlotStr[chassisslot];
\r
88 static struct ChassisList *find_chassisnum(unsigned char chassisnum)
\r
90 ChassisList *current;
\r
92 for (current = mylist.first; current; current = current->next) {
\r
93 if (current->chassisnum == chassisnum)
\r
100 static uint64_t topspin_chassisguid(uint64_t guid)
\r
102 /* Byte 3 in system image GUID is chassis type, and */
\r
103 /* Byte 4 is location ID (slot) so just mask off byte 4 */
\r
104 return guid & 0xffffffff00ffffffULL;
\r
107 int is_xsigo_guid(uint64_t guid)
\r
109 if ((guid & 0xffffff0000000000ULL) == 0x0013970000000000ULL)
\r
115 static int is_xsigo_leafone(uint64_t guid)
\r
117 if ((guid & 0xffffffffff000000ULL) == 0x0013970102000000ULL)
\r
123 int is_xsigo_hca(uint64_t guid)
\r
125 /* NodeType 2 is HCA */
\r
126 if ((guid & 0xffffffff00000000ULL) == 0x0013970200000000ULL)
\r
132 int is_xsigo_tca(uint64_t guid)
\r
134 /* NodeType 3 is TCA */
\r
135 if ((guid & 0xffffffff00000000ULL) == 0x0013970300000000ULL)
\r
141 static int is_xsigo_ca(uint64_t guid)
\r
143 if (is_xsigo_hca(guid) || is_xsigo_tca(guid))
\r
149 static int is_xsigo_switch(uint64_t guid)
\r
151 if ((guid & 0xffffffff00000000ULL) == 0x0013970100000000ULL)
\r
157 static uint64_t xsigo_chassisguid(Node *node)
\r
159 if (!is_xsigo_ca(node->sysimgguid)) {
\r
160 /* Byte 3 is NodeType and byte 4 is PortType */
\r
161 /* If NodeType is 1 (switch), PortType is masked */
\r
162 if (is_xsigo_switch(node->sysimgguid))
\r
163 return node->sysimgguid & 0xffffffff00ffffffULL;
\r
165 return node->sysimgguid;
\r
167 /* Is there a peer port ? */
\r
168 if (!node->ports->remoteport)
\r
169 return node->sysimgguid;
\r
171 /* If peer port is Leaf 1, use its chassis GUID */
\r
172 if (is_xsigo_leafone(node->ports->remoteport->node->sysimgguid))
\r
173 return node->ports->remoteport->node->sysimgguid &
\r
174 0xffffffff00ffffffULL;
\r
176 return node->sysimgguid;
\r
180 static uint64_t get_chassisguid(Node *node)
\r
182 if (node->vendid == TS_VENDOR_ID || node->vendid == SS_VENDOR_ID)
\r
183 return topspin_chassisguid(node->sysimgguid);
\r
184 else if (node->vendid == XS_VENDOR_ID || is_xsigo_guid(node->sysimgguid))
\r
185 return xsigo_chassisguid(node);
\r
187 return node->sysimgguid;
\r
190 static struct ChassisList *find_chassisguid(Node *node)
\r
192 ChassisList *current;
\r
195 chguid = get_chassisguid(node);
\r
196 for (current = mylist.first; current; current = current->next) {
\r
197 if (current->chassisguid == chguid)
\r
204 uint64_t get_chassis_guid(unsigned char chassisnum)
\r
206 ChassisList *chassis;
\r
208 chassis = find_chassisnum(chassisnum);
\r
210 return chassis->chassisguid;
\r
215 static int is_router(Node *node)
\r
217 return (node->devid == VTR_DEVID_IB_FC_ROUTER ||
\r
218 node->devid == VTR_DEVID_IB_IP_ROUTER);
\r
221 static int is_spine_9096(Node *node)
\r
223 return (node->devid == VTR_DEVID_SFB4 ||
\r
224 node->devid == VTR_DEVID_SFB4_DDR);
\r
227 static int is_spine_9288(Node *node)
\r
229 return (node->devid == VTR_DEVID_SFB12 ||
\r
230 node->devid == VTR_DEVID_SFB12_DDR);
\r
233 static int is_spine_2004(Node *node)
\r
235 return (node->devid == VTR_DEVID_SFB2004);
\r
238 static int is_spine_2012(Node *node)
\r
240 return (node->devid == VTR_DEVID_SFB2012);
\r
243 static int is_spine(Node *node)
\r
245 return (is_spine_9096(node) || is_spine_9288(node) ||
\r
246 is_spine_2004(node) || is_spine_2012(node));
\r
249 static int is_line_24(Node *node)
\r
251 return (node->devid == VTR_DEVID_SLB24 ||
\r
252 node->devid == VTR_DEVID_SLB24_DDR);
\r
255 static int is_line_8(Node *node)
\r
257 return (node->devid == VTR_DEVID_SLB8);
\r
260 static int is_line_2024(Node *node)
\r
262 return (node->devid == VTR_DEVID_SLB2024);
\r
265 static int is_line(Node *node)
\r
267 return (is_line_24(node) || is_line_8(node) || is_line_2024(node));
\r
270 int is_chassis_switch(Node *node)
\r
272 return (is_spine(node) || is_line(node));
\r
275 /* these structs help find Line (Anafa) slot number while using spine portnum */
\r
276 int line_slot_2_sfb4[25] = { 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4 };
\r
277 int anafa_line_slot_2_sfb4[25] = { 0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2 };
\r
278 int line_slot_2_sfb12[25] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10, 10, 11, 11, 12, 12 };
\r
279 int anafa_line_slot_2_sfb12[25] = { 0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 };
\r
281 /* IPR FCR modules connectivity while using sFB4 port as reference */
\r
282 int ipr_slot_2_sfb4_port[25] = { 0, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1 };
\r
284 /* these structs help find Spine (Anafa) slot number while using spine portnum */
\r
285 int spine12_slot_2_slb[25] = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
\r
286 int anafa_spine12_slot_2_slb[25]= { 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
\r
287 int spine4_slot_2_slb[25] = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
\r
288 int anafa_spine4_slot_2_slb[25] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
\r
289 /* 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 }; */
\r
291 static void get_sfb_slot(Node *node, Port *lineport)
\r
293 ChassisRecord *ch = node->chrecord;
\r
295 ch->chassisslot = SPINE_CS;
\r
296 if (is_spine_9096(node)) {
\r
297 ch->chassistype = ISR9096_CT;
\r
298 ch->slotnum = spine4_slot_2_slb[lineport->portnum];
\r
299 ch->anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
\r
300 } else if (is_spine_9288(node)) {
\r
301 ch->chassistype = ISR9288_CT;
\r
302 ch->slotnum = spine12_slot_2_slb[lineport->portnum];
\r
303 ch->anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
\r
304 } else if (is_spine_2012(node)) {
\r
305 ch->chassistype = ISR2012_CT;
\r
306 ch->slotnum = spine12_slot_2_slb[lineport->portnum];
\r
307 ch->anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
\r
308 } else if (is_spine_2004(node)) {
\r
309 ch->chassistype = ISR2004_CT;
\r
310 ch->slotnum = spine4_slot_2_slb[lineport->portnum];
\r
311 ch->anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
\r
313 IBPANIC("Unexpected node found: guid 0x%016" PRIx64, node->nodeguid);
\r
317 static void get_router_slot(Node *node, Port *spineport)
\r
319 ChassisRecord *ch = node->chrecord;
\r
323 if (!(node->chrecord = calloc(1, sizeof(ChassisRecord))))
\r
324 IBPANIC("out of mem");
\r
325 ch = node->chrecord;
\r
328 ch->chassisslot = SRBD_CS;
\r
329 if (is_spine_9096(spineport->node)) {
\r
330 ch->chassistype = ISR9096_CT;
\r
331 ch->slotnum = line_slot_2_sfb4[spineport->portnum];
\r
332 ch->anafanum = ipr_slot_2_sfb4_port[spineport->portnum];
\r
333 } else if (is_spine_9288(spineport->node)) {
\r
334 ch->chassistype = ISR9288_CT;
\r
335 ch->slotnum = line_slot_2_sfb12[spineport->portnum];
\r
336 /* this is a smart guess based on nodeguids order on sFB-12 module */
\r
337 guessnum = spineport->node->nodeguid % 4;
\r
338 /* module 1 <--> remote anafa 3 */
\r
339 /* module 2 <--> remote anafa 2 */
\r
340 /* module 3 <--> remote anafa 1 */
\r
341 ch->anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2));
\r
342 } else if (is_spine_2012(spineport->node)) {
\r
343 ch->chassistype = ISR2012_CT;
\r
344 ch->slotnum = line_slot_2_sfb12[spineport->portnum];
\r
345 /* this is a smart guess based on nodeguids order on sFB-12 module */
\r
346 guessnum = spineport->node->nodeguid % 4;
\r
347 // module 1 <--> remote anafa 3
\r
348 // module 2 <--> remote anafa 2
\r
349 // module 3 <--> remote anafa 1
\r
350 ch->anafanum = (guessnum == 3? 1 : (guessnum == 1 ? 3 : 2));
\r
351 } else if (is_spine_2004(spineport->node)) {
\r
352 ch->chassistype = ISR2004_CT;
\r
353 ch->slotnum = line_slot_2_sfb4[spineport->portnum];
\r
354 ch->anafanum = ipr_slot_2_sfb4_port[spineport->portnum];
\r
356 IBPANIC("Unexpected node found: guid 0x%016" PRIx64, spineport->node->nodeguid);
\r
360 static void get_slb_slot(ChassisRecord *ch, Port *spineport)
\r
362 ch->chassisslot = LINE_CS;
\r
363 if (is_spine_9096(spineport->node)) {
\r
364 ch->chassistype = ISR9096_CT;
\r
365 ch->slotnum = line_slot_2_sfb4[spineport->portnum];
\r
366 ch->anafanum = anafa_line_slot_2_sfb4[spineport->portnum];
\r
367 } else if (is_spine_9288(spineport->node)) {
\r
368 ch->chassistype = ISR9288_CT;
\r
369 ch->slotnum = line_slot_2_sfb12[spineport->portnum];
\r
370 ch->anafanum = anafa_line_slot_2_sfb12[spineport->portnum];
\r
371 } else if (is_spine_2012(spineport->node)) {
\r
372 ch->chassistype = ISR2012_CT;
\r
373 ch->slotnum = line_slot_2_sfb12[spineport->portnum];
\r
374 ch->anafanum = anafa_line_slot_2_sfb12[spineport->portnum];
\r
375 } else if (is_spine_2004(spineport->node)) {
\r
376 ch->chassistype = ISR2004_CT;
\r
377 ch->slotnum = line_slot_2_sfb4[spineport->portnum];
\r
378 ch->anafanum = anafa_line_slot_2_sfb4[spineport->portnum];
\r
380 IBPANIC("Unexpected node found: guid 0x%016" PRIx64, spineport->node->nodeguid);
\r
385 This function called for every Voltaire node in fabric
\r
386 It could be optimized so, but time overhead is very small
\r
387 and its only diag.util
\r
389 static void fill_chassis_record(Node *node)
\r
393 ChassisRecord *ch = 0;
\r
395 if (node->chrecord) /* somehow this node has already been passed */
\r
398 if (!(node->chrecord = calloc(1, sizeof(ChassisRecord))))
\r
399 IBPANIC("out of mem");
\r
401 ch = node->chrecord;
\r
403 /* node is router only in case of using unique lid */
\r
404 /* (which is lid of chassis router port) */
\r
405 /* in such case node->ports is actually a requested port... */
\r
406 if (is_router(node) && is_spine(node->ports->remoteport->node))
\r
407 get_router_slot(node, node->ports->remoteport);
\r
408 else if (is_spine(node)) {
\r
409 for (port = node->ports; port; port = port->next) {
\r
410 if (!port->remoteport)
\r
412 remnode = port->remoteport->node;
\r
413 if (remnode->type != SWITCH_NODE) {
\r
414 if (!remnode->chrecord)
\r
415 get_router_slot(remnode, port);
\r
418 if (!ch->chassistype)
\r
419 /* we assume here that remoteport belongs to line */
\r
420 get_sfb_slot(node, port->remoteport);
\r
422 /* we could break here, but need to find if more routers connected */
\r
425 } else if (is_line(node)) {
\r
426 for (port = node->ports; port; port = port->next) {
\r
427 if (port->portnum > 12)
\r
429 if (!port->remoteport)
\r
431 /* we assume here that remoteport belongs to spine */
\r
432 get_slb_slot(ch, port->remoteport);
\r
440 static int get_line_index(Node *node)
\r
442 int retval = 3 * (node->chrecord->slotnum - 1) + node->chrecord->anafanum;
\r
444 if (retval > LINES_MAX_NUM || retval < 1)
\r
445 IBPANIC("Internal error");
\r
449 static int get_spine_index(Node *node)
\r
453 if (is_spine_9288(node) || is_spine_2012(node))
\r
454 retval = 3 * (node->chrecord->slotnum - 1) + node->chrecord->anafanum;
\r
456 retval = node->chrecord->slotnum;
\r
458 if (retval > SPINES_MAX_NUM || retval < 1)
\r
459 IBPANIC("Internal error");
\r
463 static void insert_line_router(Node *node, ChassisList *chassislist)
\r
465 int i = get_line_index(node);
\r
467 if (chassislist->linenode[i])
\r
468 return; /* already filled slot */
\r
470 chassislist->linenode[i] = node;
\r
471 node->chrecord->chassisnum = chassislist->chassisnum;
\r
474 static void insert_spine(Node *node, ChassisList *chassislist)
\r
476 int i = get_spine_index(node);
\r
478 if (chassislist->spinenode[i])
\r
479 return; /* already filled slot */
\r
481 chassislist->spinenode[i] = node;
\r
482 node->chrecord->chassisnum = chassislist->chassisnum;
\r
485 static void pass_on_lines_catch_spines(ChassisList *chassislist)
\r
487 Node *node, *remnode;
\r
491 for (i = 1; i <= LINES_MAX_NUM; i++) {
\r
492 node = chassislist->linenode[i];
\r
494 if (!(node && is_line(node)))
\r
495 continue; /* empty slot or router */
\r
497 for (port = node->ports; port; port = port->next) {
\r
498 if (port->portnum > 12)
\r
501 if (!port->remoteport)
\r
503 remnode = port->remoteport->node;
\r
505 if (!remnode->chrecord)
\r
506 continue; /* some error - spine not initialized ? FIXME */
\r
507 insert_spine(remnode, chassislist);
\r
512 static void pass_on_spines_catch_lines(ChassisList *chassislist)
\r
514 Node *node, *remnode;
\r
518 for (i = 1; i <= SPINES_MAX_NUM; i++) {
\r
519 node = chassislist->spinenode[i];
\r
521 continue; /* empty slot */
\r
522 for (port = node->ports; port; port = port->next) {
\r
523 if (!port->remoteport)
\r
525 remnode = port->remoteport->node;
\r
527 if (!remnode->chrecord)
\r
528 continue; /* some error - line/router not initialized ? FIXME */
\r
529 insert_line_router(remnode, chassislist);
\r
535 Stupid interpolation algorithm...
\r
536 But nothing to do - have to be compliant with VoltaireSM/NMS
\r
538 static void pass_on_spines_interpolate_chguid(ChassisList *chassislist)
\r
543 for (i = 1; i <= SPINES_MAX_NUM; i++) {
\r
544 node = chassislist->spinenode[i];
\r
546 continue; /* skip the empty slots */
\r
548 /* take first guid minus one to be consistent with SM */
\r
549 chassislist->chassisguid = node->nodeguid - 1;
\r
555 This function fills chassislist structure with all nodes
\r
557 chassislist structure = structure of one standalone chassis
\r
559 static void build_chassis(Node *node, ChassisList *chassislist)
\r
564 /* we get here with node = chassis_spine */
\r
565 chassislist->chassistype = node->chrecord->chassistype;
\r
566 insert_spine(node, chassislist);
\r
568 /* loop: pass on all ports of node */
\r
569 for (port = node->ports; port; port = port->next) {
\r
570 if (!port->remoteport)
\r
572 remnode = port->remoteport->node;
\r
574 if (!remnode->chrecord)
\r
575 continue; /* some error - line or router not initialized ? FIXME */
\r
577 insert_line_router(remnode, chassislist);
\r
580 pass_on_lines_catch_spines(chassislist);
\r
581 /* this pass needed for to catch routers, since routers connected only */
\r
582 /* to spines in slot 1 or 4 and we could miss them first time */
\r
583 pass_on_spines_catch_lines(chassislist);
\r
585 /* additional 2 passes needed for to overcome a problem of pure "in-chassis" */
\r
586 /* connectivity - extra pass to ensure that all related chips/modules */
\r
587 /* inserted into the chassislist */
\r
588 pass_on_lines_catch_spines(chassislist);
\r
589 pass_on_spines_catch_lines(chassislist);
\r
590 pass_on_spines_interpolate_chguid(chassislist);
\r
593 /*========================================================*/
\r
594 /* INTERNAL TO EXTERNAL PORT MAPPING */
\r
595 /*========================================================*/
\r
598 Description : On ISR9288/9096 external ports indexing
\r
599 is not matching the internal ( anafa ) port
\r
600 indexes. Use this MAP to translate the data you get from
\r
601 the OpenIB diagnostics (smpquery, ibroute, ibtracert, etc.)
\r
606 ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24
\r
607 int port | 22 23 24 18 17 16 | 22 23 24 18 17 16
\r
608 ext port | 1 2 3 4 5 6 | 7 8 9 10 11 12
\r
609 int port | 19 20 21 15 14 13 | 19 20 21 15 14 13
\r
610 ------------------------------------------------
\r
614 ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24
\r
615 int port | 24 23 22 18 17 16 | 24 23 22 18 17 16
\r
616 ext port | 1 2 3 4 5 6 | 7 8 9 10 11 12
\r
617 int port | 21 20 19 15 14 13 | 21 20 19 15 14 13
\r
621 ext port | - - 5 - - 6 | - - 7 - - 8
\r
622 int port | 24 23 22 18 17 16 | 24 23 22 18 17 16
\r
623 ext port | - - 1 - - 2 | - - 3 - - 4
\r
624 int port | 21 20 19 15 14 13 | 21 20 19 15 14 13
\r
625 ------------------------------------------------
\r
629 ext port | 13 14 15 16 17 18 19 20 21 22 23 24
\r
630 A1 int port| 13 14 15 16 17 18 19 20 21 22 23 24
\r
631 ext port | 1 2 3 4 5 6 7 8 9 10 11 12
\r
632 A2 int port| 13 14 15 16 17 18 19 20 21 22 23 24
\r
633 ---------------------------------------------------
\r
637 int int2ext_map_slb24[2][25] = {
\r
638 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 4, 18, 17, 16, 1, 2, 3, 13, 14, 15 },
\r
639 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 11, 10, 24, 23, 22, 7, 8, 9, 19, 20, 21 }
\r
641 int int2ext_map_slb8[2][25] = {
\r
642 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 1, 1, 1, 5, 5, 5 },
\r
643 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 3, 3, 3, 7, 7, 7 }
\r
645 int int2ext_map_slb2024[2][25] = {
\r
646 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 },
\r
647 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
\r
649 /* 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 }; */
\r
652 This function relevant only for line modules/chips
\r
653 Returns string with external port index
\r
655 char *portmapstring(Port *port)
\r
657 static char mapping[OUT_BUFFER_SIZE];
\r
658 ChassisRecord *ch = port->node->chrecord;
\r
659 int portnum = port->portnum;
\r
662 Node *node = port->node;
\r
664 if (!ch || !is_line(node) || (portnum < 13 || portnum > 24))
\r
667 if (ch->anafanum < 1 || ch->anafanum > 2)
\r
670 memset(mapping, 0, sizeof(mapping));
\r
672 chipnum = ch->anafanum - 1;
\r
674 if (is_line_24(node))
\r
675 pindex = int2ext_map_slb24[chipnum][portnum];
\r
676 else if (is_line_2024(node))
\r
677 pindex = int2ext_map_slb2024[chipnum][portnum];
\r
679 pindex = int2ext_map_slb8[chipnum][portnum];
\r
681 sprintf(mapping, "[ext %d]", pindex);
\r
686 static void add_chassislist()
\r
688 if (!(mylist.current = calloc(1, sizeof(ChassisList))))
\r
689 IBPANIC("out of mem");
\r
691 if (mylist.first == NULL) {
\r
692 mylist.first = mylist.current;
\r
693 mylist.last = mylist.current;
\r
695 mylist.last->next = mylist.current;
\r
696 mylist.current->next = NULL;
\r
697 mylist.last = mylist.current;
\r
702 Main grouping function
\r
704 1. pass on every Voltaire node
\r
705 2. catch spine chip for every Voltaire node
\r
706 2.1 build/interpolate chassis around this chip
\r
708 3. pass on non Voltaire nodes (SystemImageGUID based grouping)
\r
709 4. now group non Voltaire nodes by SystemImageGUID
\r
711 ChassisList *group_nodes()
\r
715 int chassisnum = 0;
\r
716 struct ChassisList *chassis;
\r
718 mylist.first = NULL;
\r
719 mylist.current = NULL;
\r
720 mylist.last = NULL;
\r
722 /* first pass on switches and build for every Voltaire node */
\r
723 /* an appropriate chassis record (slotnum and position) */
\r
724 /* according to internal connectivity */
\r
725 /* not very efficient but clear code so... */
\r
726 for (dist = 0; dist <= maxhops_discovered; dist++) {
\r
727 for (node = nodesdist[dist]; node; node = node->dnext) {
\r
728 if (node->vendid == VTR_VENDOR_ID)
\r
729 fill_chassis_record(node);
\r
733 /* separate every Voltaire chassis from each other and build linked list of them */
\r
734 /* algorithm: catch spine and find all surrounding nodes */
\r
735 for (dist = 0; dist <= maxhops_discovered; dist++) {
\r
736 for (node = nodesdist[dist]; node; node = node->dnext) {
\r
737 if (node->vendid != VTR_VENDOR_ID)
\r
739 if (!node->chrecord || node->chrecord->chassisnum || !is_spine(node))
\r
742 mylist.current->chassisnum = ++chassisnum;
\r
743 build_chassis(node, mylist.current);
\r
747 /* now make pass on nodes for chassis which are not Voltaire */
\r
748 /* grouped by common SystemImageGUID */
\r
749 for (dist = 0; dist <= maxhops_discovered; dist++) {
\r
750 for (node = nodesdist[dist]; node; node = node->dnext) {
\r
751 if (node->vendid == VTR_VENDOR_ID)
\r
753 if (node->sysimgguid) {
\r
754 chassis = find_chassisguid(node);
\r
756 chassis->nodecount++;
\r
758 /* Possible new chassis */
\r
760 mylist.current->chassisguid = get_chassisguid(node);
\r
761 mylist.current->nodecount = 1;
\r
767 /* now, make another pass to see which nodes are part of chassis */
\r
768 /* (defined as chassis->nodecount > 1) */
\r
769 for (dist = 0; dist <= MAXHOPS; ) {
\r
770 for (node = nodesdist[dist]; node; node = node->dnext) {
\r
771 if (node->vendid == VTR_VENDOR_ID)
\r
773 if (node->sysimgguid) {
\r
774 chassis = find_chassisguid(node);
\r
775 if (chassis && chassis->nodecount > 1) {
\r
776 if (!chassis->chassisnum)
\r
777 chassis->chassisnum = ++chassisnum;
\r
778 if (!node->chrecord) {
\r
779 if (!(node->chrecord = calloc(1, sizeof(ChassisRecord))))
\r
780 IBPANIC("out of mem");
\r
781 node->chrecord->chassisnum = chassis->chassisnum;
\r
786 if (dist == maxhops_discovered)
\r
787 dist = MAXHOPS; /* skip to CAs */
\r
792 return (mylist.first);
\r