~ubuntu-branches/ubuntu/raring/ibutils/raring-proposed

« back to all changes in this revision

Viewing changes to ibdm/ibdm/Fabric.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Benoit Mortier
  • Date: 2010-01-11 22:22:00 UTC
  • Revision ID: james.westby@ubuntu.com-20100111222200-53kum2et5nh13rv3
Tags: upstream-1.2-OFED-1.4.2
ImportĀ upstreamĀ versionĀ 1.2-OFED-1.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2004 Mellanox Technologies LTD. All rights reserved.
 
3
 *
 
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:
 
9
 *
 
10
 *     Redistribution and use in source and binary forms, with or
 
11
 *     without modification, are permitted provided that the following
 
12
 *     conditions are met:
 
13
 *
 
14
 *      - Redistributions of source code must retain the above
 
15
 *        copyright notice, this list of conditions and the following
 
16
 *        disclaimer.
 
17
 *
 
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.
 
22
 *
 
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
 
30
 * SOFTWARE.
 
31
 *
 
32
 * $Id$
 
33
 */
 
34
 
 
35
/*
 
36
  IB Fabric Data Model
 
37
  This file holds implementation of the data model classes and methods
 
38
 
 
39
*/
 
40
 
 
41
//////////////////////////////////////////////////////////////////////////////
 
42
 
 
43
#include "Fabric.h"
 
44
#include "SysDef.h"
 
45
#include "Regexp.h"
 
46
#include <iomanip>
 
47
#include <sstream>
 
48
#include "git_version.h"
 
49
 
 
50
// Track verbosity:
 
51
uint8_t FabricUtilsVerboseLevel = 0x1;
 
52
 
 
53
stringstream ibdmLog;
 
54
streambuf *ibdmCoutBuf;
 
55
 
 
56
int ibdmUseInternalLog() {
 
57
   streambuf *psbuf = ibdmLog.rdbuf();
 
58
   ibdmCoutBuf = cout.rdbuf(psbuf);
 
59
   return 0;
 
60
}
 
61
 
 
62
int ibdmUseCoutLog() {
 
63
   cout.rdbuf(ibdmCoutBuf);
 
64
   return 0;
 
65
}
 
66
 
 
67
char *ibdmGetAndClearInternalLog() {
 
68
   char *res;
 
69
   cout.rdbuf(ibdmCoutBuf);
 
70
   res = (char*)malloc(ibdmLog.str().length() + 1);
 
71
   strcpy(res, ibdmLog.str().c_str());
 
72
   ibdmLog.str("");
 
73
   ibdmUseInternalLog();
 
74
   return res;
 
75
}
 
76
 
 
77
//////////////////////////////////////////////////////////////////////////////
 
78
//
 
79
// CLASS IBPort:
 
80
//
 
81
 
 
82
// constructor
 
83
IBPort::IBPort(IBNode *p_nodePtr, int number) {
 
84
   p_node = p_nodePtr;
 
85
   num = number;
 
86
   p_sysPort = NULL;
 
87
   p_remotePort = NULL;
 
88
   base_lid = IB_LID_UNASSIGNED;
 
89
   memset(&guid,0,sizeof(uint64_t));
 
90
   counter1 = 0;
 
91
   counter2 = 0;
 
92
}
 
93
 
 
94
// destructor
 
95
IBPort::~IBPort() {
 
96
   if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
 
97
   {
 
98
      cout << "-I- Destructing Port:" << p_node->name << "/" << num << endl;
 
99
   }
 
100
 
 
101
   // if was connected - remove the connection:
 
102
   if (p_remotePort)
 
103
      p_remotePort->p_remotePort = NULL;
 
104
 
 
105
   // if has a system port - delete it too.
 
106
   if (p_sysPort)
 
107
   {
 
108
      p_sysPort->p_nodePort = NULL;
 
109
      delete p_sysPort;
 
110
   }
 
111
}
 
112
 
 
113
// Set the guid in the fabric too:
 
114
void IBPort::guid_set(uint64_t g) {
 
115
   if (p_node && p_node->p_fabric)
 
116
   {
 
117
      p_node->p_fabric->PortByGuid[g] = this;
 
118
      guid = g;
 
119
   }
 
120
}
 
121
 
 
122
// Get the port name.
 
123
// If connects to a system port - use the system port name.
 
124
string
 
125
IBPort::getName() {
 
126
   string name;
 
127
   if (p_sysPort)
 
128
   {
 
129
      name = p_sysPort->p_system->name + string("/") + p_sysPort->name;
 
130
   }
 
131
   else
 
132
   {
 
133
      if (! p_node)
 
134
      {
 
135
         cerr << "Got a port with no node" << endl;
 
136
         abort();
 
137
      }
 
138
      char buff[8];
 
139
      sprintf(buff,"/P%u", num);
 
140
      name = p_node->name + string(buff);
 
141
   }
 
142
   return name;
 
143
}
 
144
 
 
145
// connect the port to another node port
 
146
void
 
147
IBPort::connect (IBPort *p_otherPort,
 
148
                 IBLinkWidth w,
 
149
                 IBLinkSpeed s)
 
150
{
 
151
   // we can not simply override existing connections
 
152
   if (p_remotePort)
 
153
   {
 
154
      // we only do care if not the requested remote previously conn.
 
155
      if (p_remotePort != p_otherPort)
 
156
      {
 
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)
 
163
         {
 
164
            p_remotePort->p_remotePort = NULL;
 
165
         }
 
166
      }
 
167
   }
 
168
   p_remotePort = p_otherPort;
 
169
 
 
170
   // Check the other side was not previously connected
 
171
   if (p_otherPort->p_remotePort)
 
172
   {
 
173
      if (p_otherPort->p_remotePort != this)
 
174
      {
 
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)
 
182
         {
 
183
            p_otherPort->p_remotePort->p_remotePort = NULL;
 
184
         }
 
185
      }
 
186
   }
 
187
   p_otherPort->p_remotePort = this;
 
188
 
 
189
   p_remotePort->speed = speed = s;
 
190
   p_remotePort->width = width = w;
 
191
}
 
192
 
 
193
// disconenct two ports
 
194
int
 
195
IBPort::disconnect(int duringSysPortDisconnect)
 
196
{
 
197
   if (!p_remotePort)
 
198
   {
 
199
      cout << "-W- Trying to disconenct non connected port." << endl;
 
200
      return(1);
 
201
   }
 
202
 
 
203
   if (p_remotePort->p_remotePort != this)
 
204
   {
 
205
      cout
 
206
         << "-W- Remote port does not point back! Disconnecting self only."
 
207
         << endl;
 
208
      p_remotePort = NULL;
 
209
      return(1);
 
210
   }
 
211
   IBPort *p_remPort = p_remotePort;
 
212
   p_remotePort->p_remotePort = NULL;
 
213
   p_remotePort = NULL;
 
214
   if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
 
215
      cout << "-I- Disconnected port:" << getName()
 
216
           << " from:" << p_remPort->getName() << endl;
 
217
 
 
218
   // might need to treat the sys port too - but mark it duringPortDisconenct
 
219
   if (p_sysPort && ! duringSysPortDisconnect)
 
220
      return(p_sysPort->disconnect(1));
 
221
 
 
222
   return(0);
 
223
}
 
224
 
 
225
//////////////////////////////////////////////////////////////////////////////
 
226
//
 
227
// CLASS IBNode:
 
228
//
 
229
 
 
230
// Constructor:
 
231
IBNode::IBNode(string n,
 
232
               IBFabric *p_fab,
 
233
               IBSystem *p_sys,
 
234
               IBNodeType t, int np) {
 
235
   name = n;
 
236
   p_fabric = p_fab;
 
237
   p_system = p_sys;
 
238
   type = t;
 
239
   numPorts = np;
 
240
   guid = 0;
 
241
   rank = IBNODE_UNASSIGNED_RANK;
 
242
   attributes = string("");
 
243
   appData1.ptr = NULL;
 
244
   appData2.ptr = NULL;
 
245
   for (unsigned int i = 0; i < numPorts; i++)
 
246
      Ports.push_back((IBPort *)NULL);
 
247
 
 
248
   p_system->NodeByName[name] = this;
 
249
   p_fabric->NodeByName[name] = this;
 
250
}
 
251
 
 
252
// Delete the node cleaning up all it's connections
 
253
IBNode::~IBNode() {
 
254
   if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
 
255
   {
 
256
      cout << "-I- Destructing Node:" << name << endl;
 
257
   }
 
258
   // delete all the node ports:
 
259
   unsigned int p;
 
260
   for (p = 0; p < numPorts; p++) {
 
261
      IBPort *p_port = Ports[p];
 
262
      if (p_port)
 
263
      {
 
264
         delete p_port;
 
265
      }
 
266
   }
 
267
 
 
268
   // remove from the system NodesByName:
 
269
   if (p_system)
 
270
   {
 
271
      map_str_pnode::iterator nI = p_system->NodeByName.find(name);
 
272
      if (nI != p_system->NodeByName.end())
 
273
      {
 
274
         p_system->NodeByName.erase(nI);
 
275
      }
 
276
   }
 
277
 
 
278
   // remove from the fabric NodesByName:
 
279
   if (p_fabric)
 
280
   {
 
281
      map_str_pnode::iterator nI = p_fabric->NodeByName.find(name);
 
282
      if (nI != p_fabric->NodeByName.end())
 
283
      {
 
284
         p_fabric->NodeByName.erase(nI);
 
285
      }
 
286
   }
 
287
}
 
288
 
 
289
void
 
290
IBNode::guid_set(uint64_t g) {
 
291
   if (p_fabric)
 
292
   {
 
293
      p_fabric->NodeByGuid[g] = this;
 
294
      guid = g;
 
295
   }
 
296
}
 
297
 
 
298
// Set the min hop for the given port (* is all) lid pair
 
299
void
 
300
IBNode::setHops (IBPort *p_port, unsigned int lid, int hops) {
 
301
   if (MinHopsTable.empty())
 
302
   {
 
303
      if (lid > p_fabric->maxLid)
 
304
      {
 
305
         cout << "-W- We got a bigget lid:" << lid
 
306
              << " then maxLid:" << p_fabric->maxLid << endl;
 
307
         p_fabric->maxLid = lid;
 
308
      }
 
309
 
 
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;
 
316
      }
 
317
   }
 
