2
* Copyright (c) 2004 Mellanox Technologies LTD. All rights reserved.
4
* This software is available to you under a choice of one of two
5
* licenses. You may choose to be licensed under the terms of the GNU
6
* General Public License (GPL) Version 2, available from the file
7
* COPYING in the main directory of this source tree, or the
8
* OpenIB.org BSD license below:
10
* Redistribution and use in source and binary forms, with or
11
* without modification, are permitted provided that the following
14
* - Redistributions of source code must retain the above
15
* copyright notice, this list of conditions and the following
18
* - Redistributions in binary form must reproduce the above
19
* copyright notice, this list of conditions and the following
20
* disclaimer in the documentation and/or other materials
21
* provided with the distribution.
23
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37
This file holds implementation of the data model classes and methods
41
//////////////////////////////////////////////////////////////////////////////
48
#include "git_version.h"
51
uint8_t FabricUtilsVerboseLevel = 0x1;
54
streambuf *ibdmCoutBuf;
56
int ibdmUseInternalLog() {
57
streambuf *psbuf = ibdmLog.rdbuf();
58
ibdmCoutBuf = cout.rdbuf(psbuf);
62
int ibdmUseCoutLog() {
63
cout.rdbuf(ibdmCoutBuf);
67
char *ibdmGetAndClearInternalLog() {
69
cout.rdbuf(ibdmCoutBuf);
70
res = (char*)malloc(ibdmLog.str().length() + 1);
71
strcpy(res, ibdmLog.str().c_str());
77
//////////////////////////////////////////////////////////////////////////////
83
IBPort::IBPort(IBNode *p_nodePtr, int number) {
88
base_lid = IB_LID_UNASSIGNED;
89
memset(&guid,0,sizeof(uint64_t));
96
if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
98
cout << "-I- Destructing Port:" << p_node->name << "/" << num << endl;
101
// if was connected - remove the connection:
103
p_remotePort->p_remotePort = NULL;
105
// if has a system port - delete it too.
108
p_sysPort->p_nodePort = NULL;
113
// Set the guid in the fabric too:
114
void IBPort::guid_set(uint64_t g) {
115
if (p_node && p_node->p_fabric)
117
p_node->p_fabric->PortByGuid[g] = this;
122
// Get the port name.
123
// If connects to a system port - use the system port name.
129
name = p_sysPort->p_system->name + string("/") + p_sysPort->name;
135
cerr << "Got a port with no node" << endl;
139
sprintf(buff,"/P%u", num);
140
name = p_node->name + string(buff);
145
// connect the port to another node port
147
IBPort::connect (IBPort *p_otherPort,
151
// we can not simply override existing connections
154
// we only do care if not the requested remote previously conn.
155
if (p_remotePort != p_otherPort)
157
cout << "-W- Disconnecting: "
158
<< p_remotePort->getName() << " previously connected to:"
159
<< p_remotePort->getName()
160
<< " while connecting:" << p_otherPort->getName() << endl;
161
// the other side should be cleaned only if points here
162
if (p_remotePort->p_remotePort == this)
164
p_remotePort->p_remotePort = NULL;
168
p_remotePort = p_otherPort;
170
// Check the other side was not previously connected
171
if (p_otherPort->p_remotePort)
173
if (p_otherPort->p_remotePort != this)
175
// it was connected to a wrong port so disconnect
176
cout << "-W- Disconnecting: " << p_otherPort->getName()
177
<< " previously connected to:"
178
<< p_otherPort->p_remotePort->getName()
179
<< " while connecting:" << this->getName() << endl;
180
// the other side should be cleaned only if points here
181
if (p_otherPort->p_remotePort->p_remotePort == p_otherPort)
183
p_otherPort->p_remotePort->p_remotePort = NULL;
187
p_otherPort->p_remotePort = this;
189
p_remotePort->speed = speed = s;
190
p_remotePort->width = width = w;
193
// disconenct two ports
195
IBPort::disconnect(int duringSysPortDisconnect)
199
cout << "-W- Trying to disconenct non connected port." << endl;
203
if (p_remotePort->p_remotePort != this)
206
<< "-W- Remote port does not point back! Disconnecting self only."
211
IBPort *p_remPort = p_remotePort;
212
p_remotePort->p_remotePort = NULL;
214
if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
215
cout << "-I- Disconnected port:" << getName()
216
<< " from:" << p_remPort->getName() << endl;
218
// might need to treat the sys port too - but mark it duringPortDisconenct
219
if (p_sysPort && ! duringSysPortDisconnect)
220
return(p_sysPort->disconnect(1));
225
//////////////////////////////////////////////////////////////////////////////
231
IBNode::IBNode(string n,
234
IBNodeType t, int np) {
241
rank = IBNODE_UNASSIGNED_RANK;
242
attributes = string("");
245
for (unsigned int i = 0; i < numPorts; i++)
246
Ports.push_back((IBPort *)NULL);
248
p_system->NodeByName[name] = this;
249
p_fabric->NodeByName[name] = this;
252
// Delete the node cleaning up all it's connections
254
if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
256
cout << "-I- Destructing Node:" << name << endl;
258
// delete all the node ports:
260
for (p = 0; p < numPorts; p++) {
261
IBPort *p_port = Ports[p];
268
// remove from the system NodesByName:
271
map_str_pnode::iterator nI = p_system->NodeByName.find(name);
272
if (nI != p_system->NodeByName.end())
274
p_system->NodeByName.erase(nI);
278
// remove from the fabric NodesByName:
281
map_str_pnode::iterator nI = p_fabric->NodeByName.find(name);
282
if (nI != p_fabric->NodeByName.end())
284
p_fabric->NodeByName.erase(nI);
290
IBNode::guid_set(uint64_t g) {
293
p_fabric->NodeByGuid[g] = this;
298
// Set the min hop for the given port (* is all) lid pair
300
IBNode::setHops (IBPort *p_port, unsigned int lid, int hops) {
301
if (MinHopsTable.empty())
303
if (lid > p_fabric->maxLid)
305
cout << "-W- We got a bigget lid:" << lid
306
<< " then maxLid:" << p_fabric->maxLid << endl;
307
p_fabric->maxLid = lid;
310
// we allocate the complete table upfront
311
MinHopsTable.resize(p_fabric->maxLid + 1);
312
for(unsigned int l = 0; l < p_fabric->maxLid + 1; l++) {
313
MinHopsTable[l].resize(numPorts + 1);
314
for(unsigned int i = 0; i <= numPorts; i++)
315
MinHopsTable[l][i] = IB_HOP_UNASSIGNED;
320
// if we were not passed a port do it for all!
321
// only if lid is legal , otherwise the user meant ,just to init the
322
// table with IB_HOP_UNASSIGNED
327
// set it for all ports
328
for(unsigned int i = 0; i <= numPorts; i++)
329
MinHopsTable[lid][i] = hops;
333
MinHopsTable[lid][p_port->num] = hops;
338
for (unsigned int l = 0; l < MinHopsTable.size(); l++)
339
for(unsigned int i = 0; i <= numPorts; i++)
340
MinHopsTable[l][i] = hops;
343
// keep track about the min hops per node:
344
if (MinHopsTable[lid][0] > hops)
345
MinHopsTable[lid][0] = hops;
348
// Report Min Hop Table of the current Node
350
IBNode::repHopTable () {
351
cout << "-I- MinHopTable for Node:" << name << "\n"
352
<< "=========================\n" <<endl;
353
if (MinHopsTable.empty())
355
cout << "\tEmpty" << endl;
359
cout << " " << setw(3) << "MIN" << " ";
360
// Lid/Port header line
361
for (int i=1; i <= Ports.size(); i++)
362
cout << setw(2) << i << " " ;
364
for (int i = 1; i <= 3*Ports.size()+5; i++) cout << "-";
366
for (int l = 1; l <= p_fabric->maxLid; l++)
368
cout << setw(2) << l << "|";
369
for (int i=0; i <= Ports.size(); i++)
371
int val=(int)MinHopsTable[l][i];
373
cout << setw(2) << val << " " ;
375
cout << setw(2) << "-" << " " ;
377
IBPort *p_port = p_fabric->getPortByLid(l);
379
cout << " " << p_port->p_node->name;
384
} // Method repHopTable
389
//////////////////////////////////////////////////////////////////////////////
391
// Get the min number of hops defined for the given port or all
393
IBNode::getHops (IBPort *p_port, unsigned int lid) {
394
// make sure it is initialized:
395
if (MinHopsTable.empty() || (MinHopsTable.size() < lid + 1))
396
return IB_HOP_UNASSIGNED;
397
if (MinHopsTable[lid].empty()) return IB_HOP_UNASSIGNED;
398
if (p_port == NULL) return MinHopsTable[lid][0];
399
return MinHopsTable[lid][p_port->num];
402
//////////////////////////////////////////////////////////////////////////////
404
// Scan the node ports and find the first port
405
// with min hop to the lid
407
IBNode::getFirstMinHopPort(unsigned int lid) {
409
// make sure it is a SW:
410
if (type != IB_SW_NODE)
412
cout << "-E- Get best hop port must be run on SW nodes!" << endl;
416
if (MinHopsTable.empty() || (MinHopsTable.size() < lid + 1))
419
// the best hop is stored in port 0:
420
int minHop = MinHopsTable[lid][0];
421
for (unsigned int i = 1; i <= numPorts; i++)
422
if (MinHopsTable[lid][i] == minHop)
427
//////////////////////////////////////////////////////////////////////////////
429
// Set the Linear Forwarding Table:
431
IBNode::setLFTPortForLid (unsigned int lid, unsigned int portNum) {
432
unsigned int origSize = LFT.empty() ? 0 : LFT.size();
433
// make sur the vector is init
434
if (origSize < lid + 1)
436
LFT.resize(lid + 100);
438
for(unsigned int i = origSize; i < LFT.size(); i++)
439
LFT[i] = IB_LFT_UNASSIGNED;
446
//////////////////////////////////////////////////////////////////////////////
448
// Get the LFT for a given lid
450
IBNode::getLFTPortForLid (unsigned int lid) {
451
// make sure it is initialized:
452
if (LFT.empty() || (LFT.size() < lid + 1)) return IB_LFT_UNASSIGNED;
456
//////////////////////////////////////////////////////////////////////////////
458
// Set the PSL Table:
460
IBNode::setPSLForLid (unsigned int lid, unsigned int maxLid, uint8_t sl) {
463
PSL.resize(maxLid + 1);
464
for(unsigned int i = 0; i<PSL.size(); i++)
465
PSL[i] = IB_SLT_UNASSIGNED;
470
//////////////////////////////////////////////////////////////////////////////
472
// Get the PSL Table:
474
IBNode::getPSLForLid (unsigned int lid) {
478
if (PSL.size() < lid+1)
479
return IB_SLT_UNASSIGNED;
484
//////////////////////////////////////////////////////////////////////////////
486
// Set the SL2VL Table:
488
IBNode::setSLVL (unsigned int iport,unsigned int oport,uint8_t sl, uint8_t vl) {
489
// Create an empty table
492
SLVL.resize(numPorts+1);
493
for (int i=0;i<SLVL.size();i++) {
494
SLVL[i].resize(numPorts+1);
495
for (int j=0;j<SLVL[i].size();j++) {
496
SLVL[i][j].resize(IB_NUM_SL);
497
for (int k=0;k<SLVL[i][j].size();k++)
498
SLVL[i][j][k] = IB_SLT_UNASSIGNED;
502
SLVL[iport][oport][sl] = vl;
505
//////////////////////////////////////////////////////////////////////////////
507
// Get the SLVL Table:
509
IBNode::getSLVL (unsigned int iport,unsigned int oport,uint8_t sl) {
514
return SLVL[iport][oport][sl];
517
//////////////////////////////////////////////////////////////////////////////
518
// Set the Multicast FDB table
520
IBNode::setMFTPortForMLid(
522
unsigned int portNum)
524
if ((portNum > numPorts) || (portNum >= 64))
526
cout << "-E- setMFTPortForMLid : Given port:" << portNum
527
<< " is too high!" << endl;
531
// make sure the mlid is in range:
532
if ((lid < 0xc000) || (lid > 0xffff))
534
cout << "-E- setMFTPortForMLid : Given lid:" << lid
535
<< " is out of range" << endl;
539
int idx = lid - 0xc000;
541
// make sure we have enough vector:
542
int prevSize = MFT.size();
545
MFT.resize(idx + 10);
546
for( int i = prevSize; i < idx + 10; i++)
550
MFT[idx] |= (((uint64_t)1) << portNum);
552
// we track all Groups:
553
p_fabric->mcGroups.insert(lid);
557
//////////////////////////////////////////////////////////////////////////////
558
// Get the list of ports for the givan MLID from the MFT
560
IBNode::getMFTPortsForMLid(
564
// make sure the mlid is in range:
565
if ((lid < 0xc000) || (lid > 0xffff))
567
cout << "-E- getMFTPortsForMLid : Given lid:" << lid
568
<< " is out of range" << endl;
572
int idx = lid - 0xc000;
573
if (MFT.size() <= idx)
576
uint64_t mftVal = MFT[idx];
577
for(unsigned int pn = 0; pn <= numPorts; pn++)
578
if (mftVal & (((uint64_t)1) << pn)) res.push_back(pn);
583
//////////////////////////////////////////////////////////////////////////////
588
// Connect two system ports. This will update both sides pointers
590
IBSysPort::connect (IBSysPort *p_otherSysPort,
594
// we can not simply override existing connections
597
// we only do care if not the requested remote previously conn.
598
if (p_remoteSysPort != p_otherSysPort)
600
cout << "-W- Disconnecting system port: " << p_system->name << "-/"
601
<< this->name << " previously connected to:"
602
<< p_remoteSysPort->p_system->name << "-/"
603
<< p_remoteSysPort->name
604
<< " while connecting:" << p_otherSysPort->p_system->name
605
<< "-/" << p_otherSysPort->name << endl;
606
// the other side should be cleaned only if points here
607
if (p_remoteSysPort->p_remoteSysPort == this)
609
p_remoteSysPort->p_remoteSysPort = NULL;
613
p_remoteSysPort = p_otherSysPort;
615
// Check the other side was not previously connected
616
if (p_otherSysPort->p_remoteSysPort)
618
if (p_otherSysPort->p_remoteSysPort != this)
620
// it was connected to a wrong port so disconnect
621
cout << "-W- Disconnecting system port back: "
622
<< p_otherSysPort->p_system->name << "-/"
623
<< p_otherSysPort->name << " previously connected to:"
624
<< p_otherSysPort->p_remoteSysPort->p_system->name << "-/"
625
<< p_otherSysPort->p_remoteSysPort->name
626
<< " while connecting:" << this->p_system->name
627
<< "-/" << this->name << endl;
628
// the other side should be cleaned only if points here
629
if (p_otherSysPort->p_remoteSysPort->p_remoteSysPort == p_otherSysPort)
631
p_otherSysPort->p_remoteSysPort->p_remoteSysPort = NULL;
635
p_otherSysPort->p_remoteSysPort = this;
637
// there should be a lower level port to connect too:
638
if (p_remoteSysPort->p_nodePort && p_nodePort)
639
p_nodePort->connect(p_remoteSysPort->p_nodePort, width, speed);
641
cout << "-E- Connected sys ports but no nodes ports:"
642
<< p_system->name << "/" << name << " - "
643
<< p_remoteSysPort->p_system->name << "/"
644
<< p_remoteSysPort->name << endl;
648
IBSysPort::disconnect(int duringPortDisconnect)
650
if (!p_remoteSysPort)
652
cout << "-W- Trying to disconenct non connected system port." << endl;
656
if (p_remoteSysPort->p_remoteSysPort != this)
659
<< "-W- Remote port does not point back! Disconnecting self only."
661
p_remoteSysPort = NULL;
665
IBSysPort *p_remSysPort = p_remoteSysPort;
666
p_remoteSysPort->p_remoteSysPort = NULL;
667
p_remoteSysPort = NULL;
668
if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
669
cout << "-I- Disconnected system port:" << name
670
<< " from:" << p_remSysPort->name << endl;
672
// might need to treat the port too - but mark it duringPortDisconenct
673
if (p_nodePort && ! duringPortDisconnect) return(p_nodePort->disconnect(1));
679
IBSysPort::IBSysPort(string n, class IBSystem *p_sys)
684
p_remoteSysPort = NULL;
685
p_system->PortByName[name] = this;
689
IBSysPort::~IBSysPort() {
690
if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
692
cout << "-I- Destructing SysPort:" << name << endl;
695
// if connected to another side remove the connection
697
p_remoteSysPort->p_remoteSysPort = NULL;
699
// remove from the map of the parent system
702
map_str_psysport::iterator pI = p_system->PortByName.find(name);
703
if (pI != p_system->PortByName.end())
705
p_system->PortByName.erase(pI);
710
//////////////////////////////////////////////////////////////////////////////
716
IBSystem::~IBSystem() {
717
if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
718
cout << "-I- Destructing System:" << name << endl;
720
// cleanup all allocated sysPorts:
721
while (!PortByName.empty()) {
722
map_str_psysport::iterator pI = PortByName.begin();
723
// deleting a SysPort should cleanup the table
724
IBSysPort *p_sysPort = (*pI).second;
731
// cleanup from parent fabric table of systems:
734
map_str_psys::iterator sI = p_fabric->SystemByName.find(name);
735
if (sI != p_fabric->SystemByName.end())
736
p_fabric->SystemByName.erase(sI);
740
// make sure we got the port defined
742
IBSystem::makeSysPort (string pName) {
744
map_str_psysport::iterator pI = PortByName.find(pName);
745
if (pI == PortByName.end())
747
p_port = new IBSysPort(pName, this);
748
if (!p_port) return NULL;
749
PortByName[pName] = p_port;
753
p_port = (*pI).second;
755
// connect the SysPort to the lower level nodes
756
IBPort *p_nodePort = getSysPortNodePortByName(pName);
757
if (! p_nodePort) return NULL;
758
p_nodePort->p_sysPort = p_port;
759
p_port->p_nodePort = p_nodePort;
763
//////////////////////////////////////////////////////////////////////////////
765
IBSystem::guid_set(uint64_t g) {
768
p_fabric->SystemByGuid[g] = this;
773
//////////////////////////////////////////////////////////////////////////////
776
IBSystem::getSysPort(string name) {
777
IBSysPort *p_sysPort = NULL;
778
map_str_psysport::iterator nI = PortByName.find(name);
779
if (nI != PortByName.end())
781
p_sysPort = (*nI).second;
786
//////////////////////////////////////////////////////////////////////////////
789
IBSystem::IBSystem(string n, class IBFabric *p_fab, string t) {
790
if (p_fab->getSystem(n))
792
cerr << "Can't deal with double allocation of same system!" << endl;
799
p_fabric->SystemByName[n] = this;
802
//////////////////////////////////////////////////////////////////////////////
804
// Get a string with all the System Port Names (even if not connected)
806
IBSystem::getAllSysPortNames() {
808
for (map_str_psysport::iterator pI = PortByName.begin();
809
pI != PortByName.end();
811
portNames.push_back((*pI).first);
816
//////////////////////////////////////////////////////////////////////////////
818
// get the node port for the given sys port by name
820
IBSystem::getSysPortNodePortByName (string sysPortName) {
821
map_str_psysport::iterator pI = PortByName.find(sysPortName);
822
if (pI != PortByName.end())
824
return ((*pI).second)->p_nodePort;
828
//////////////////////////////////////////////////////////////////////////////
830
// Split the given cfg into a vector of board cfg codes
832
IBSystem::cfg2Vector(const string& cfg,
833
vector<string>& boardCfgs,
838
unsigned int prevDelim = 0;
839
const char *p_str = cfg.c_str();
842
// skip leading spaces:
843
for (i = 0; (i < strlen(p_str)) && (
844
(p_str[i] == '\t') || (p_str[i] == ' ')); i++);
847
// scan each character:
848
for (; (i < strlen(p_str)) && (b < numBoards); i++) {
849
// either a delimiter or not:
852
strncpy(bcfg, p_str + prevDelim, i - prevDelim);
853
bcfg[i - prevDelim] = '\0';
854
boardCfgs.push_back(string(bcfg));
862
strncpy(bcfg, p_str + prevDelim, i - prevDelim);
863
bcfg[i - prevDelim] = '\0';
864
boardCfgs.push_back(string(bcfg));
868
for (;b < numBoards; b++) {
869
boardCfgs.push_back("");
873
//////////////////////////////////////////////////////////////////////////////
875
// Remove a system board
877
IBSystem::removeBoard (string boardName) {
878
list <IBNode *> matchedNodes;
879
// we assume system name is followed by "/" by board to get the node name:
880
string sysNodePrefix = name + string("/") + boardName + string("/");
882
// go through all the system nodes.
883
for (map_str_pnode::iterator nI = p_fabric->NodeByName.begin();
884
nI != p_fabric->NodeByName.end();
886
// if node name start matches the module name - we need to remove it.
887
if (!strncmp((*nI).first.c_str(), sysNodePrefix.c_str(),
888
strlen(sysNodePrefix.c_str())))
890
matchedNodes.push_back((*nI).second);
895
if (matchedNodes.empty())
897
cout << "-W- removeBoard : Fail to find any node in:"
898
<< sysNodePrefix << " while removing:" << boardName << endl;
902
// go through the list of nodes and delete them
903
list <IBNode *>::iterator lI = matchedNodes.begin();
904
while (lI != matchedNodes.end()) {
905
// cleanup the node from the fabric node by name:
906
IBNode *p_node = *lI;
907
// cout << "Removing node:" << p_node->name.c_str() << endl;
908
p_fabric->NodeByName.erase(p_node->name);
910
matchedNodes.erase(lI);
911
lI = matchedNodes.begin();
917
//////////////////////////////////////////////////////////////////////////////
919
// Write out the system IBNL into the given directory
920
// and return the new system type
922
// We are facing here a "heuristic" approach for how one knows
923
// the number of system ports - since some may be added later.
925
// In the case of a single device system we can and should expose
926
// all device ports - simply as P<pn>.
928
// In the case of a combined system we can not tell. Adding new connections
929
// will require regenerating the IBNL (which is by SysGuid anyway)
931
IBSystem::dumpIBNL(char *ibnlDir, string &sysType) {
932
char sysTypeStr[256];
933
// if we got just one node it is simple - write a corresponding IBNL by the
935
if (NodeByName.size() == 1)
937
map_str_pnode::iterator nI = NodeByName.begin();
938
IBNode *p_node = (*nI).second;
939
sprintf(sysTypeStr, "DEV%u", p_node->devId);
943
sprintf(sysTypeStr, "SYS%x", guid);
945
sysType = string(sysTypeStr);
946
string fileName = string(ibnlDir) + string("/") + sysType + string(".ibnl");
948
ibnl.open(fileName.c_str());
952
cout << "-E- Failed to write IBNL into file:" << fileName << endl;
956
ibnl << "TOPSYSTEM " << sysType << endl;
958
// go over all nodes of the system:
959
for (map_str_pnode::iterator nI = NodeByName.begin();
960
nI != NodeByName.end(); nI++) {
961
IBNode *p_node = (*nI).second;
962
string nameWithoutSysName =
963
p_node->name.substr(name.length()+1, p_node->name.length() - name.length() - 1);
964
if (p_node->type == IB_SW_NODE)
966
ibnl << "\nNODE SW " << p_node->numPorts << " "
967
<< "DEV" << p_node->devId << " " << nameWithoutSysName.c_str() << endl;
971
ibnl << "\nNODE CA " << p_node->numPorts << " "
972
<< "DEV" << p_node->devId << " " << nameWithoutSysName.c_str() << endl;
975
for (unsigned int pn = 1; pn <= p_node->numPorts; pn++) {
976
IBPort *p_port = p_node->getPort(pn);
978
if (NodeByName.size() == 1) {
981
sprintf(buf,"%s/P%u", nameWithoutSysName.c_str(), pn);
982
ibnl << " " << pn << " -> " << buf << endl;
984
if (! p_port) continue;
987
if (p_port->p_sysPort)
989
ibnl << " " << pn << " -> "
990
<< p_port->p_sysPort->name << endl;
991
} else if (p_port->p_remotePort) {
992
ibnl << " " << pn << " -"
993
<< width2char(p_port->width)
994
<< "-" << speed2char(p_port->speed) << "G-> "
995
<< p_port->p_remotePort->p_node->name << " "
996
<< p_port->p_remotePort->num << endl;
1005
//////////////////////////////////////////////////////////////////////////////
1011
IBFabric::~IBFabric() {
1012
// cleanup all Systems and Nodes:
1014
// starting with nodes since they point back to their systems
1015
while (! NodeByName.empty()) {
1016
map_str_pnode::iterator nI = NodeByName.begin();
1017
// note this will cleanup the node from the table...
1018
IBNode *p_node = (*nI).second;
1022
// now we do the systems
1023
while (!SystemByName.empty()) {
1024
map_str_psys::iterator sI = SystemByName.begin();
1025
// note this will cleanup the system from the table...
1026
IBSystem *p_sys = (*sI).second;
1031
//////////////////////////////////////////////////////////////////////////////
1036
// make a new node if can not find it by name
1038
IBFabric::makeNode (string n, IBSystem *p_sys, IBNodeType type,
1039
unsigned int numPorts) {
1041
map_str_pnode::iterator nI = NodeByName.find(n);
1042
if (nI == NodeByName.end())
1044
p_node = new IBNode(n, this, p_sys, type, numPorts);
1045
NodeByName[n] = p_node;
1046
// if the node is uniq by name in the fabric it must be uniq in the sys
1047
p_sys->NodeByName[n] = p_node;
1051
p_node = (*nI).second;
1054
// if the fabric require all ports to be declared do it:
1056
for (unsigned int i = 1; i <= numPorts; i++)
1057
p_node->makePort(i);
1062
//////////////////////////////////////////////////////////////////////////////
1064
// Look for the node by its name
1066
IBFabric::getNode (string name) {
1067
IBNode *p_node = NULL;
1068
map_str_pnode::iterator nI = NodeByName.find(name);
1069
if (nI != NodeByName.end())
1071
p_node = (*nI).second;
1076
/////////////////////////////////////////////////////////////////////////////
1079
IBFabric::getPortByGuid (uint64_t guid) {
1080
IBPort *p_port = NULL;
1081
map_guid_pport::iterator nI = PortByGuid.find(guid);
1082
if (nI != PortByGuid.end())
1084
p_port = (*nI).second;
1090
IBFabric::getNodeByGuid (uint64_t guid) {
1091
IBNode *p_node = NULL;
1092
map_guid_pnode::iterator nI = NodeByGuid.find(guid);
1093
if (nI != NodeByGuid.end())
1095
p_node = (*nI).second;
1101
IBFabric::getSystemByGuid (uint64_t guid) {
1102
IBSystem *p_system = NULL;
1103
map_guid_psys::iterator nI = SystemByGuid.find(guid);
1104
if (nI != SystemByGuid.end())
1106
p_system = (*nI).second;
1111
/////////////////////////////////////////////////////////////////////////////
1113
// return the list of node pointers matching the required type
1115
IBFabric::getNodesByType (IBNodeType type) {
1117
list_pnode *res = new list_pnode;
1118
for (map_str_pnode::iterator nI = NodeByName.begin(); nI != NodeByName.end(); nI++) {
1119
if ((type == IB_UNKNOWN_NODE_TYPE) || (type == ((*nI).second)->type))
1121
res->push_back(((*nI).second));
1127
//////////////////////////////////////////////////////////////////////////////
1128
// convert the given configuration string to modifiers list
1129
// The syntax of the modifier string is comma sep board=modifier pairs
1131
cfgStrToModifiers(string cfg, map_str_str &mods) {
1133
unsigned int prevDelim = 0;
1134
const char *p_str = cfg.c_str();
1137
// skip leading spaces:
1138
for (i = 0; (i < strlen(p_str)) && (
1139
(p_str[i] == '\t') || (p_str[i] == ' ')); i++);
1142
// scan each character:
1143
for (;i < strlen(p_str); i++) {
1144
// either a delimiter or not:
1145
if (p_str[i] == ',')
1147
strncpy(bcfg, p_str + prevDelim, i - prevDelim);
1148
bcfg[i - prevDelim] = '\0';
1149
char *eqSign = strchr(bcfg, '=');
1154
string val = ++eqSign;
1159
cout << "-E- Bad modifier syntax:" << bcfg
1160
<< "expected: board=modifier" << endl;
1168
strncpy(bcfg, p_str + prevDelim, i - prevDelim);
1169
bcfg[i - prevDelim] = '\0';
1170
char *eqSign = strchr(bcfg, '=');
1175
string val = ++eqSign;
1180
cout << "-E- Bad modifier syntax:" << bcfg
1181
<< "expected: board=modifier" << endl;
1187
//////////////////////////////////////////////////////////////////////////////
1189
// crate a new generic system - basically an empty contaner for nodes...
1191
IBFabric::makeGenericSystem (string name) {
1195
// make sure we do not previoulsy have this system defined.
1196
map_str_psys::iterator sI = SystemByName.find(name);
1197
if (sI == SystemByName.end())
1199
p_sys = new IBSystem(name,this,"Generic");
1203
p_sys = (*sI).second;
1208
//////////////////////////////////////////////////////////////////////////////
1209
// crate a new system - the type must have a predefined sysdef
1211
IBFabric::makeSystem (string name, string type, string cfg) {
1215
// make sure we do not previoulsy have this system defined.
1216
map_str_psys::iterator sI = SystemByName.find(name);
1217
if (sI == SystemByName.end())
1220
// We base our system building on the system definitions:
1223
// convert the given configuration string to modifiers map
1224
cfgStrToModifiers(cfg, mods);
1226
p_sys = theSysDefsCollection()->makeSystem(this, name, type, mods);
1230
cout << "-E- Fail to find System class:" << type
1235
SystemByName[name] = p_sys;
1237
// if the fabric require all ports to be declared do it:
1240
list_str portNames = p_sys->getAllSysPortNames();
1241
for (list_str::const_iterator pnI = portNames.begin();
1242
pnI != portNames.end();
1244
p_sys->makeSysPort(*pnI);
1250
p_sys = (*sI).second;
1255
//////////////////////////////////////////////////////////////////////////////
1257
// Look for the system by its name
1259
IBFabric::getSystem (string name) {
1260
IBSystem *p_system = NULL;
1261
map_str_psys::iterator nI = SystemByName.find(name);
1262
if (nI != SystemByName.end())
1264
p_system = (*nI).second;
1269
//////////////////////////////////////////////////////////////////////////////
1271
// Add a cable connection
1273
IBFabric::addCable (string t1, string n1, string p1,
1274
string t2, string n2, string p2,
1275
IBLinkWidth width, IBLinkSpeed speed) {
1276
// make sure the nodes exists:
1277
IBSystem *p_sys1 = makeSystem(n1,t1);
1278
IBSystem *p_sys2 = makeSystem(n2,t2);
1281
if (! (p_sys1 && p_sys2))
1283
cout << "-E- Fail to make either systems:" << n1 << " or:"
1289
if (p_sys1->type != t1)
1291
cout << "-W- Provided System1 Type:" << t1
1292
<< " does not match pre-existing system:" << n1
1293
<< " type:" << p_sys1->type << endl;
1296
if (p_sys2->type != t2)
1298
cout << "-W- Provided System1 Type:" << t2
1299
<< " does not match pre-existing system:" << n2
1300
<< " type:" << p_sys2->type << endl;
1303
// make sure the sys ports exists
1304
IBSysPort *p_port1 = p_sys1->makeSysPort(p1);
1305
IBSysPort *p_port2 = p_sys2->makeSysPort(p2);
1306
if (! (p_port1 && p_port2)) return 1;
1308
// make sure they are not previously connected otherwise
1309
if (p_port1->p_remoteSysPort && (p_port1->p_remoteSysPort != p_port2))
1312
<< p_port1->p_system->name << "/"
1314
<< " already connected to:"
1315
<< p_port1->p_remoteSysPort->p_system->name << "/"
1316
<< p_port1->p_remoteSysPort->name <<endl;
1320
if (p_port2->p_remoteSysPort && (p_port2->p_remoteSysPort != p_port1))
1323
<< p_port2->p_system->name << "/"
1325
<< " already connected to:"
1326
<< p_port2->p_remoteSysPort->p_system->name << "/"
1327
<< p_port2->p_remoteSysPort->name << endl;
1332
p_port1->connect(p_port2, width, speed);
1333
p_port2->connect(p_port1, width, speed);
1337
//////////////////////////////////////////////////////////////////////////////
1339
// Parse the cabling definition file
1341
IBFabric::parseCables (string fn) {
1342
ifstream f(fn.c_str());
1344
string n1, t1, p1, n2, t2, p2;
1345
regExp cablingLine("[ \t]*([^ \t]+)[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]*");
1346
regExp ignoreLine("^[ \t]*(#|[ \t]*$)");
1348
IBLinkSpeed speed = IB_UNKNOWN_LINK_SPEED;
1349
IBLinkWidth width = IB_UNKNOWN_LINK_WIDTH;
1353
cout << "-E- Fail to open file:" << fn.c_str() << endl;
1357
cout << "-I- Parsing cabling definition:" << fn.c_str() << endl;
1363
f.getline(sLine,1024);
1364
// <SysType1> <sysName1> <portName1> <SysType2> <sysName2> <portName2>
1365
p_rexRes = cablingLine.apply(sLine);
1369
t1 = p_rexRes->field(1);
1370
n1 = p_rexRes->field(2);
1371
p1 = p_rexRes->field(3);
1372
t2 = p_rexRes->field(4);
1373
n2 = p_rexRes->field(5);
1374
p2 = p_rexRes->field(6);
1375
if (addCable(t1, n1, p1, t2, n2, p2, width, speed))
1377
cout << "-E- Fail to make cable"
1378
<< " (line:" << lineNum << ")"
1388
// check if leagel ignored line
1389
p_rexRes = ignoreLine.apply(sLine);
1396
cout << "-E- Bad syntax on line:" << sLine << endl;
1400
cout << "-I- Defined " << SystemByName.size() << "/" << NodeByName.size() <<
1401
" systems/nodes " << endl;
1406
//////////////////////////////////////////////////////////////////////////////
1408
// Parse the topology definition file
1410
IBFabric::parseTopology (string fn) {
1411
ifstream f(fn.c_str());
1413
string n1 = string(""), t1, p1, n2, t2, p2, cfg = string("");
1414
regExp sysLine("^[ \t]*([^/ \t]+)[ \t]+([^/ \t]+)[ \t]*( CFG:(.*))?$");
1415
regExp sysModule("([^ \t,]+)(.*)");
1416
regExp portLine("^[ \t]+([^ \t]+)[ \t]+-((1|4|8|12)[xX]-)?((2.5|5|10)G-)?[>]"
1417
"[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]+([^ \t]+)[ \t]*$");
1418
regExp ignoreLine("^[ \t]*#");
1419
regExp emptyLine("^[ \t]*$");
1421
IBSystem *p_system = NULL;
1427
cout << "-E- Fail to open file:" << fn.c_str() << endl;
1431
cout << "-I- Parsing topology definition:" << fn.c_str() << endl;
1433
// we need two passes since we only get system configuration
1434
// on a system definition line.
1438
f.getline(sLine,1024);
1440
// check if legal ignored line
1441
p_rexRes = ignoreLine.apply(sLine);
1448
// First look for system line:
1449
p_rexRes = sysLine.apply(sLine);
1453
t1 = p_rexRes->field(1);
1454
n1 = p_rexRes->field(2);
1455
cfg = p_rexRes->field(4);
1456
p_system = makeSystem(n1,t1,cfg);
1461
cout << "-E- Fail to make system:" << n1
1462
<< " of type:" << t1
1463
<< " (line:" << lineNum << ")"
1480
cout << "-E- Fail to re open file:" << fn.c_str() << endl;
1488
f.getline(sLine,1024);
1490
// check if legal ignored line
1491
p_rexRes = ignoreLine.apply(sLine);
1498
// look for system line:
1499
p_rexRes = sysLine.apply(sLine);
1503
t1 = p_rexRes->field(1);
1504
n1 = p_rexRes->field(2);
1505
cfg = p_rexRes->field(4);
1506
p_system = makeSystem(n1,t1,cfg);
1511
cout << "-E- Fail to make system:" << n1
1512
<< " of type:" << t1
1513
<< " (line:" << lineNum << ")"
1522
// is it a port line:
1523
p_rexRes = portLine.apply(sLine);
1528
p1 = p_rexRes->field(1);
1529
width = char2width((p_rexRes->field(3) + "x").c_str());
1530
speed = char2speed((p_rexRes->field(5)).c_str());
1531
// supporting backward compatibility and default
1532
// we define both speed and width:
1533
if (width == IB_UNKNOWN_LINK_WIDTH) width = IB_LINK_WIDTH_4X;
1534
if (speed == IB_UNKNOWN_LINK_SPEED) speed = IB_LINK_SPEED_2_5;
1536
t2 = p_rexRes->field(6);
1537
n2 = p_rexRes->field(7);
1538
p2 = p_rexRes->field(8);
1539
if (addCable(t1, n1, p1, t2, n2, p2, width, speed))
1541
cout << "-E- Fail to make cable"
1542
<< " (line:" << lineNum << ")"
1551
cout << "-E- Fail to make connection as local system "
1552
<< "not defined (line:" << lineNum << ")"
1561
// check if empty line - marking system end:
1562
p_rexRes = emptyLine.apply(sLine);
1570
cout << "-W- Ignoring '" << sLine << "'"
1571
<< " (line:" << lineNum << ")" << endl;
1574
cout << "-I- Defined " << SystemByName.size() << "/"
1575
<< NodeByName.size() << " systems/nodes " << endl;
1580
//////////////////////////////////////////////////////////////////////////////
1582
// Create a new link in the fabric.
1583
// create the node and the system if required.
1584
// NOTE that for LMC > 0 we do not get the multiple lid
1585
// assignments - just the base lid.
1586
// so we need to assign them ourselves (for CAs) if we have LMC
1587
// Also note that if we provide a description for the device
1588
// it is actually means the device is a CA and that is the system name ...
1590
IBFabric::addLink(string type1, int numPorts1,
1591
uint64_t sysGuid1, uint64_t nodeGuid1, uint64_t portGuid1,
1592
int vend1, int devId1, int rev1, string desc1,
1593
int hcaIdx1, int lid1, int portNum1,
1594
string type2, int numPorts2,
1595
uint64_t sysGuid2, uint64_t nodeGuid2, uint64_t portGuid2,
1596
int vend2, int devId2, int rev2, string desc2,
1597
int hcaIdx2, int lid2, int portNum2,
1598
IBLinkWidth width, IBLinkSpeed speed
1601
IBSystem *p_sys1, *p_sys2;
1602
IBNode *p_node1, *p_node2;
1605
// make sure the system1 exists
1608
sprintf(buf, "S%016" PRIx64, sysGuid1);
1609
string sysName1 = string(buf);
1610
p_sys1 = makeGenericSystem(sysName1);
1614
p_sys1 = makeGenericSystem(desc1);
1619
sprintf(buf, "S%016" PRIx64, sysGuid2);
1620
string sysName2 = string(buf);
1621
p_sys2 = makeGenericSystem(sysName2);
1625
p_sys2 = makeGenericSystem(desc2);
1628
// make sure the nodes exists
1629
p_node1 = getNodeByGuid(nodeGuid1);
1632
// if we got a desc name
1633
if ((type1 != "SW") && desc1.size())
1635
sprintf(buf,"%s/U%d", desc1.c_str(), hcaIdx1);
1639
sprintf(buf,"%s/U%d", p_sys1->name.c_str(),
1640
p_sys1->NodeByName.size() + 1);
1644
p_node1 = makeNode(buf, p_sys1, IB_SW_NODE, numPorts1);
1648
p_node1 = makeNode(buf, p_sys1, IB_CA_NODE, numPorts1);
1650
p_node1->guid_set(nodeGuid1);
1653
p_node2 = getNodeByGuid(nodeGuid2);
1656
// if we got a desc name
1657
if ((type2 != "SW") && desc2.size())
1658
sprintf(buf,"%s/U%d", desc2.c_str(), hcaIdx2);
1660
sprintf(buf,"%s/U%d", p_sys2->name.c_str(),
1661
p_sys2->NodeByName.size() + 1);
1664
p_node2 = makeNode(buf, p_sys2, IB_SW_NODE, numPorts2);
1668
p_node2 = makeNode(buf, p_sys2, IB_CA_NODE, numPorts2);
1670
p_node2->guid_set(nodeGuid2);
1673
// we want to use the host names if they are defined:
1675
p_node1->attributes = string("host=") + desc1;
1678
p_node2->attributes = string("host=") + desc2;
1680
IBSysPort *p_sysPort1 = 0, *p_sysPort2 = 0;
1682
// create system ports if required
1683
if (sysGuid1 != sysGuid2)
1685
if (type1 == "SW" || desc1.size() == 0 || hcaIdx1 != 1)
1687
// avoid adding the sys name to the port...
1688
if (p_sys1->name == p_node1->name.substr(0, p_sys1->name.length()))
1690
string noSys = p_node1->name.substr(p_sys1->name.length() + 1,
1691
p_node1->name.length() -
1692
p_sys1->name.length() - 1);
1693
sprintf(buf,"%s/P%u", noSys.c_str(), portNum1);
1697
sprintf(buf,"%s/P%u", p_node1->name.c_str(), portNum1);
1702
sprintf(buf,"P%u", portNum1);
1704
p_sysPort1 = p_sys1->getSysPort(buf);
1705
if (p_sysPort1 == NULL)
1706
p_sysPort1 = new IBSysPort(buf, p_sys1);
1708
if (type2 == "SW" || desc2.size() == 0 || hcaIdx2 != 1)
1710
if (p_sys2->name == p_node2->name.substr(0, p_sys2->name.length()))
1712
string noSys = p_node2->name.substr(p_sys2->name.length() + 1,
1713
p_node2->name.length() -
1714
p_sys2->name.length() - 1);
1715
sprintf(buf,"%s/P%u", noSys.c_str(), portNum2);
1719
sprintf(buf,"%s/P%u", p_node2->name.c_str(), portNum2);
1724
sprintf(buf,"P%u", portNum2);
1726
p_sysPort2 = p_sys2->getSysPort(buf);
1727
if (p_sysPort2 == NULL)
1728
p_sysPort2 = new IBSysPort(buf, p_sys2);
1731
// make sure the ports exits
1732
IBPort *p_port1 = p_node1->makePort(portNum1);
1733
IBPort *p_port2 = p_node2->makePort(portNum2);
1735
// we know the guids so set them
1736
p_sys1->guid_set(sysGuid1);
1737
p_sys2->guid_set(sysGuid2);
1739
p_node1->guid_set(nodeGuid1);
1740
p_node2->guid_set(nodeGuid2);
1741
p_port1->guid_set(portGuid1);
1742
p_port2->guid_set(portGuid2);
1744
// copy some data...
1745
p_node1->devId = devId1;
1746
p_node1->revId = rev1;
1747
p_node1->vendId = vend1;
1749
p_node2->devId = devId2;
1750
p_node2->revId = rev2;
1751
p_node2->vendId = vend2;
1754
int numLidsPerPort = 1 << lmc;
1755
p_port1->base_lid = lid1;
1756
for (int l = lid1; l < lid1 + numLidsPerPort; l++)
1757
setLidPort(l, p_port1);
1758
p_port2->base_lid = lid2;
1759
for (int l = lid2; l < lid2 + numLidsPerPort; l++)
1760
setLidPort(l, p_port2);
1765
p_sysPort1->p_nodePort = p_port1;
1766
p_sysPort2->p_nodePort = p_port2;
1767
p_port1->p_sysPort = p_sysPort1;
1768
p_port2->p_sysPort = p_sysPort2;
1769
p_sysPort1->connect(p_sysPort2, width, speed);
1770
p_sysPort2->connect(p_sysPort1, width, speed);
1774
p_port1->connect(p_port2, width, speed);
1775
p_port2->connect(p_port1, width, speed);
1778
if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
1779
cout << "-V- Connecting Lid:" << lid1 << " Port:" << portNum1
1780
<< " to Lid:" << lid2 << " Port:" << portNum2 << endl;
1785
//////////////////////////////////////////////////////////////////////////////
1787
// Parse a single subnet line using strtok for simplicity...
1789
IBFabric::parseSubnetLine(char *line) {
1791
string type1, desc1;
1792
unsigned int numPorts1, vend1, devId1, rev1, lid1, portNum1, hcaIdx1 = 0;
1793
uint64_t sysGuid1, nodeGuid1, portGuid1;
1795
string type2, desc2;
1796
unsigned int numPorts2, vend2, devId2, rev2, lid2, portNum2, hcaIdx2 = 0;
1797
uint64_t sysGuid2, nodeGuid2, portGuid2;
1803
// do the first Port...
1804
pch = strtok(line, " ");
1805
if (!pch || pch[0] != '{') return(1);
1807
pch = strtok(NULL, " ");
1808
if (!pch || (strncmp(pch,"CA",2) && strncmp(pch,"SW",2))) return(2);
1809
if (!strncmp(pch,"CA",2)) type1 = "CA"; else type1 = "SW";
1811
pch = strtok(NULL, " ");
1812
if (!pch || strncmp(pch,"Ports:",6)) return(3);
1813
numPorts1 = strtol(pch+6, NULL,16);
1815
pch = strtok(NULL, " ");
1816
if (!pch || strncmp(pch,"SystemGUID:",11)) return(4);
1817
sysGuid1 = strtoull(pch+11, NULL, 16);
1819
pch = strtok(NULL, " ");
1820
if (!pch || strncmp(pch,"NodeGUID:",9)) return(5);
1821
nodeGuid1 = strtoull(pch+9, NULL, 16);
1823
pch = strtok(NULL, " ");
1824
if (!pch || strncmp(pch,"PortGUID:",9)) return(6);
1825
portGuid1 = strtoull(pch+9, NULL, 16);
1827
pch = strtok(NULL, " ");
1828
if (!pch || strncmp(pch,"VenID:",6)) return(7);
1829
vend1 = strtol(pch+6, NULL, 16);
1831
pch = strtok(NULL, " ");
1832
if (!pch || strncmp(pch,"DevID:",6)) return(8);
1833
char *pdid1 = pch+6;
1834
pch = strtok(NULL, " ");
1836
// handle old broken DevId field in subnet.lst
1837
// which was adding 0000 suffix. Should have been 16 bits only
1838
if (strlen(pdid1) == 8) pdid1[4] = '\0';
1839
devId1 = strtol(pdid1, NULL, 16);
1841
if (!pch || strncmp(pch,"Rev:",4)) return(9);
1842
rev1 = strtol(pch+4, NULL, 16);
1844
// on some installations the desc of the node holds the
1845
// name of the hosts:
1846
if (subnCANames && (type1 == "CA"))
1848
// the first word in the description please.
1849
pch = strtok(NULL, " ");
1850
// but now we must find an "HCA-" ...
1851
string dbg = string(pch + strlen(pch) + 1);
1852
if (!strncmp("HCA-", pch + strlen(pch) + 1, 4))
1854
desc1 = string(pch+1);
1855
hcaIdx1 = atoi(pch + strlen(pch) + 5);
1858
// on some rare cases there is no space in desc:
1859
if (!strchr(pch,'}'))
1861
pch = strtok(NULL, "}");
1862
if (!pch ) return(10);
1865
pch = strtok(NULL, " ");
1866
if (!pch || strncmp(pch,"LID:", 4)) return(11);
1867
lid1 = strtol(pch+4, NULL, 16);
1869
pch = strtok(NULL, " ");
1870
if (!pch || strncmp(pch,"PN:", 3)) return(12);
1871
portNum1 = strtol(pch+3, NULL, 16);
1873
pch = strtok(NULL, " ");
1874
if (!pch || pch[0] != '}') return(13);
1876
pch = strtok(NULL, " ");
1877
if (!pch || pch[0] != '{') return(14);
1880
pch = strtok(NULL, " ");
1881
if (!pch || (strncmp(pch,"CA",2) && strncmp(pch,"SW",2))) return(15);
1882
if (!strncmp(pch,"CA",2)) type2 = "CA"; else type2 = "SW";
1884
pch = strtok(NULL, " ");
1885
if (!pch || strncmp(pch,"Ports:",6)) return(16);
1886
numPorts2 = strtol(pch+6, NULL,16);
1888
pch = strtok(NULL, " ");
1889
if (!pch || strncmp(pch,"SystemGUID:",11)) return(17);
1890
sysGuid2 = strtoull(pch+11, NULL, 16);
1892
pch = strtok(NULL, " ");
1893
if (!pch || strncmp(pch,"NodeGUID:",9)) return(18);
1894
nodeGuid2 = strtoull(pch+9, NULL, 16);
1896
pch = strtok(NULL, " ");
1897
if (!pch || strncmp(pch,"PortGUID:",9)) return(19);
1898
portGuid2 = strtoull(pch+9, NULL, 16);
1900
pch = strtok(NULL, " ");
1901
if (!pch || strncmp(pch,"VenID:",6)) return(20);
1902
vend2 = strtol(pch+6, NULL, 16);
1904
pch = strtok(NULL, " ");
1905
if (!pch || strncmp(pch,"DevID:",6)) return(21);
1906
char *pdid2 = pch+6;
1907
pch = strtok(NULL, " ");
1909
// handle old broken DevId field in subnet.lst
1910
// which was adding 0000 suffix. Should have been 16 bits only
1911
if (strlen(pdid2) == 8) pdid2[4] = '\0';
1912
devId2 = strtol(pdid2, NULL, 16);
1914
if (!pch || strncmp(pch,"Rev:",4)) return(22);
1915
rev2 = strtol(pch+4, NULL, 16);
1917
if (subnCANames && (type2 == "CA"))
1919
// the first word in the description please.
1920
pch = strtok(NULL, " ");
1921
// but now we must find an "HCA-" ...
1922
if (!strncmp("HCA-", pch + strlen(pch) + 1, 4))
1924
desc2 = string(pch+1);
1925
hcaIdx2 = atoi(pch + strlen(pch) + 5);
1928
// on some rare cases there is no space in desc:
1929
if (!strchr(pch,'}'))
1931
pch = strtok(NULL, "}");
1932
if (!pch ) return(23);
1935
pch = strtok(NULL, " ");
1936
if (!pch || strncmp(pch,"LID:", 4)) return(24);
1937
lid2 = strtol(pch+4, NULL, 16);
1939
pch = strtok(NULL, " ");
1940
if (!pch || strncmp(pch,"PN:", 3)) return(25);
1941
portNum2 = strtol(pch+3, NULL, 16);
1943
pch = strtok(NULL, " ");
1944
if (!pch || pch[0] != '}') return(26);
1946
// PHY=8x LOG=ACT SPD=5
1947
pch = strtok(NULL, " ");
1948
if (!pch || strncmp(pch,"PHY=",4)) return(27);
1949
width = char2width(pch+4);
1951
pch = strtok(NULL, " ");
1952
if (!pch || strncmp(pch,"LOG=",4)) return(28);
1954
// for now we require the state to be ACTIVE ...
1955
if (strncmp(pch+4, "ACT",3) &&
1956
strncmp(pch+4, "INI",3) &&
1957
strncmp(pch+4, "ARM",3)) return(0);
1959
// speed is optional ... s
1960
pch = strtok(NULL, " ");
1961
if (pch && !strncmp(pch,"SPD=",4))
1963
speed = char2speed(pch+4);
1965
speed = IB_LINK_SPEED_2_5;
1972
if (addLink(type1, numPorts1, sysGuid1, nodeGuid1, portGuid1,
1973
vend1, devId1, rev1, desc1, hcaIdx1, lid1, portNum1,
1974
type2, numPorts2, sysGuid2, nodeGuid2, portGuid2,
1975
vend2, devId2, rev2, desc2, hcaIdx2, lid2, portNum2,
1981
// Parse an OpenSM Subnet file and build the fabric accordingly
1983
IBFabric::parseSubnetLinks (string fn) {
1984
ifstream f(fn.c_str());
1991
cout << "-E- Fail to open file:" << fn.c_str() << endl;
1995
cout << "-I- Parsing Subnet file:" << fn.c_str() << endl;
2001
f.getline(sLine,1024);
2002
if (!strlen(sLine)) continue;
2004
status = parseSubnetLine(sLine);
2007
cout << "-W- Wrong syntax code:" << status << " in line:"
2012
cout << "-I- Defined " << SystemByName.size() << "/" << NodeByName.size()
2013
<< " systems/nodes " << endl;
2018
//////////////////////////////////////////////////////////////////////////////
2020
// Parse an OpenSM FDBs file and set the LFT table accordingly
2022
IBFabric::parseFdbFile(string fn) {
2023
ifstream f(fn.c_str());
2024
int switches = 0, fdbLines=0;
2026
// osm_ucast_mgr_dump_ucast_routes: Switch 0x2c90000213700
2027
// 0x0001 : 006 : 01 : yes
2028
regExp switchLine("osm_ucast_mgr_dump_ucast_routes: Switch 0x([0-9a-z]+)");
2029
regExp lidLine("0x([0-9a-zA-Z]+) : ([0-9]+)");
2034
cout << "-E- Fail to open file:" << fn.c_str() << endl;
2038
cout << "-I- Parsing FDBs file:" << fn.c_str() << endl;
2044
f.getline(sLine,1024);
2046
p_rexRes = switchLine.apply(sLine);
2049
// Got a new switch - find the node:
2051
guid = strtoull(p_rexRes->field(1).c_str(), NULL, 16);
2052
p_node = getNodeByGuid(guid);
2055
cout << "-E- Fail to find node with guid:"
2056
<< p_rexRes->field(1) << endl;
2067
p_rexRes = lidLine.apply(sLine);
2070
// Got a new lid port pair
2073
unsigned int lid = strtol((p_rexRes->field(1)).c_str(), NULL, 16);
2074
unsigned int port = strtol((p_rexRes->field(2)).c_str(), NULL, 10);
2075
if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
2076
cout << "-V- Setting FDB for:" << p_node->name
2077
<< " lid:" << lid << " port:" << port << endl;
2079
p_node->setLFTPortForLid(lid,port);
2086
// is it an ignore line ?
2087
//cout << "-W- Ignoring line:" << sLine << endl;
2090
cout << "-I- Defined " << fdbLines << " fdb entries for:"
2091
<< switches << " switches" << endl;
2096
//////////////////////////////////////////////////////////////////////////////
2098
// Parse PSL file and set the SLT tables accordingly
2100
IBFabric::parsePSLFile(string fn) {
2101
ifstream f(fn.c_str());
2105
// 0x0002c90000000099 154 0
2107
regExp slLine("0x([0-9a-z]+) ([0-9]+) ([0-9]+)");
2112
cout << "-E- Fail to open file:" << fn.c_str() << endl;
2116
cout << "-I- Parsing SL file:" << fn.c_str() << endl;
2122
f.getline(sLine,1024);
2123
p_rexRes = slLine.apply(sLine);
2126
unsigned int lid = strtoull(p_rexRes->field(2).c_str(), NULL, 10);
2127
maxLid = lid > maxLid ? lid:maxLid;
2131
cout << "-E- Wrong file format:" << fn.c_str() << endl;
2137
// Make second pass and build the tables
2138
f.open(fn.c_str(),ifstream::in);
2141
cout << "-E- Fail to open file:" << fn.c_str() << endl;
2146
f.getline(sLine,1024);
2148
p_rexRes = slLine.apply(sLine);
2151
uint64_t guid = strtoull(p_rexRes->field(1).c_str(), NULL, 16);
2152
unsigned int lid = strtoull(p_rexRes->field(2).c_str(), NULL, 10);
2153
uint8_t sl = strtoull(p_rexRes->field(3).c_str(), NULL, 10);
2155
IBNode* p_node = getNodeByGuid(guid);
2158
cout << "-E- Fail to find node with guid:"
2164
// Update number of used SLs
2165
numSLs = sl+1 > numSLs ? sl+1:numSLs;
2166
// Insert table entry
2167
p_node->setPSLForLid(lid,maxLid,sl);
2173
cout << "-E- Wrong file format:" << fn.c_str() << endl;
2177
cout << "-I- Defined "<< (int)numSLs << " SLs in use" <<endl;
2183
//////////////////////////////////////////////////////////////////////////////
2185
// Parse SLVL file and set the SL2VL tables accordingly
2187
IBFabric::parseSLVLFile(string fn) {
2189
ifstream f(fn.c_str());
2192
// 0x0002c90000000201 5 1 0x01 0x23 0x45 0x67 0x89 0xab 0xcd 0xe7
2193
// guid iport oport 0x(sl0)(sl1) 0x(sl2)(sl3)...
2194
regExp slLine("0x([0-9a-z]+) ([0-9]+) ([0-9]+) 0x([0-9a-z])([0-9a-z]) 0x([0-9a-z])([0-9a-z]) 0x([0-9a-z])([0-9a-z]) 0x([0-9a-z])([0-9a-z]) 0x([0-9a-z])([0-9a-z]) 0x([0-9a-z])([0-9a-z]) 0x([0-9a-z])([0-9a-z]) 0x([0-9a-z])([0-9a-z])");
2198
cout << "-E- Fail to open file:" << fn.c_str() << endl;
2202
cout << "-I- Parsing SLVL file:" << fn.c_str() << endl;
2208
f.getline(sLine,1024);
2210
p_rexRes = slLine.apply(sLine);
2213
uint64_t guid = strtoull(p_rexRes->field(1).c_str(), NULL, 16);
2214
unsigned int iport = strtoull(p_rexRes->field(2).c_str(), NULL, 10);
2215
unsigned int oport = strtoull(p_rexRes->field(3).c_str(), NULL, 10);
2217
IBNode* p_node = getNodeByGuid(guid);
2220
cout << "-E- Fail to find node with guid:"
2226
for (int i=0;i<IB_NUM_SL;i++) {
2227
// Extract the VL value
2228
uint8_t vl = strtoull(p_rexRes->field(4+i).c_str(), NULL, 16);
2229
numVLs = numVLs > vl+1 ? numVLs : vl+1;
2230
// Set the table entry
2231
p_node->setSLVL(iport,oport,i,vl);
2238
cout << "-E- Wrong file format:" << fn.c_str() << endl;
2242
cout << "-I- Defined "<< (int)numVLs << " VLs in use" <<endl;
2249
///////////////////////////////////////////////////////////////////////////
2251
// Parse an OpenSM MCFDBs file and set the MFT table accordingly
2253
IBFabric::parseMCFdbFile(string fn) {
2254
ifstream f(fn.c_str());
2255
int switches = 0, fdbLines=0;
2257
// Switch 0x0002c9010bb90090
2258
// LID : Out Port(s)
2261
regExp switchLine("Switch 0x([0-9a-z]+)");
2262
regExp lidLine("0x([0-9a-zA-Z]+) :(.*)");
2267
cout << "-E- Fail to open file:" << fn.c_str() << endl;
2271
cout << "-I- Parsing Multicast FDBs file:" << fn.c_str() << endl;
2277
f.getline(sLine,1024);
2279
p_rexRes = switchLine.apply(sLine);
2282
// Got a new switch - find the node:
2284
guid = strtoull(p_rexRes->field(1).c_str(), NULL, 16);
2285
p_node = getNodeByGuid(guid);
2288
cout << "-E- Fail to find switch: node:"
2289
<< p_rexRes->field(1) << endl;
2300
p_rexRes = lidLine.apply(sLine);
2303
// Got a new lid port pair
2306
unsigned int lid = strtol((p_rexRes->field(1)).c_str(), NULL, 16);
2308
char buff[(p_rexRes->field(2)).size() + 1];
2309
strcpy(buff, p_rexRes->field(2).c_str());
2311
char *pPortChr = strtok(buff, " ");
2313
unsigned int port = strtol(pPortChr, NULL, 16);
2315
if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
2316
cout << "-V- Setting Multicast FDB for:" << p_node->name
2317
<< " lid:" << lid << " port:" << port << endl;
2319
p_node->setMFTPortForMLid(lid,port);
2320
pPortChr = strtok(NULL, " ");
2328
// is it an ignore line ?
2329
//cout << "-W- Ignoring line:" << sLine << endl;
2332
cout << "-I- Defined " << fdbLines << " Multicast Fdb entries for:"
2333
<< switches << " switches" << endl;
2338
///////////////////////////////////////////////////////////////////////////
2339
// dump out the contents of the entire fabric
2341
IBFabric::dump(ostream &sout) {
2342
sout << "--------------- FABRIC DUMP ----------------------" << endl;
2343
// we start with all systems at top level:
2344
for (map_str_psys::iterator sI = SystemByName.begin();
2345
sI != SystemByName.end();
2347
IBSystem *p_system = (*sI).second;
2348
sout << "\nSystem:" << p_system->name << " (" << p_system->type
2349
<< "," << guid2str(p_system->guid_get()) << ")" << endl;
2350
for (map_str_psysport::iterator pI = p_system->PortByName.begin();
2351
pI != p_system->PortByName.end();
2353
IBSysPort *p_port = (*pI).second;
2354
IBLinkWidth width = IB_UNKNOWN_LINK_WIDTH;
2355
IBLinkSpeed speed = IB_UNKNOWN_LINK_SPEED;
2357
if (! p_port) continue;
2360
sout << " " << p_port->name;
2361
if ( p_port->p_nodePort)
2363
sout << " (" << p_port->p_nodePort->p_node->name << "/"
2364
<< p_port->p_nodePort->num << ")";
2365
width = p_port->p_nodePort->width;
2366
speed = p_port->p_nodePort->speed;
2370
sout << " (ERR: NO NODE PORT?)";
2374
if ( p_port->p_remoteSysPort)
2376
sout << " -" << width2char(width) << "-" << speed2char(speed)
2378
<< p_port->p_remoteSysPort->p_system->name << "/"
2379
<< p_port->p_remoteSysPort->name << endl;
2388
// Now dump system internals:
2389
for (map_str_psys::iterator sI = SystemByName.begin();
2390
sI != SystemByName.end();
2392
IBSystem *p_system = (*sI).second;
2393
sout << "--------------- SYSTEM " << (*sI).first
2394
<< " DUMP ----------------------" << endl;
2396
// go over all nodes of the system:
2397
for (map_str_pnode::iterator nI = p_system->NodeByName.begin();
2398
nI != p_system->NodeByName.end();
2400
IBNode *p_node = (*nI).second;
2402
sout << "\nNode:" << p_node->name << " (" << p_node->type
2403
<< "," << guid2str(p_node->guid_get()) << ")" << endl;
2405
for (unsigned int pn = 1; pn <= p_node->numPorts; pn++) {
2406
IBPort *p_port = p_node->getPort(pn);
2408
if (! p_port) continue;
2410
// we do not report cross system connections:
2411
if (p_port->p_sysPort)
2413
sout << " " << pn << " => SysPort:"
2414
<< p_port->p_sysPort->name << endl;
2415
} else if (p_port->p_remotePort) {
2416
sout << " " << pn << " -" << width2char(p_port->width)
2417
<< "-" << speed2char(p_port->speed) << "G-> "
2418
<< p_port->p_remotePort->getName() << endl;
2425
///////////////////////////////////////////////////////////////////////////
2426
// dump out the contents of the entire fabric as a topology file with
2427
// required set of IBNL's if unknown
2429
IBFabric::dumpTopology(char *fileName, char * ibnlDir) {
2431
sout.open(fileName);
2434
cout << "-E- failed to open:" << fileName << " for writing." << endl;
2437
sout << "# This topology file was automaticlly generated by IBDM" << endl;
2439
// we start with all systems at top level:
2440
for (map_str_psys::iterator sI = SystemByName.begin();
2441
sI != SystemByName.end();
2443
IBSystem *p_system = (*sI).second;
2446
if (p_system->type == "Generic")
2448
p_system->dumpIBNL(ibnlDir, sysType);
2452
sysType = string(p_system->type);
2454
sout << "\n" << sysType << " " << p_system->name << endl;
2455
for (map_str_psysport::iterator pI = p_system->PortByName.begin();
2456
pI != p_system->PortByName.end();
2458
IBSysPort *p_sysPort = (*pI).second;
2459
IBLinkWidth width = IB_UNKNOWN_LINK_WIDTH;
2460
IBLinkSpeed speed = IB_UNKNOWN_LINK_SPEED;
2462
if (! p_sysPort) continue;
2465
if ( p_sysPort->p_remoteSysPort)
2467
width = p_sysPort->p_nodePort->width;
2468
speed = p_sysPort->p_nodePort->speed;
2470
if (p_sysPort->p_remoteSysPort->p_system->type == "Generic")
2472
p_sysPort->p_remoteSysPort->p_system->dumpIBNL(ibnlDir, sysType);
2476
sysType = string(p_sysPort->p_remoteSysPort->p_system->type);
2479
sout << " " << p_sysPort->name
2480
<< " -" << width2char(width) << "-" << speed2char(speed)
2481
<< "G-> " << sysType.c_str() << " "
2482
<< p_sysPort->p_remoteSysPort->p_system->name << " "
2483
<< p_sysPort->p_remoteSysPort->name << endl;
2491
#ifndef IBDM_CODE_VERSION
2492
#define IBDM_CODE_VERSION "undefined"
2494
const char * ibdmSourceVersion = IBDM_CODE_VERSION ;