318
 
 
319
   // now do the job
 
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
 
323
   if (lid != 0)
 
324
   {
 
325
      if (p_port == NULL)
 
326
      {
 
327
         // set it for all ports
 
328
         for(unsigned int i = 0; i <= numPorts; i++)
 
329
            MinHopsTable[lid][i] = hops;
 
330
      }
 
331
      else
 
332
      {
 
333
         MinHopsTable[lid][p_port->num] = hops;
 
334
      }
 
335
   }
 
336
   else
 
337
   {
 
338
      for (unsigned int l = 0; l < MinHopsTable.size(); l++)
 
339
         for(unsigned int i = 0; i <= numPorts; i++)
 
340
            MinHopsTable[l][i] = hops;
 
341
   }
 
342
 
 
343
   // keep track about the min hops per node:
 
344
   if (MinHopsTable[lid][0] > hops)
 
345
      MinHopsTable[lid][0] = hops;
 
346
} // method setHops
 
347
 
 
348
// Report Min Hop Table of the current Node
 
349
void
 
350
IBNode::repHopTable () {
 
351
   cout << "-I- MinHopTable for Node:" << name << "\n"
 
352
        << "=========================\n" <<endl;
 
353
   if (MinHopsTable.empty())
 
354
   {
 
355
      cout << "\tEmpty" << endl;
 
356
   }
 
357
   else
 
358
   {
 
359
      cout << "  " << setw(3) << "MIN" << " ";
 
360
      // Lid/Port header line
 
361
      for (int i=1; i <= Ports.size(); i++)
 
362
         cout << setw(2) << i << " " ;
 
363
      cout << endl;
 
364
      for (int i = 1; i <= 3*Ports.size()+5; i++) cout << "-";
 
365
      cout << endl;
 
366
      for (int l = 1; l <= p_fabric->maxLid; l++)
 
367
      {
 
368
         cout << setw(2) << l << "|";
 
369
         for (int i=0; i <= Ports.size(); i++)
 
370
         {
 
371
            int val=(int)MinHopsTable[l][i];
 
372
            if (val != 255)
 
373
               cout << setw(2) << val << " " ;
 
374
            else
 
375
               cout << setw(2) << "-" << " " ;
 
376
         }
 
377
         IBPort *p_port = p_fabric->getPortByLid(l);
 
378
         if (p_port)
 
379
            cout << " " << p_port->p_node->name;
 
380
         cout << endl;
 
381
      }
 
382
      cout << endl;
 
383
   }
 
384
} // Method repHopTable
 
385
 
 
386
 
 
387
 
 
388
 
 
389
//////////////////////////////////////////////////////////////////////////////
 
390
 
 
391
// Get the min number of hops defined for the given port or all
 
392
int
 
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];
 
400
}
 
401
 
 
402
//////////////////////////////////////////////////////////////////////////////
 
403
 
 
404
// Scan the node ports and find the first port
 
405
// with min hop to the lid
 
406
IBPort *
 
407
IBNode::getFirstMinHopPort(unsigned int lid) {
 
408
 
 
409
   // make sure it is a SW:
 
410
   if (type != IB_SW_NODE)
 
411
   {
 
412
      cout << "-E- Get best hop port must be run on SW nodes!" << endl;
 
413
      return NULL;
 
414
   }
 
415
 
 
416
   if (MinHopsTable.empty() || (MinHopsTable.size() < lid + 1))
 
417
      return NULL;
 
418
 
 
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)
 
423
         return getPort(i);
 
424
   return NULL;
 
425
}
 
426
 
 
427
//////////////////////////////////////////////////////////////////////////////
 
428
 
 
429
// Set the Linear Forwarding Table:
 
430
void
 
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)
 
435
   {
 
436
      LFT.resize(lid + 100);
 
437
      // initialize
 
438
      for(unsigned int i = origSize; i < LFT.size(); i++)
 
439
         LFT[i] = IB_LFT_UNASSIGNED;
 
440
   }
 
441
 
 
442
   // now do the job
 
443
   LFT[lid] = portNum;
 
444
}
 
445
 
 
446
//////////////////////////////////////////////////////////////////////////////
 
447
 
 
448
// Get the LFT for a given lid
 
449
int
 
450
IBNode::getLFTPortForLid (unsigned int lid) {
 
451
   // make sure it is initialized:
 
452
   if (LFT.empty() || (LFT.size() < lid + 1)) return IB_LFT_UNASSIGNED;
 
453
   return ( LFT[lid] );
 
454
}
 
455
 
 
456
//////////////////////////////////////////////////////////////////////////////
 
457
 
 
458
// Set the PSL Table:
 
459
void
 
460
IBNode::setPSLForLid (unsigned int lid, unsigned int maxLid, uint8_t sl) {
 
461
  if (PSL.empty())
 
462
  {
 
463
    PSL.resize(maxLid + 1);
 
464
    for(unsigned int i = 0; i<PSL.size(); i++)
 
465
      PSL[i] = IB_SLT_UNASSIGNED;
 
466
  }
 
467
  PSL[lid] = sl;
 
468
}
 
469
 
 
470
//////////////////////////////////////////////////////////////////////////////
 
471
 
 
472
// Get the PSL Table:
 
473
uint8_t
 
474
IBNode::getPSLForLid (unsigned int lid) {
 
475
  if (PSL.empty())
 
476
    return 0;
 
477
 
 
478
 if (PSL.size() < lid+1)
 
479
    return IB_SLT_UNASSIGNED;
 
480
 
 
481
  return PSL[lid];
 
482
}
 
483
 
 
484
//////////////////////////////////////////////////////////////////////////////
 
485
 
 
486
// Set the SL2VL Table:
 
487
void
 
488
IBNode::setSLVL (unsigned int iport,unsigned int oport,uint8_t sl, uint8_t vl) {
 
489
  // Create an empty table
 
490
  if (SLVL.empty())
 
491
  {
 
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;
 
499
      }
 
500
    }
 
501
  }
 
502
  SLVL[iport][oport][sl] = vl;
 
503
}
 
504
 
 
505
//////////////////////////////////////////////////////////////////////////////
 
506
 
 
507
// Get the SLVL Table:
 
508
uint8_t
 
509
IBNode::getSLVL (unsigned int iport,unsigned int oport,uint8_t sl) {
 
510
  // Identity mapping
 
511
  if (SLVL.empty())
 
512
    return sl;
 
513
 
 
514
  return SLVL[iport][oport][sl];
 
515
}
 
516
 
 
517
//////////////////////////////////////////////////////////////////////////////
 
518
// Set the Multicast FDB table
 
519
void
 
520
IBNode::setMFTPortForMLid(
 
521
   unsigned int lid,
 
522
   unsigned int portNum)
 
523
{
 
524
   if ((portNum > numPorts) || (portNum >= 64))
 
525
   {
 
526
      cout << "-E- setMFTPortForMLid : Given port:" << portNum
 
527
           << " is too high!" << endl;
 
528
      return;
 
529
   }
 
530
 
 
531
   // make sure the mlid is in range:
 
532
   if ((lid < 0xc000) || (lid > 0xffff))
 
533
   {
 
534
      cout << "-E- setMFTPortForMLid : Given lid:" << lid
 
535
           << " is out of range" << endl;
 
536
      return;
 
537
   }
 
538
 
 
539
   int idx = lid - 0xc000;
 
540
 
 
541
   // make sure we have enough vector:
 
542
   int prevSize = MFT.size();
 
543
   if (prevSize <= idx)
 
544
   {
 
545
      MFT.resize(idx + 10);
 
546
      for( int i = prevSize; i < idx + 10; i++)
 
547
         MFT[i]=0;
 
548
   }
 
549
 
 
550
   MFT[idx] |= (((uint64_t)1) << portNum);
 
551
 
 
552
   // we track all Groups:
 
553
   p_fabric->mcGroups.insert(lid);
 
554
 
 
555
}
 
556
 
 
557
//////////////////////////////////////////////////////////////////////////////
 
558
// Get the list of ports for the givan MLID from the MFT
 
559
list_int
 
560
IBNode::getMFTPortsForMLid(
 
561
   unsigned int lid)
 
562
{
 
563
   list_int res;
 
564
   // make sure the mlid is in range:
 
565
   if ((lid < 0xc000) || (lid > 0xffff))
 
566
   {
 
567
      cout << "-E- getMFTPortsForMLid : Given lid:" << lid
 
568
           << " is out of range" << endl;
 
569
      return res;
 
570
   }
 
571
 
 
572
   int idx = lid - 0xc000;
 
573
   if (MFT.size() <= idx)
 
574
      return res;
 
575
 
 
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);
 
579
 
 
580
   return res;
 
581
}
 
582
 
 
583
//////////////////////////////////////////////////////////////////////////////
 
584
//
 
585
// CLASS IBSysPort:
 
586
//
 
587
 
 
588
// Connect two system ports. This will update both sides pointers
 
589
void
 
590
IBSysPort::connect (IBSysPort *p_otherSysPort,
 
591
                    IBLinkWidth width,
 
592
                    IBLinkSpeed speed
 
593
                    ) {
 
594
   // we can not simply override existing connections
 
595
   if (p_remoteSysPort)
 
596
   {
 
597
      // we only do care if not the requested remote previously conn.
 
598
      if (p_remoteSysPort != p_otherSysPort)
 
599
      {
 
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)
 
608
         {
 
609
            p_remoteSysPort->p_remoteSysPort = NULL;
 
610
         }
 
611
      }
 
612
   }
 
613
   p_remoteSysPort = p_otherSysPort;
 
614
 
 
615
   // Check the other side was not previously connected
 
616
   if (p_otherSysPort->p_remoteSysPort)
 
617
   {
 
618
      if (p_otherSysPort->p_remoteSysPort != this)
 
619
      {
 
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)
 
630
         {
 
631
            p_otherSysPort->p_remoteSysPort->p_remoteSysPort = NULL;
 
632
         }
 
633
      }
 
634
   }
 
635
   p_otherSysPort->p_remoteSysPort = this;
 
636
 
 
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);
 
640
   else
 
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;
 
645
}
 
646
 
 
647
int
 
648
IBSysPort::disconnect(int duringPortDisconnect)
 
649
{
 
650
   if (!p_remoteSysPort)
 
651
   {
 
652
      cout << "-W- Trying to disconenct non connected system port." << endl;
 
653
      return(1);
 
654
   }
 
655
 
 
656
   if (p_remoteSysPort->p_remoteSysPort != this)
 
657
   {
 
658
      cout
 
659
         << "-W- Remote port does not point back! Disconnecting self only."
 
660
         << endl;
 
661
      p_remoteSysPort = NULL;
 
662
      return(1);
 
663
   }
 
664
 
 
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;
 
671
 
 
672
   // might need to treat the port too - but mark it duringPortDisconenct
 
673
   if (p_nodePort && ! duringPortDisconnect) return(p_nodePort->disconnect(1));
 
674
 
 
675
   return(0);
 
676
}
 
677
 
 
678
// Constructor:
 
679
IBSysPort::IBSysPort(string n, class IBSystem *p_sys)
 
680
{
 
681
   p_system = p_sys;
 
682
   name = n;
 
683
   p_nodePort = NULL;
 
684
   p_remoteSysPort = NULL;
 
685
   p_system->PortByName[name] = this;
 
686
}
 
687
 
 
688
// Distractor
 
689
IBSysPort::~IBSysPort() {
 
690
   if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
 
691
   {
 
692
      cout << "-I- Destructing SysPort:" << name << endl;
 
693
   }
 
694
 
 
695
   // if connected to another side remove the connection
 
696
   if (p_remoteSysPort)
 
697
      p_remoteSysPort->p_remoteSysPort = NULL;
 
698
 
 
699
   // remove from the map of the parent system
 
700
   if (p_system)
 
701
   {
 
702
      map_str_psysport::iterator pI = p_system->PortByName.find(name);
 
703
      if (pI != p_system->PortByName.end())
 
704
      {
 
705
         p_system->PortByName.erase(pI);
 
706
      }
 
707
   }
 
708
}
 
709
 
 
710
//////////////////////////////////////////////////////////////////////////////
 
711
//
 
712
// CLASS IBSystem:
 
713
//
 
714
 
 
715
// Destructor
 
716
IBSystem::~IBSystem() {
 
717
   if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
 
718
      cout << "-I- Destructing System:" << name << endl;
 
719
 
 
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;
 
725
      if (p_sysPort)
 
726
      {
 
727
         delete p_sysPort;
 
728
      }
 
729
   }
 
730
 
 
731
   // cleanup from parent fabric table of systems:
 
732
   if (p_fabric)
 
733
   {
 
734
      map_str_psys::iterator sI = p_fabric->SystemByName.find(name);
 
735
      if (sI != p_fabric->SystemByName.end())
 
736
         p_fabric->SystemByName.erase(sI);
 
737
   }
 
738
}
 
739
 
 
740
// make sure we got the port defined
 
741
IBSysPort *
 
742
IBSystem::makeSysPort (string pName) {
 
743
   IBSysPort *p_port;
 
744
   map_str_psysport::iterator pI = PortByName.find(pName);
 
745
   if (pI == PortByName.end())
 
746
   {
 
747
      p_port = new IBSysPort(pName, this);
 
748
      if (!p_port) return NULL;
 
749
      PortByName[pName] = p_port;
 
750
   }
 
751
   else
 
752
   {
 
753
      p_port = (*pI).second;
 
754
   }
 
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;
 
760
   return p_port;
 
761
}
 
762
 
 
763
//////////////////////////////////////////////////////////////////////////////
 
764
void
 
765
IBSystem::guid_set(uint64_t g) {
 
766
   if (p_fabric)
 
767
   {
 
768
      p_fabric->SystemByGuid[g] = this;
 
769
      guid = g;
 
770
   }
 
771
}
 
772
 
 
773
//////////////////////////////////////////////////////////////////////////////
 
774
 
 
775
IBSysPort *
 
776
IBSystem::getSysPort(string name) {
 
777
   IBSysPort *p_sysPort = NULL;
 
778
   map_str_psysport::iterator nI = PortByName.find(name);
 
779
   if (nI != PortByName.end())
 
780
   {
 
781
      p_sysPort = (*nI).second;
 
782
   }
 
783
   return p_sysPort;
 
784
}
 
785
 
 
786
//////////////////////////////////////////////////////////////////////////////
 
787
 
 
788
// constructor:
 
789
IBSystem::IBSystem(string n, class IBFabric *p_fab, string t) {
 
790
   if (p_fab->getSystem(n))
 
791
   {
 
792
      cerr << "Can't deal with double allocation of same system!" << endl;
 
793
      abort();
 
794
   }
 
795
   name = n;
 
796
   type = t;
 
797
   guid = 0;
 
798
   p_fabric = p_fab;
 
799
   p_fabric->SystemByName[n] = this;
 
800
}
 
801
 
 
802
//////////////////////////////////////////////////////////////////////////////
 
803
 
 
804
// Get a string with all the System Port Names (even if not connected)
 
805
list_str
 
806
IBSystem::getAllSysPortNames() {
 
807
   list_str portNames;
 
808
   for (map_str_psysport::iterator pI = PortByName.begin();
 
809
        pI != PortByName.end();
 
810
        pI++) {
 
811
      portNames.push_back((*pI).first);
 
812
   }
 
813
   return portNames;
 
814
}
 
815
 
 
816
//////////////////////////////////////////////////////////////////////////////
 
817
 
 
818
// get the node port for the given sys port by name
 
819
IBPort *
 
820
IBSystem::getSysPortNodePortByName (string sysPortName) {
 
821
   map_str_psysport::iterator pI = PortByName.find(sysPortName);
 
822
   if (pI != PortByName.end())
 
823
   {
 
824
      return ((*pI).second)->p_nodePort;
 
825
   }
 
826
   return NULL;
 
827
}
 
828
//////////////////////////////////////////////////////////////////////////////
 
829
 
 
830
// Split the given cfg into a vector of board cfg codes
 
831
void
 
832
IBSystem::cfg2Vector(const string& cfg,
 
833
                     vector<string>& boardCfgs,
 
834
                     int numBoards)
 
835
{
 
836
   unsigned int i;
 
837
   int b = 0;
 
838
   unsigned int prevDelim = 0;
 
839
   const char *p_str = cfg.c_str();
 
840
   char bcfg[16];
 
841
 
 
842
   // skip leading spaces:
 
843
   for (i = 0; (i < strlen(p_str)) && (
 
844
           (p_str[i] == '\t') || (p_str[i] == ' ')); i++);
 
845
   prevDelim = i;
 
846
 
 
847
   // scan each character:
 
848
   for (; (i < strlen(p_str)) && (b < numBoards); i++) {
 
849
      // either a delimiter or not:
 
850
      if (p_str[i] == ',')
 
851
      {
 
852
         strncpy(bcfg, p_str + prevDelim, i - prevDelim);
 
853
         bcfg[i - prevDelim] = '\0';
 
854
         boardCfgs.push_back(string(bcfg));
 
855
         prevDelim = i + 1;
 
856
         b++;
 
857
      }
 
858
   }
 
859
 
 
860
   if (prevDelim != i)
 
861
   {
 
862
      strncpy(bcfg, p_str + prevDelim, i - prevDelim);
 
863
      bcfg[i - prevDelim] = '\0';
 
864
      boardCfgs.push_back(string(bcfg));
 
865
      b++;
 
866
   }
 
867
 
 
868
   for (;b < numBoards; b++) {
 
869
      boardCfgs.push_back("");
 
870
   }
 
871
}
 
872
 
 
873
//////////////////////////////////////////////////////////////////////////////
 
874
 
 
875
// Remove a system board
 
876
int
 
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("/");
 
881
 
 
882
   // go through all the system nodes.
 
883
   for (map_str_pnode::iterator nI = p_fabric->NodeByName.begin();
 
884
        nI != p_fabric->NodeByName.end();
 
885
        nI++) {
 
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())))
 
889
      {
 
890
         matchedNodes.push_back((*nI).second);
 
891
      }
 
892
   }
 
893
 
 
894
   // Warn if no match:
 
895
   if (matchedNodes.empty())
 
896
   {
 
897
      cout << "-W- removeBoard : Fail to find any node in:"
 
898
           << sysNodePrefix << " while removing:" << boardName << endl;
 
899
      return 1;
 
900
   }
 
901
 
 
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);
 
909
      delete p_node;
 
910
      matchedNodes.erase(lI);
 
911
      lI = matchedNodes.begin();
 
912
   }
 
913
 
 
914
   return 0;
 
915
}
 
916
 
 
917
//////////////////////////////////////////////////////////////////////////////
 
918
 
 
919
// Write out the system IBNL into the given directory
 
920
// and return the new system type
 
921
//
 
922
// We are facing here a "heuristic" approach for how one knows
 
923
// the number of system ports - since some may be added later.
 
924
// 
 
925
// In the case of a single device system we can and should expose
 
926
// all device ports - simply as P<pn>.
 
927
//
 
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)
 
930
int
 
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
 
934
   // device ID
 
935
   if (NodeByName.size() == 1)
 
936
   {
 
937
      map_str_pnode::iterator nI = NodeByName.begin();
 
938
      IBNode *p_node = (*nI).second;
 
939
      sprintf(sysTypeStr, "DEV%u", p_node->devId);
 
940
   }
 
941
   else
 
942
   {
 
943
      sprintf(sysTypeStr, "SYS%x", guid);
 
944
   }
 
945
   sysType = string(sysTypeStr);
 
946
   string fileName = string(ibnlDir) + string("/") + sysType + string(".ibnl");
 
947
   ofstream ibnl;
 
948
   ibnl.open(fileName.c_str());
 
949
 
 
950
   if (ibnl.fail())
 
951
   {
 
952
      cout << "-E- Failed to write IBNL into file:" << fileName << endl;
 
953
      return 1;
 
954
   }
 
955
 
 
956
   ibnl << "TOPSYSTEM " << sysType << endl;
 
957
 
 
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)
 
965
      {
 
966
         ibnl << "\nNODE SW " << p_node->numPorts << " "
 
967
              << "DEV" << p_node->devId << " " << nameWithoutSysName.c_str() << endl;
 
968
      }
 
969
      else
 
970
      {
 
971
         ibnl << "\nNODE CA " << p_node->numPorts << " "
 
972
              << "DEV" << p_node->devId << " " << nameWithoutSysName.c_str() << endl;
 
973
      }
 
974
 
 
975
      for (unsigned int pn = 1; pn <= p_node->numPorts; pn++) {
 
976
         IBPort *p_port = p_node->getPort(pn);
 
977
 
 
978
                        if (NodeByName.size() == 1) {
 
979
                          // invent a port ...
 
980
                          char buf[128];
 
981
                          sprintf(buf,"%s/P%u", nameWithoutSysName.c_str(), pn);
 
982
                          ibnl << "   " << pn << " -> " << buf << endl;
 
983
                        } else {
 
984
                          if (! p_port) continue;
 
985
                        }
 
986
 
 
987
         if (p_port->p_sysPort)
 
988
         {
 
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;
 
997
         }
 
998
      }
 
999
   }
 
1000
 
 
1001
   ibnl.close();
 
1002
   return 0;
 
1003
}
 
1004
 
 
1005
//////////////////////////////////////////////////////////////////////////////
 
1006
//
 
1007
// CLASS IBFabric:
 
1008
//
 
1009
 
 
1010
// Destructor:
 
1011
IBFabric::~IBFabric() {
 
1012
   // cleanup all Systems and Nodes:
 
1013
 
 
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;
 
1019
      delete p_node;
 
1020
   }
 
1021
 
 
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;
 
1027
      delete p_sys;
 
1028
   }
 
1029
}
 
1030
 
 
1031
//////////////////////////////////////////////////////////////////////////////
 
1032
//
 
1033
// CLASS IBFabric:
 
1034
//
 
1035
 
 
1036
// make a new node if can not find it by name
 
1037
IBNode *
 
1038
IBFabric::makeNode (string n, IBSystem *p_sys, IBNodeType type,
 
1039
                    unsigned int numPorts) {
 
1040
   IBNode *p_node;
 
1041
   map_str_pnode::iterator nI = NodeByName.find(n);
 
1042
   if (nI == NodeByName.end())
 
1043
   {
 
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;
 
1048
   }
 
1049
   else
 
1050
   {
 
1051
      p_node = (*nI).second;
 
1052
   }
 
1053
 
 
1054
   // if the fabric require all ports to be declared do it:
 
1055
   if (defAllPorts)
 
1056
      for (unsigned int i = 1; i <= numPorts; i++)
 
1057
         p_node->makePort(i);
 
1058
 
 
1059
   return p_node;
 
1060
}
 
1061
 
 
1062
//////////////////////////////////////////////////////////////////////////////
 
1063
 
 
1064
// Look for the node by its name
 
1065
IBNode *
 
1066
IBFabric::getNode (string name) {
 
1067
   IBNode *p_node = NULL;
 
1068
   map_str_pnode::iterator nI = NodeByName.find(name);
 
1069
   if (nI != NodeByName.end())
 
1070
   {
 
1071
      p_node = (*nI).second;
 
1072
   }
 
1073
   return p_node;
 
1074
}
 
1075
 
 
1076
/////////////////////////////////////////////////////////////////////////////
 
1077
 
 
1078
IBPort *
 
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())
 
1083
   {
 
1084
      p_port = (*nI).second;
 
1085
   }
 
1086
   return p_port;
 
1087
}
 
1088
 
 
1089
IBNode *
 
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())
 
1094
   {
 
1095
      p_node = (*nI).second;
 
1096
   }
 
1097
   return p_node;
 
1098
}
 
1099
 
 
1100
IBSystem *
 
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())
 
1105
   {
 
1106
      p_system = (*nI).second;
 
1107
   }
 
1108
   return p_system;
 
1109
}
 
1110
 
 
1111
/////////////////////////////////////////////////////////////////////////////
 
1112
 
 
1113
// return the list of node pointers matching the required type
 
1114
list_pnode *
 
1115
IBFabric::getNodesByType (IBNodeType type) {
 
1116
 
 
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))
 
1120
      {
 
1121
         res->push_back(((*nI).second));
 
1122
      }
 
1123
   }
 
1124
   return res;
 
1125
}
 
1126
 
 
1127
//////////////////////////////////////////////////////////////////////////////
 
1128
// convert the given configuration string to modifiers list
 
1129
// The syntax of the modifier string is comma sep board=modifier pairs
 
1130
static int
 
1131
cfgStrToModifiers(string cfg, map_str_str &mods) {
 
1132
   unsigned int i;
 
1133
   unsigned int prevDelim = 0;
 
1134
   const char *p_str = cfg.c_str();
 
1135
   char bcfg[64];
 
1136
 
 
1137
   // skip leading spaces:
 
1138
   for (i = 0; (i < strlen(p_str)) && (
 
1139
           (p_str[i] == '\t') || (p_str[i] == ' ')); i++);
 
1140
   prevDelim = i;
 
1141
 
 
1142
   // scan each character:
 
1143
   for (;i < strlen(p_str); i++) {
 
1144
      // either a delimiter or not:
 
1145
      if (p_str[i] == ',')
 
1146
      {
 
1147
         strncpy(bcfg, p_str + prevDelim, i - prevDelim);
 
1148
         bcfg[i - prevDelim] = '\0';
 
1149
         char *eqSign = strchr(bcfg, '=');
 
1150
         if (eqSign)
 
1151
         {
 
1152
            eqSign[0] = '\0';
 
1153
            string key = bcfg;
 
1154
            string val = ++eqSign;
 
1155
            mods[key] = val;
 
1156
         }
 
1157
         else
 
1158
         {
 
1159
            cout << "-E- Bad modifier syntax:" << bcfg
 
1160
                 << "expected: board=modifier" << endl;
 
1161
         }
 
1162
         prevDelim = i + 1;
 
1163
      }
 
1164
   }
 
1165
 
 
1166
   if (prevDelim != i)
 
1167
   {
 
1168
      strncpy(bcfg, p_str + prevDelim, i - prevDelim);
 
1169
      bcfg[i - prevDelim] = '\0';
 
1170
      char *eqSign = strchr(bcfg, '=');
 
1171
      if (eqSign)
 
1172
      {
 
1173
         eqSign[0] = '\0';
 
1174
         string key = bcfg;
 
1175
         string val = ++eqSign;
 
1176
         mods[key] = val;
 
1177
      }
 
1178
      else
 
1179
      {
 
1180
         cout << "-E- Bad modifier syntax:" << bcfg
 
1181
              << "expected: board=modifier" << endl;
 
1182
      }
 
1183
   }
 
1184
   return(0);
 
1185
}
 
1186
 
 
1187
//////////////////////////////////////////////////////////////////////////////
 
1188
 
 
1189
// crate a new generic system - basically an empty contaner for nodes...
 
1190
IBSystem *
 
1191
IBFabric::makeGenericSystem (string name) {
 
1192
 
 
1193
   IBSystem *p_sys;
 
1194
 
 
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())
 
1198
   {
 
1199
      p_sys = new IBSystem(name,this,"Generic");
 
1200
   }
 
1201
   else
 
1202
   {
 
1203
      p_sys = (*sI).second;
 
1204
   }
 
1205
   return p_sys;
 
1206
}
 
1207
 
 
1208
//////////////////////////////////////////////////////////////////////////////
 
1209
// crate a new system - the type must have a predefined sysdef
 
1210
IBSystem *
 
1211
IBFabric::makeSystem (string name, string type, string cfg) {
 
1212
 
 
1213
   IBSystem *p_sys;
 
1214
 
 
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())
 
1218
   {
 
1219
 
 
1220
      // We base our system building on the system definitions:
 
1221
      map_str_str mods;
 
1222
 
 
1223
      // convert the given configuration string to modifiers map
 
1224
      cfgStrToModifiers(cfg, mods);
 
1225
 
 
1226
      p_sys = theSysDefsCollection()->makeSystem(this, name, type, mods);
 
1227
 
 
1228
      if (!p_sys)
 
1229
      {
 
1230
         cout << "-E- Fail to find System class:" << type
 
1231
              << endl;
 
1232
         return NULL;
 
1233
      }
 
1234
 
 
1235
      SystemByName[name] = p_sys;
 
1236
 
 
1237
      // if the fabric require all ports to be declared do it:
 
1238
      if (defAllPorts)
 
1239
      {
 
1240
         list_str portNames = p_sys->getAllSysPortNames();
 
1241
         for (list_str::const_iterator pnI = portNames.begin();
 
1242
              pnI != portNames.end();
 
1243
              pnI++) {
 
1244
            p_sys->makeSysPort(*pnI);
 
1245
         }
 
1246
      }
 
1247
   }
 
1248
   else
 
1249
   {
 
1250
      p_sys = (*sI).second;
 
1251
   }
 
1252
   return p_sys;
 
1253
}
 
1254
 
 
1255
//////////////////////////////////////////////////////////////////////////////
 
1256
 
 
1257
// Look for the system by its name
 
1258
IBSystem *
 
1259
IBFabric::getSystem (string name) {
 
1260
   IBSystem *p_system = NULL;
 
1261
   map_str_psys::iterator nI = SystemByName.find(name);
 
1262
   if (nI != SystemByName.end())
 
1263
   {
 
1264
      p_system = (*nI).second;
 
1265
   }
 
1266
   return p_system;
 
1267
}
 
1268
 
 
1269
//////////////////////////////////////////////////////////////////////////////
 
1270
 
 
1271
// Add a cable connection
 
1272
int
 
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);
 
1279
 
 
1280
   // check please:
 
1281
   if (! (p_sys1 && p_sys2))
 
1282
   {
 
1283
      cout << "-E- Fail to make either systems:" << n1 << " or:"
 
1284
           << n2 << endl;
 
1285
      return 1;
 
1286
   }
 
1287
 
 
1288
   // check types
 
1289
   if (p_sys1->type != t1)
 
1290
   {
 
1291
      cout << "-W- Provided System1 Type:" << t1
 
1292
           << " does not match pre-existing system:" << n1
 
1293
           << " type:" << p_sys1->type << endl;
 
1294
   }
 
1295
 
 
1296
   if (p_sys2->type != t2)
 
1297
   {
 
1298
      cout << "-W- Provided System1 Type:" << t2
 
1299
           << " does not match pre-existing system:" << n2
 
1300
           << " type:" << p_sys2->type << endl;
 
1301
   }
 
1302
 
 
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;
 
1307
 
 
1308
   // make sure they are not previously connected otherwise
 
1309
   if (p_port1->p_remoteSysPort && (p_port1->p_remoteSysPort != p_port2))
 
1310
   {
 
1311
      cout << "-E- Port:"
 
1312
           << p_port1->p_system->name << "/"
 
1313
           << p_port1->name
 
1314
           << " already connected to:"
 
1315
           << p_port1->p_remoteSysPort->p_system->name << "/"
 
1316
           << p_port1->p_remoteSysPort->name <<endl;
 
1317
      return 1;
 
1318
   }
 
1319
 
 
1320
   if (p_port2->p_remoteSysPort && (p_port2->p_remoteSysPort != p_port1))
 
1321
   {
 
1322
      cout << "-E- Port:"
 
1323
           << p_port2->p_system->name << "/"
 
1324
           << p_port2->name
 
1325
           << " already connected to:"
 
1326
           << p_port2->p_remoteSysPort->p_system->name << "/"
 
1327
           << p_port2->p_remoteSysPort->name << endl;
 
1328
      return 1;
 
1329
   }
 
1330
 
 
1331
   // connect them
 
1332
   p_port1->connect(p_port2, width, speed);
 
1333
   p_port2->connect(p_port1, width, speed);
 
1334
   return 0;
 
1335
}
 
1336
 
 
1337
//////////////////////////////////////////////////////////////////////////////
 
1338
 
 
1339
// Parse the cabling definition file
 
1340
int
 
1341
IBFabric::parseCables (string fn) {
 
1342
   ifstream f(fn.c_str());
 
1343
   char sLine[1024];
 
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]*$)");
 
1347
   rexMatch *p_rexRes;
 
1348
   IBLinkSpeed speed = IB_UNKNOWN_LINK_SPEED;
 
1349
   IBLinkWidth width = IB_UNKNOWN_LINK_WIDTH;
 
1350
 
 
1351
   if (! f)
 
1352
   {
 
1353
      cout << "-E- Fail to open file:" << fn.c_str() << endl;
 
1354
      return 1;
 
1355
   }
 
1356
 
 
1357
   cout << "-I- Parsing cabling definition:" << fn.c_str() << endl;
 
1358
 
 
1359
   int numCables = 0;
 
1360
   int lineNum = 0;
 
1361
   while (f.good()) {
 
1362
      lineNum++;
 
1363
      f.getline(sLine,1024);
 
1364
      // <SysType1> <sysName1> <portName1> <SysType2> <sysName2> <portName2>
 
1365
      p_rexRes = cablingLine.apply(sLine);
 
1366
 
 
1367
      if (p_rexRes)
 
1368
      {
 
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))
 
1376
         {
 
1377
            cout << "-E- Fail to make cable"
 
1378
                 << " (line:" << lineNum << ")"
 
1379
                 << endl;
 
1380
            delete p_rexRes;
 
1381
            return 1;
 
1382
         }
 
1383
         numCables++;
 
1384
         delete p_rexRes;
 
1385
         continue;
 
1386
      }
 
1387
 
 
1388
      // check if leagel ignored line
 
1389
      p_rexRes = ignoreLine.apply(sLine);
 
1390
      if (p_rexRes)
 
1391
      {
 
1392
         delete p_rexRes;
 
1393
      }
 
1394
      else
 
1395
      {
 
1396
         cout << "-E- Bad syntax on line:" << sLine << endl;
 
1397
      }
 
1398
   }
 
1399
 
 
1400
   cout << "-I- Defined " << SystemByName.size() << "/" << NodeByName.size() <<
 
1401
      " systems/nodes " << endl;
 
1402
   f.close();
 
1403
   return 0;
 
1404
}
 
1405
 
 
1406
//////////////////////////////////////////////////////////////////////////////
 
1407
 
 
1408
// Parse the topology definition file
 
1409
int
 
1410
IBFabric::parseTopology (string fn) {
 
1411
   ifstream f(fn.c_str());
 
1412
   char sLine[1024];
 
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]*$");
 
1420
   rexMatch *p_rexRes;
 
1421
   IBSystem *p_system = NULL;
 
1422
   IBLinkSpeed speed;
 
1423
   IBLinkWidth width;
 
1424
 
 
1425
   if (! f.is_open())
 
1426
   {
 
1427
      cout << "-E- Fail to open file:" << fn.c_str() << endl;
 
1428
      return 1;
 
1429
   }
 
1430
 
 
1431
   cout << "-I- Parsing topology definition:" << fn.c_str() << endl;
 
1432
 
 
1433
   // we need two passes since we only get system configuration
 
1434
   // on a system definition line.
 
1435
   int lineNum = 0;
 
1436
   while (f.good()) {
 
1437
      lineNum++;
 
1438
      f.getline(sLine,1024);
 
1439
 
 
1440
      // check if legal ignored line
 
1441
      p_rexRes = ignoreLine.apply(sLine);
 
1442
      if (p_rexRes)
 
1443
      {
 
1444
         delete p_rexRes;
 
1445
         continue;
 
1446
      }
 
1447
 
 
1448
      // First look for system line:
 
1449
      p_rexRes = sysLine.apply(sLine);
 
1450
 
 
1451
      if (p_rexRes)
 
1452
      {
 
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);
 
1457
 
 
1458
         // check please:
 
1459
         if (! p_system)
 
1460
         {
 
1461
            cout << "-E- Fail to make system:" << n1
 
1462
                 << " of type:" <<  t1
 
1463
                 << " (line:" << lineNum << ")"
 
1464
                 << endl;
 
1465
            delete p_rexRes;
 
1466
            return 1;
 
1467
         }
 
1468
         delete p_rexRes;
 
1469
         continue;
 
1470
      }
 
1471
   }
 
1472
 
 
1473
   lineNum = 0;
 
1474
   f.close();
 
1475
   f.clear();
 
1476
   f.open(fn.c_str());
 
1477
 
 
1478
   if (! f.is_open())
 
1479
   {
 
1480
      cout << "-E- Fail to re open file:" << fn.c_str() << endl;
 
1481
      return 1;
 
1482
   }
 
1483
 
 
1484
   int numCables = 0;
 
1485
 
 
1486
   while (f.good()) {
 
1487
      lineNum++;
 
1488
      f.getline(sLine,1024);
 
1489
 
 
1490
      // check if legal ignored line
 
1491
      p_rexRes = ignoreLine.apply(sLine);
 
1492
      if (p_rexRes)
 
1493
      {
 
1494
         delete p_rexRes;
 
1495
         continue;
 
1496
      }
 
1497
 
 
1498
      // look for system line:
 
1499
      p_rexRes = sysLine.apply(sLine);
 
1500
 
 
1501
      if (p_rexRes)
 
1502
      {
 
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);
 
1507
 
 
1508
         // check please:
 
1509
         if (! p_system)
 
1510
         {
 
1511
            cout << "-E- Fail to make system:" << n1
 
1512
                 << " of type:" <<  t1
 
1513
                 << " (line:" << lineNum << ")"
 
1514
                 << endl;
 
1515
            delete p_rexRes;
 
1516
            return 1;
 
1517
         }
 
1518
         delete p_rexRes;
 
1519
         continue;
 
1520
      }
 
1521
 
 
1522
      // is it a port line:
 
1523
      p_rexRes = portLine.apply(sLine);
 
1524
      if (p_rexRes)
 
1525
      {
 
1526
         if (p_system)
 
1527
         {
 
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;
 
1535
 
 
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))
 
1540
            {
 
1541
               cout << "-E- Fail to make cable"
 
1542
                    << " (line:" << lineNum << ")"
 
1543
                    << endl;
 
1544
               delete p_rexRes;
 
1545
               return 1;
 
1546
            }
 
1547
            numCables++;
 
1548
         }
 
1549
         else
 
1550
         {
 
1551
            cout << "-E- Fail to make connection as local system "
 
1552
                 << "not defined (line:" << lineNum << ")"
 
1553
                 << endl;
 
1554
            delete p_rexRes;
 
1555
            return 1;
 
1556
         }
 
1557
         delete p_rexRes;
 
1558
         continue;
 
1559
      }
 
1560
 
 
1561
      // check if empty line - marking system end:
 
1562
      p_rexRes = emptyLine.apply(sLine);
 
1563
      if (p_rexRes)
 
1564
      {
 
1565
         p_system = NULL;
 
1566
         delete p_rexRes;
 
1567
         continue;
 
1568
      }
 
1569
 
 
1570
      cout << "-W- Ignoring '" << sLine << "'"
 
1571
           << " (line:" << lineNum << ")" << endl;
 
1572
   }
 
1573
 
 
1574
   cout << "-I- Defined " << SystemByName.size() << "/"
 
1575
        << NodeByName.size() << " systems/nodes " << endl;
 
1576
   f.close();
 
1577
   return 0;
 
1578
}
 
1579
 
 
1580
//////////////////////////////////////////////////////////////////////////////
 
1581
 
 
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 ...
 
1589
int
 
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
 
1599
                  ) {
 
1600
 
 
1601
   IBSystem *p_sys1, *p_sys2;
 
1602
   IBNode *p_node1, *p_node2;
 
1603
   char buf[256];
 
1604
 
 
1605
   // make sure the system1 exists
 
1606
   if (!desc1.size())
 
1607
   {
 
1608
      sprintf(buf, "S%016" PRIx64, sysGuid1);
 
1609
      string sysName1 = string(buf);
 
1610
      p_sys1 = makeGenericSystem(sysName1);
 
1611
   }
 
1612
   else
 
1613
   {
 
1614
      p_sys1 = makeGenericSystem(desc1);
 
1615
   }
 
1616
 
 
1617
   if (!desc2.size())
 
1618
   {
 
1619
      sprintf(buf, "S%016" PRIx64, sysGuid2);
 
1620
      string sysName2 = string(buf);
 
1621
      p_sys2 = makeGenericSystem(sysName2);
 
1622
   }
 
1623
   else
 
1624
   {
 
1625
      p_sys2 = makeGenericSystem(desc2);
 
1626
   }
 
1627
 
 
1628
   // make sure the nodes exists
 
1629
   p_node1 = getNodeByGuid(nodeGuid1);
 
1630
   if (! p_node1)
 
1631
   {
 
1632
      // if we got a desc name
 
1633
      if ((type1 != "SW") && desc1.size())
 
1634
      {
 
1635
         sprintf(buf,"%s/U%d", desc1.c_str(), hcaIdx1);
 
1636
      }
 
1637
      else
 
1638
      {
 
1639
         sprintf(buf,"%s/U%d", p_sys1->name.c_str(),
 
1640
                 p_sys1->NodeByName.size() + 1);
 
1641
      }
 
1642
      if (type1 == "SW")
 
1643
      {
 
1644
         p_node1 = makeNode(buf, p_sys1, IB_SW_NODE, numPorts1);
 
1645
      }
 
1646
      else
 
1647
      {
 
1648
         p_node1 = makeNode(buf, p_sys1, IB_CA_NODE, numPorts1);
 
1649
      }
 
1650
      p_node1->guid_set(nodeGuid1);
 
1651
   }
 
1652
 
 
1653
   p_node2 = getNodeByGuid(nodeGuid2);
 
1654
   if (! p_node2)
 
1655
   {
 
1656
      // if we got a desc name
 
1657
      if ((type2 != "SW") && desc2.size())
 
1658
         sprintf(buf,"%s/U%d", desc2.c_str(), hcaIdx2);
 
1659
      else
 
1660
         sprintf(buf,"%s/U%d", p_sys2->name.c_str(),
 
1661
                 p_sys2->NodeByName.size() + 1);
 
1662
      if (type2 == "SW")
 
1663
      {
 
1664
         p_node2 = makeNode(buf, p_sys2, IB_SW_NODE, numPorts2);
 
1665
      }
 
1666
      else
 
1667
      {
 
1668
         p_node2 = makeNode(buf, p_sys2, IB_CA_NODE, numPorts2);
 
1669
      }
 
1670
      p_node2->guid_set(nodeGuid2);
 
1671
   }
 
1672
 
 
1673
   // we want to use the host names if they are defined:
 
1674
   if (desc1.size())
 
1675
      p_node1->attributes = string("host=") + desc1;
 
1676
 
 
1677
   if (desc2.size())
 
1678
      p_node2->attributes = string("host=") + desc2;
 
1679
 
 
1680
   IBSysPort *p_sysPort1 = 0, *p_sysPort2 = 0;
 
1681
 
 
1682
   // create system ports if required
 
1683
   if (sysGuid1 != sysGuid2)
 
1684
   {
 
1685
      if (type1 == "SW" || desc1.size() == 0 || hcaIdx1 != 1)
 
1686
      {
 
1687
         // avoid adding the sys name to the port...
 
1688
         if (p_sys1->name == p_node1->name.substr(0, p_sys1->name.length()))
 
1689
         {
 
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);
 
1694
         }
 
1695
         else
 
1696
         {
 
1697
            sprintf(buf,"%s/P%u", p_node1->name.c_str(), portNum1);
 
1698
         }
 
1699
      }
 
1700
      else
 
1701
      {
 
1702
         sprintf(buf,"P%u", portNum1);
 
1703
      }
 
1704
      p_sysPort1 = p_sys1->getSysPort(buf);
 
1705
      if (p_sysPort1 == NULL)
 
1706
         p_sysPort1 = new IBSysPort(buf, p_sys1);
 
1707
 
 
1708
      if (type2 == "SW" || desc2.size() == 0 || hcaIdx2 != 1)
 
1709
      {
 
1710
         if (p_sys2->name == p_node2->name.substr(0, p_sys2->name.length()))
 
1711
         {
 
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);
 
1716
         }
 
1717
         else
 
1718
         {
 
1719
            sprintf(buf,"%s/P%u", p_node2->name.c_str(), portNum2);
 
1720
         }
 
1721
      }
 
1722
      else
 
1723
      {
 
1724
         sprintf(buf,"P%u", portNum2);
 
1725
      }
 
1726
      p_sysPort2 = p_sys2->getSysPort(buf);
 
1727
      if (p_sysPort2 == NULL)
 
1728
         p_sysPort2 = new IBSysPort(buf, p_sys2);
 
1729
   }
 
1730
 
 
1731
   // make sure the ports exits
 
1732
   IBPort *p_port1 = p_node1->makePort(portNum1);
 
1733
   IBPort *p_port2 = p_node2->makePort(portNum2);
 
1734
 
 
1735
   // we know the guids so set them
 
1736
   p_sys1->guid_set(sysGuid1);
 
1737
   p_sys2->guid_set(sysGuid2);
 
1738
 
 
1739
   p_node1->guid_set(nodeGuid1);
 
1740
   p_node2->guid_set(nodeGuid2);
 
1741
   p_port1->guid_set(portGuid1);
 
1742
   p_port2->guid_set(portGuid2);
 
1743
 
 
1744
   // copy some data...
 
1745
   p_node1->devId  = devId1;
 
1746
   p_node1->revId  = rev1;
 
1747
   p_node1->vendId = vend1;
 
1748
 
 
1749
   p_node2->devId  = devId2;
 
1750
   p_node2->revId  = rev2;
 
1751
   p_node2->vendId = vend2;
 
1752
 
 
1753
   // handle LMC :
 
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);
 
1761
 
 
1762
   // connect
 
1763
   if (p_sysPort1)
 
1764
   {
 
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);
 
1771
   }
 
1772
   else
 
1773
   {
 
1774
      p_port1->connect(p_port2, width, speed);
 
1775
      p_port2->connect(p_port1, width, speed);
 
1776
   }
 
1777
 
 
1778
   if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
 
1779
      cout << "-V- Connecting Lid:" << lid1 << " Port:" << portNum1
 
1780
           << " to Lid:" << lid2 << " Port:" << portNum2 << endl;
 
1781
   return 0;
 
1782
}
 
1783
 
 
1784
 
 
1785
//////////////////////////////////////////////////////////////////////////////
 
1786
 
 
1787
// Parse a single subnet line using strtok for simplicity...
 
1788
int
 
1789
IBFabric::parseSubnetLine(char *line) {
 
1790
 
 
1791
   string type1, desc1;
 
1792
   unsigned int  numPorts1, vend1, devId1, rev1, lid1, portNum1, hcaIdx1 = 0;
 
1793
   uint64_t sysGuid1, nodeGuid1, portGuid1;
 
1794
 
 
1795
   string type2, desc2;
 
1796
   unsigned int  numPorts2, vend2, devId2, rev2, lid2, portNum2, hcaIdx2 = 0;
 
1797
   uint64_t sysGuid2, nodeGuid2, portGuid2;
 
1798
   IBLinkSpeed speed;
 
1799
   IBLinkWidth width;
 
1800
 
 
1801
   char *pch;
 
1802
 
 
1803
   // do the first Port...
 
1804
   pch = strtok(line, " ");
 
1805
   if (!pch || pch[0] != '{') return(1);
 
1806
 
 
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";
 
1810
 
 
1811
   pch = strtok(NULL, " ");
 
1812
   if (!pch || strncmp(pch,"Ports:",6)) return(3);
 
1813
   numPorts1 = strtol(pch+6, NULL,16);
 
1814
 
 
1815
   pch = strtok(NULL, " ");
 
1816
   if (!pch || strncmp(pch,"SystemGUID:",11)) return(4);
 
1817
   sysGuid1 = strtoull(pch+11, NULL, 16);
 
1818
 
 
1819
   pch = strtok(NULL, " ");
 
1820
   if (!pch || strncmp(pch,"NodeGUID:",9)) return(5);
 
1821
   nodeGuid1 = strtoull(pch+9, NULL, 16);
 
1822
 
 
1823
   pch = strtok(NULL, " ");
 
1824
   if (!pch || strncmp(pch,"PortGUID:",9)) return(6);
 
1825
   portGuid1 = strtoull(pch+9, NULL, 16);
 
1826
 
 
1827
   pch = strtok(NULL, " ");
 
1828
   if (!pch || strncmp(pch,"VenID:",6)) return(7);
 
1829
   vend1 = strtol(pch+6, NULL, 16);
 
1830
 
 
1831
   pch = strtok(NULL, " ");
 
1832
   if (!pch || strncmp(pch,"DevID:",6)) return(8);
 
1833
   char *pdid1 = pch+6;
 
1834
   pch = strtok(NULL, " ");
 
1835
 
 
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);
 
1840
 
 
1841
   if (!pch || strncmp(pch,"Rev:",4)) return(9);
 
1842
   rev1 = strtol(pch+4, NULL, 16);
 
1843
 
 
1844
   // on some installations the desc of the node holds the
 
1845
   // name of the hosts:
 
1846
   if (subnCANames && (type1 == "CA"))
 
1847
   {
 
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))
 
1853
      {
 
1854
         desc1 = string(pch+1);
 
1855
         hcaIdx1 = atoi(pch + strlen(pch) + 5);
 
1856
      }
 
1857
   }
 
1858
   // on some rare cases there is no space in desc:
 
1859
   if (!strchr(pch,'}'))
 
1860
   {
 
1861
      pch = strtok(NULL, "}");
 
1862
      if (!pch ) return(10);
 
1863
   }
 
1864
 
 
1865
   pch = strtok(NULL, " ");
 
1866
   if (!pch || strncmp(pch,"LID:", 4)) return(11);
 
1867
   lid1 = strtol(pch+4, NULL, 16);
 
1868
 
 
1869
   pch = strtok(NULL, " ");
 
1870
   if (!pch || strncmp(pch,"PN:", 3)) return(12);
 
1871
   portNum1 = strtol(pch+3, NULL, 16);
 
1872
 
 
1873
   pch = strtok(NULL, " ");
 
1874
   if (!pch || pch[0] != '}') return(13);
 
1875
 
 
1876
   pch = strtok(NULL, " ");
 
1877
   if (!pch || pch[0] != '{') return(14);
 
1878
 
 
1879
   // second port
 
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";
 
1883
 
 
1884
   pch = strtok(NULL, " ");
 
1885
   if (!pch || strncmp(pch,"Ports:",6)) return(16);
 
1886
   numPorts2 = strtol(pch+6, NULL,16);
 
1887
 
 
1888
   pch = strtok(NULL, " ");
 
1889
   if (!pch || strncmp(pch,"SystemGUID:",11)) return(17);
 
1890
   sysGuid2 = strtoull(pch+11, NULL, 16);
 
1891
 
 
1892
   pch = strtok(NULL, " ");
 
1893
   if (!pch || strncmp(pch,"NodeGUID:",9)) return(18);
 
1894
   nodeGuid2 = strtoull(pch+9, NULL, 16);
 
1895
 
 
1896
   pch = strtok(NULL, " ");
 
1897
   if (!pch || strncmp(pch,"PortGUID:",9)) return(19);
 
1898
   portGuid2 = strtoull(pch+9, NULL, 16);
 
1899
 
 
1900
   pch = strtok(NULL, " ");
 
1901
   if (!pch || strncmp(pch,"VenID:",6)) return(20);
 
1902
   vend2 = strtol(pch+6, NULL, 16);
 
1903
 
 
1904
   pch = strtok(NULL, " ");
 
1905
   if (!pch || strncmp(pch,"DevID:",6)) return(21);
 
1906
   char *pdid2 = pch+6;
 
1907
   pch = strtok(NULL, " ");
 
1908
 
 
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);
 
1913
 
 
1914
   if (!pch || strncmp(pch,"Rev:",4)) return(22);
 
1915
   rev2 = strtol(pch+4, NULL, 16);
 
1916
 
 
1917
   if (subnCANames && (type2 == "CA"))
 
1918
   {
 
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))
 
1923
      {
 
1924
         desc2 = string(pch+1);
 
1925
         hcaIdx2 = atoi(pch + strlen(pch) + 5);
 
1926
      }
 
1927
   }
 
1928
   // on some rare cases there is no space in desc:
 
1929
   if (!strchr(pch,'}'))
 
1930
   {
 
1931
      pch = strtok(NULL, "}");
 
1932
      if (!pch ) return(23);
 
1933
   }
 
1934
 
 
1935
   pch = strtok(NULL, " ");
 
1936
   if (!pch || strncmp(pch,"LID:", 4)) return(24);
 
1937
   lid2 = strtol(pch+4, NULL, 16);
 
1938
 
 
1939
   pch = strtok(NULL, " ");
 
1940
   if (!pch || strncmp(pch,"PN:", 3)) return(25);
 
1941
   portNum2 = strtol(pch+3, NULL, 16);
 
1942
 
 
1943
   pch = strtok(NULL, " ");
 
1944
   if (!pch || pch[0] != '}') return(26);
 
1945
 
 
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);
 
1950
 
 
1951
   pch = strtok(NULL, " ");
 
1952
   if (!pch || strncmp(pch,"LOG=",4)) return(28);
 
1953
 
 
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);
 
1958
 
 
1959
   // speed is optional ... s
 
1960
   pch = strtok(NULL, " ");
 
1961
   if (pch && !strncmp(pch,"SPD=",4))
 
1962
   {
 
1963
      speed = char2speed(pch+4);
 
1964
   } else if (!pch) {
 
1965
      speed = IB_LINK_SPEED_2_5;
 
1966
   }
 
1967
   else
 
1968
   {
 
1969
      return(29);
 
1970
   }
 
1971
 
 
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,
 
1976
               width, speed
 
1977
               )) return (30);
 
1978
   return(0);
 
1979
}
 
1980
 
 
1981
// Parse an OpenSM Subnet file and build the fabric accordingly
 
1982
int
 
1983
IBFabric::parseSubnetLinks (string fn) {
 
1984
   ifstream f(fn.c_str());
 
1985
 
 
1986
   char sLine[1024];
 
1987
   int status;
 
1988
 
 
1989
   if (! f)
 
1990
   {
 
1991
      cout << "-E- Fail to open file:" << fn.c_str() << endl;
 
1992
      return 1;
 
1993
   }
 
1994
 
 
1995
   cout << "-I- Parsing Subnet file:" << fn.c_str() << endl;
 
1996
 
 
1997
   int lineNum = 0;
 
1998
   while (f.good()) {
 
1999
      lineNum++;
 
2000
 
 
2001
      f.getline(sLine,1024);
 
2002
      if (!strlen(sLine)) continue;
 
2003
 
 
2004
      status = parseSubnetLine(sLine);
 
2005
      if (status)
 
2006
      {
 
2007
         cout << "-W- Wrong syntax code:" << status << " in line:"
 
2008
              << lineNum << endl;
 
2009
      }
 
2010
   }
 
2011
 
 
2012
   cout << "-I- Defined " << SystemByName.size() << "/" << NodeByName.size()
 
2013
        << " systems/nodes " << endl;
 
2014
   f.close();
 
2015
   return 0;
 
2016
}
 
2017
 
 
2018
//////////////////////////////////////////////////////////////////////////////
 
2019
 
 
2020
// Parse an OpenSM FDBs file and set the LFT table accordingly
 
2021
int
 
2022
IBFabric::parseFdbFile(string fn) {
 
2023
   ifstream f(fn.c_str());
 
2024
   int switches = 0, fdbLines=0;
 
2025
   char sLine[1024];
 
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]+)");
 
2030
   rexMatch *p_rexRes;
 
2031
 
 
2032
   if (! f)
 
2033
   {
 
2034
      cout << "-E- Fail to open file:" << fn.c_str() << endl;
 
2035
      return 1;
 
2036
   }
 
2037
 
 
2038
   cout << "-I- Parsing FDBs file:" << fn.c_str() << endl;
 
2039
 
 
2040
   IBNode *p_node;
 
2041
   int anyErr = 0;
 
2042
 
 
2043
   while (f.good()) {
 
2044
      f.getline(sLine,1024);
 
2045
 
 
2046
      p_rexRes = switchLine.apply(sLine);
 
2047
      if (p_rexRes)
 
2048
      {
 
2049
         // Got a new switch - find the node:
 
2050
         uint64_t guid;
 
2051
         guid = strtoull(p_rexRes->field(1).c_str(), NULL, 16);
 
2052
         p_node = getNodeByGuid(guid);
 
2053
         if (!p_node)
 
2054
         {
 
2055
            cout << "-E- Fail to find node with guid:"
 
2056
                 << p_rexRes->field(1) << endl;
 
2057
            anyErr++;
 
2058
         }
 
2059
         else
 
2060
         {
 
2061
            switches++;
 
2062
         }
 
2063
         delete p_rexRes;
 
2064
         continue;
 
2065
      }
 
2066
 
 
2067
      p_rexRes = lidLine.apply(sLine);
 
2068
      if (p_rexRes)
 
2069
      {
 
2070
         // Got a new lid port pair
 
2071
         if (p_node)
 
2072
         {
 
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;
 
2078
 
 
2079
            p_node->setLFTPortForLid(lid,port);
 
2080
            fdbLines++;
 
2081
         }
 
2082
         delete p_rexRes;
 
2083
         continue;
 
2084
      }
 
2085
 
 
2086
      // is it an ignore line ?
 
2087
      //cout << "-W- Ignoring line:" << sLine << endl;
 
2088
   }
 
2089
 
 
2090
   cout << "-I- Defined " << fdbLines << " fdb entries for:"
 
2091
        << switches << " switches" << endl;
 
2092
   f.close();
 
2093
   return anyErr;
 
2094
}
 
2095
 
 
2096
//////////////////////////////////////////////////////////////////////////////
 
2097
 
 
2098
// Parse PSL file and set the SLT tables accordingly
 
2099
int
 
2100
IBFabric::parsePSLFile(string fn) {
 
2101
   ifstream f(fn.c_str());
 
2102
   int maxLid = 0;
 
2103
 
 
2104
   char sLine[1024];
 
2105
   // 0x0002c90000000099 154 0
 
2106
   // srcguid dlid sl
 
2107
   regExp slLine("0x([0-9a-z]+) ([0-9]+) ([0-9]+)");
 
2108
   rexMatch *p_rexRes;
 
2109
 
 
2110
   if (f.fail())
 
2111
   {
 
2112
      cout << "-E- Fail to open file:" << fn.c_str() << endl;
 
2113
      return 1;
 
2114
   }
 
2115
 
 
2116
   cout << "-I- Parsing SL file:" << fn.c_str() << endl;
 
2117
 
 
2118
   int anyErr = 0;
 
2119
 
 
2120
   // Find max HCA LID
 
2121
   while (f.good()) {
 
2122
      f.getline(sLine,1024);
 
2123
      p_rexRes = slLine.apply(sLine);
 
2124
      if (p_rexRes)
 
2125
      {
 
2126
        unsigned int lid = strtoull(p_rexRes->field(2).c_str(), NULL, 10);
 
2127
        maxLid = lid > maxLid ? lid:maxLid;
 
2128
      }
 
2129
      /*else
 
2130
      {
 
2131
        cout << "-E- Wrong file format:" << fn.c_str() << endl;
 
2132
        anyErr++;
 
2133
        }*/
 
2134
   }
 
2135
   f.close();
 
2136
 
 
2137
   // Make second pass and build the tables
 
2138
   f.open(fn.c_str(),ifstream::in);
 
2139
   if (f.fail())
 
2140
   {
 
2141
      cout << "-E- Fail to open file:" << fn.c_str() << endl;
 
2142
      return 1;
 
2143
   }
 
2144
 
 
2145
   while (f.good()) {
 
2146
      f.getline(sLine,1024);
 
2147
 
 
2148
      p_rexRes = slLine.apply(sLine);
 
2149
      if (p_rexRes)
 
2150
      {
 
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);
 
2154
 
 
2155
        IBNode* p_node = getNodeByGuid(guid);
 
2156
        if (!p_node)
 
2157
        {
 
2158
           cout << "-E- Fail to find node with guid:"
 
2159
                << guid << endl;
 
2160
           anyErr++;
 
2161
        }
 
2162
        else
 
2163
        {
 
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);
 
2168
        }
 
2169
        delete p_rexRes;
 
2170
      }
 
2171
      /*else
 
2172
      {
 
2173
        cout << "-E- Wrong file format:" << fn.c_str() << endl;
 
2174
        anyErr++;
 
2175
        }*/
 
2176
   }
 
2177
   cout << "-I- Defined "<< (int)numSLs << " SLs in use" <<endl;
 
2178
   f.close();
 
2179
 
 
2180
   return anyErr;
 
2181
}
 
2182
 
 
2183
//////////////////////////////////////////////////////////////////////////////
 
2184
 
 
2185
// Parse SLVL file and set the SL2VL tables accordingly
 
2186
int
 
2187
IBFabric::parseSLVLFile(string fn) {
 
2188
  numVLs = 1;
 
2189
  ifstream f(fn.c_str());
 
2190
 
 
2191
  char sLine[1024];
 
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])");
 
2195
  rexMatch *p_rexRes;
 
2196
 
 
2197
  if (f.fail()) {
 
2198
    cout << "-E- Fail to open file:" << fn.c_str() << endl;
 
2199
    return 1;
 
2200
  }
 
2201
 
 
2202
  cout << "-I- Parsing SLVL file:" << fn.c_str() << endl;
 
2203
 
 
2204
  int anyErr = 0;
 
2205
 
 
2206
   // Parse the file
 
2207
   while (f.good()) {
 
2208
      f.getline(sLine,1024);
 
2209
 
 
2210
      p_rexRes = slLine.apply(sLine);
 
2211
      if (p_rexRes)
 
2212
      {
 
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);
 
2216
 
 
2217
        IBNode* p_node = getNodeByGuid(guid);
 
2218
        if (!p_node)
 
2219
        {
 
2220
           cout << "-E- Fail to find node with guid:"
 
2221
                << guid << endl;
 
2222
           anyErr++;
 
2223
        }
 
2224
        else
 
2225
        {
 
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);
 
2232
          }
 
2233
        }
 
2234
        delete p_rexRes;
 
2235
      }
 
2236
      /*else
 
2237
      {
 
2238
        cout << "-E- Wrong file format:" << fn.c_str() << endl;
 
2239
        anyErr++;
 
2240
        }*/
 
2241
   }
 
2242
   cout << "-I- Defined "<< (int)numVLs << " VLs in use" <<endl;
 
2243
 
 
2244
   f.close();
 
2245
 
 
2246
   return anyErr;
 
2247
}
 
2248
 
 
2249
///////////////////////////////////////////////////////////////////////////
 
2250
 
 
2251
// Parse an OpenSM MCFDBs file and set the MFT table accordingly
 
2252
int
 
2253
IBFabric::parseMCFdbFile(string fn) {
 
2254
   ifstream f(fn.c_str());
 
2255
   int switches = 0, fdbLines=0;
 
2256
   char sLine[1024];
 
2257
   // Switch 0x0002c9010bb90090
 
2258
   // LID    : Out Port(s)
 
2259
   // 0xC000 : 0x007
 
2260
   // 0xC001 : 0x007
 
2261
   regExp switchLine("Switch 0x([0-9a-z]+)");
 
2262
   regExp lidLine("0x([0-9a-zA-Z]+) :(.*)");
 
2263
   rexMatch *p_rexRes;
 
2264
 
 
2265
   if (! f)
 
2266
   {
 
2267
      cout << "-E- Fail to open file:" << fn.c_str() << endl;
 
2268
      return 1;
 
2269
   }
 
2270
 
 
2271
   cout << "-I- Parsing Multicast FDBs file:" << fn.c_str() << endl;
 
2272
 
 
2273
   IBNode *p_node;
 
2274
   int anyErr = 0;
 
2275
 
 
2276
   while (f.good()) {
 
2277
      f.getline(sLine,1024);
 
2278
 
 
2279
      p_rexRes = switchLine.apply(sLine);
 
2280
      if (p_rexRes)
 
2281
      {
 
2282
         // Got a new switch - find the node:
 
2283
         uint64_t guid;
 
2284
         guid = strtoull(p_rexRes->field(1).c_str(), NULL, 16);
 
2285
         p_node = getNodeByGuid(guid);
 
2286
         if (!p_node)
 
2287
         {
 
2288
            cout << "-E- Fail to find switch: node:"
 
2289
                 << p_rexRes->field(1) << endl;
 
2290
            anyErr++;
 
2291
         }
 
2292
         else
 
2293
         {
 
2294
            switches++;
 
2295
         }
 
2296
         delete p_rexRes;
 
2297
         continue;
 
2298
      }
 
2299
 
 
2300
      p_rexRes = lidLine.apply(sLine);
 
2301
      if (p_rexRes)
 
2302
      {
 
2303
         // Got a new lid port pair
 
2304
         if (p_node)
 
2305
         {
 
2306
            unsigned int lid = strtol((p_rexRes->field(1)).c_str(), NULL, 16);
 
2307
 
 
2308
            char buff[(p_rexRes->field(2)).size() + 1];
 
2309
            strcpy(buff, p_rexRes->field(2).c_str());
 
2310
 
 
2311
            char *pPortChr = strtok(buff, " ");
 
2312
            while (pPortChr) {
 
2313
               unsigned int port = strtol(pPortChr, NULL, 16);
 
2314
 
 
2315
               if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
 
2316
                  cout << "-V- Setting Multicast FDB for:" << p_node->name
 
2317
                       << " lid:" << lid << " port:" << port << endl;
 
2318
 
 
2319
               p_node->setMFTPortForMLid(lid,port);
 
2320
               pPortChr = strtok(NULL, " ");
 
2321
               fdbLines++;
 
2322
            }
 
2323
         }
 
2324
         delete p_rexRes;
 
2325
         continue;
 
2326
      }
 
2327
 
 
2328
      // is it an ignore line ?
 
2329
      //cout << "-W- Ignoring line:" << sLine << endl;
 
2330
   }
 
2331
 
 
2332
   cout << "-I- Defined " << fdbLines << " Multicast Fdb entries for:"
 
2333
        << switches << " switches" << endl;
 
2334
   f.close();
 
2335
   return anyErr;
 
2336
}
 
2337
 
 
2338
///////////////////////////////////////////////////////////////////////////
 
2339
// dump out the contents of the entire fabric
 
2340
void
 
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();
 
2346
        sI++) {
 
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();
 
2352
           pI++) {
 
2353
         IBSysPort *p_port = (*pI).second;
 
2354
         IBLinkWidth width = IB_UNKNOWN_LINK_WIDTH;
 
2355
         IBLinkSpeed speed = IB_UNKNOWN_LINK_SPEED;
 
2356
 
 
2357
         if (! p_port) continue;
 
2358
 
 
2359
         // node port
 
2360
         sout << "  " << p_port->name;
 
2361
         if ( p_port->p_nodePort)
 
2362
         {
 
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;
 
2367
         }
 
2368
         else
 
2369
         {
 
2370
            sout << " (ERR: NO NODE PORT?)";
 
2371
         }
 
2372
 
 
2373
         // remote sys port?
 
2374
         if ( p_port->p_remoteSysPort)
 
2375
         {
 
2376
            sout << " -" << width2char(width) << "-" << speed2char(speed)
 
2377
                 << "G-> "
 
2378
                 << p_port->p_remoteSysPort->p_system->name << "/"
 
2379
                 << p_port->p_remoteSysPort->name << endl;
 
2380
         }
 
2381
         else
 
2382
         {
 
2383
            sout << endl;
 
2384
         }
 
2385
      }
 
2386
   }
 
2387
 
 
2388
   // Now dump system internals:
 
2389
   for (map_str_psys::iterator sI = SystemByName.begin();
 
2390
        sI != SystemByName.end();
 
2391
        sI++) {
 
2392
      IBSystem *p_system = (*sI).second;
 
2393
      sout << "--------------- SYSTEM " << (*sI).first
 
2394
           << " DUMP ----------------------" << endl;
 
2395
 
 
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();
 
2399
           nI++) {
 
2400
         IBNode *p_node = (*nI).second;
 
2401
 
 
2402
         sout << "\nNode:" << p_node->name << " (" << p_node->type
 
2403
              << "," << guid2str(p_node->guid_get()) << ")" << endl;
 
2404
 
 
2405
         for (unsigned int pn = 1; pn <= p_node->numPorts; pn++) {
 
2406
            IBPort *p_port = p_node->getPort(pn);
 
2407
 
 
2408
            if (! p_port) continue;
 
2409
 
 
2410
            // we do not report cross system connections:
 
2411
            if (p_port->p_sysPort)
 
2412
            {
 
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;
 
2419
            }
 
2420
         }
 
2421
      }
 
2422
   }
 
2423
}
 
2424
 
 
2425
///////////////////////////////////////////////////////////////////////////
 
2426
// dump out the contents of the entire fabric as a topology file with
 
2427
// required set of IBNL's if unknown
 
2428
int
 
2429
IBFabric::dumpTopology(char *fileName, char * ibnlDir) {
 
2430
   ofstream sout;
 
2431
   sout.open(fileName);
 
2432
   if (sout.fail())
 
2433
   {
 
2434
      cout << "-E- failed to open:" << fileName << " for writing." << endl;
 
2435
      return 1;
 
2436
   }
 
2437
   sout << "# This topology file was automaticlly generated by IBDM" << endl;
 
2438
 
 
2439
   // we start with all systems at top level:
 
2440
   for (map_str_psys::iterator sI = SystemByName.begin();
 
2441
        sI != SystemByName.end();
 
2442
        sI++) {
 
2443
      IBSystem *p_system = (*sI).second;
 
2444
 
 
2445
      string sysType;
 
2446
      if (p_system->type == "Generic")
 
2447
      {
 
2448
         p_system->dumpIBNL(ibnlDir, sysType);
 
2449
      }
 
2450
      else
 
2451
      {
 
2452
         sysType = string(p_system->type);
 
2453
      }
 
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();
 
2457
           pI++) {
 
2458
         IBSysPort *p_sysPort = (*pI).second;
 
2459
         IBLinkWidth width = IB_UNKNOWN_LINK_WIDTH;
 
2460
         IBLinkSpeed speed = IB_UNKNOWN_LINK_SPEED;
 
2461
 
 
2462
         if (! p_sysPort) continue;
 
2463
 
 
2464
         // remote sys port?
 
2465
         if ( p_sysPort->p_remoteSysPort)
 
2466
         {
 
2467
            width = p_sysPort->p_nodePort->width;
 
2468
            speed = p_sysPort->p_nodePort->speed;
 
2469
 
 
2470
            if (p_sysPort->p_remoteSysPort->p_system->type == "Generic")
 
2471
            {
 
2472
               p_sysPort->p_remoteSysPort->p_system->dumpIBNL(ibnlDir, sysType);
 
2473
            }
 
2474
            else
 
2475
            {
 
2476
               sysType = string(p_sysPort->p_remoteSysPort->p_system->type);
 
2477
            }
 
2478
 
 
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;
 
2484
         }
 
2485
      }
 
2486
   }
 
2487
   sout.close();
 
2488
   return 0;
 
2489
}
 
2490
 
 
2491
#ifndef IBDM_CODE_VERSION
 
2492
#define IBDM_CODE_VERSION "undefined"
 
2493
#endif
 
2494
const char * ibdmSourceVersion = IBDM_CODE_VERSION ;