Logo Search packages:      
Sourcecode: ibutils version File versions  Download package

TopoMatch.cpp

/*
 * Copyright (c) 2004 Mellanox Technologies LTD. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * $Id$
 */

/*

Topology Matching

The file holds a set of utilities to providea "topology matchine"
functionality: comparing two fabrics based on some entry point.

The comparison is of a "discovered" fabric to a "spec" fabric:
disc = The fabric de-facto as OpenSM see it.
spec = The fabric as specified in either a topology file or cables file.

Through the matching algorithm:
1. The specification fabric get guids annotations.
2. Missmatches are being formatted into a text report.

After Matching a Merger can be run to create the merged fabric.
This fabric only includes the discovered nodes but uses the
names of the specification fabric and systems from the specification
fabric.

*/

#include "Fabric.h"
#include "Regexp.h"
#include <iomanip>
#include <sstream>

// we use the node appData2.val as a "visited" marker for the
// topology matching algorithm by setting it's value to 1
static inline void
TopoMarkNodeAsMatchAlgoVisited(IBNode *p_node) {
  p_node->appData2.val = 1;
}

static inline int
TopoIsNodeMatchAlgoVisited(IBNode *p_node) {
  return (p_node->appData2.val & 1);
}

// we use the node appData2.val as a "reported" marker for the
// topology matching algorithm by setting it's second bit (2) to 1
static inline void
TopoMarkNodeAsReported(IBNode *p_node) {
  p_node->appData2.val = (p_node->appData2.val | 2);
}

static inline int
TopoIsNodeMarkedAsReported(IBNode *p_node) {
  return (p_node->appData2.val & 2);
}

// Check for two ports to be matching:
// PortNumber must match,
// If RemotePort exists should:
// a. Same port number
// b. Same node guid if already defined
// c. Link width and speed (these are only added to diagnostics as warnings)
// d. Remote nodes have same number of ports...
// RETURN: 1 if match 0 otherwise.
static int
TopoMatchPorts(
  IBPort *p_sPort,
  IBPort *p_dPort,
  int doDiag,
  stringstream &diag)
{

  if (!p_sPort || !p_dPort) {
    return 0;
  }
  if (p_sPort->num != p_dPort->num) {
    if (doDiag)
      diag << "Port number missmatch found. The port:" << p_sPort->getName()
           << " != discovered:" << p_dPort->num << endl;
    return 0;
  }

  IBPort *p_dRemPort = p_dPort->p_remotePort;
  IBPort *p_sRemPort = p_sPort->p_remotePort;

  if (p_sRemPort && !p_dRemPort) {
    if (doDiag)
      diag << "Missing link from:" << p_sPort->getName()
           << " to:" << p_sRemPort->getName()
           << endl;
    return 0;
  } else if (!p_sRemPort && p_dRemPort) {
    if (doDiag)
      diag << "Extra link from:" << p_sPort->getName()
           << " to:" << p_dRemPort->getName()
           << endl;
    return 0;
  } else if (p_sRemPort) {
    // check for port numbers
    if (p_sRemPort->num != p_dRemPort->num) {
      // on HCA nodes we can try the other port ...
      if (p_dRemPort->p_node->type != IB_SW_NODE) {
        // we need the spec to define other port of the HCA as empty
        if (doDiag)
          diag << "Probably switched CA ports on cable from:"
               << p_sPort->getName()
               << ". Expected port:" << p_sRemPort->num
               << " but got port:" << p_dRemPort->num << endl;
      } else {
        if (doDiag)
          diag << "Wrong port number on remote side of cable from:"
               << p_sPort->getName()
               << ". Expected port:" << p_sRemPort->num
               << " but got port:" << p_dRemPort->num << endl;
        return 0;
      }
    }

    // check link width - since it does not affect the result
    // only in diagnostics mode:
    if (doDiag) {
      if (p_sPort->width != p_dPort->width)
        diag << "Wrong link width on:" << p_sPort->getName()
             << ". Expected:" << width2char(p_sPort->width)
             << " got:" << width2char(p_dPort->width) << endl;
      if (p_sPort->speed != p_dPort->speed)
        diag << "Wrong link speed on:" << p_sPort->getName()
             << ". Expected:" << speed2char(p_sPort->speed)
             << " got:" << speed2char(p_dPort->speed) << endl;
    }

    IBNode *p_dRemNode = p_dRemPort->p_node;
    IBNode *p_sRemNode = p_sRemPort->p_node;

    // check to see if the remote nodes are not already cross linked
    if (p_dRemNode->appData1.ptr) {
      if ((IBNode *)p_dRemNode->appData1.ptr != p_sRemNode) {
        IBPort *p_port =
          ((IBNode *)p_dRemNode->appData1.ptr)->getPort(p_sRemPort->num);
        if (p_port) {
          diag << "Link from port:" << p_sPort->getName()
               << " should connect to port:" << p_sRemPort->getName()
               << " but connects to (previously matched) port:"
               << p_port->getName() << endl;
        } else {
          diag << "Link from port:" << p_sPort->getName()
               << " should connect to port:" << p_sRemPort->getName()
               << " but connects to a port not supposed to be connected"
               << " on (previously matched) node:"
               << ((IBNode *)p_dRemNode->appData1.ptr)->name << endl;
        }
        return 0;
      }
    }

//     if (p_sRemNode->appData1.ptr) {
//       if ((IBNode *)p_sRemNode->appData1.ptr != p_dRemNode) {
//         diag << "Link from port:" << p_sPort->getName()
//              << " should connect to node:" << p_sRemNode->name
//              << " but connects to previously matched node:"
//              << ((IBNode *)p_sRemNode->appData1.ptr)->name << endl;
//         return 0;
//       }
//     }

    // if spec node guid is defined verify same guid:
    if (p_sRemNode->guid_get() &&
        (p_sRemNode->guid_get() != p_dRemNode->guid_get())) {
      if (doDiag)
        diag << "Wrong node on cable from:" << p_sPort->getName()
             << ". Expected connection to node:"
             << guid2str(p_sRemNode->guid_get())
             << " but connects to:"
             << guid2str(p_dRemNode->guid_get()) << endl;
      return 0;
    }

    // same number of ports on nodes
    if (p_sRemNode->numPorts != p_dRemNode->numPorts) {
      if (doDiag)
        diag << "Other side of cable from:" << p_sPort->getName()
             << " difference in port count. Expected:"
             << p_sRemNode->numPorts
             << " but got:"
             << p_dRemNode->numPorts << endl;
      return 0;
    }
  }

  return 1;
}

// Consider node matching by inspecting all their ports.
// All ports but maxMiss should be matched to pass.
// RETURN: 1 if qualified as matching 0 otherwise.
int
TopoQalifyNodesMatching(IBNode *p_sNode, IBNode *p_dNode)
{
  int maxMissed = 2; // TODO : Maybe need to restrict by the number of ports?
  int numMissed = 0;
  IBPort *p_sPort;
  IBPort *p_dPort;
  stringstream tmpDiag;

  // we must make sure we did not assign a match to any of the nodes ...
  if ((p_sNode->appData1.ptr || p_dNode->appData1.ptr) &&
      (p_sNode->appData1.ptr != p_dNode->appData1.ptr))
    return 0;

  // we must have same number of ports ...
  if (p_dNode->numPorts != p_sNode->numPorts)
    return 0;

  // Try to match all ports of this node
  for (unsigned int pn = 1; pn <= p_dNode->numPorts; pn++) {
    p_dPort = p_dNode->getPort(pn);
    p_sPort = p_sNode->getPort(pn);

    // we might miss some ports:
    if (!p_dPort && !p_sPort) {
      continue;
    } else if (!p_dPort || !p_sPort) {
      if (p_dPort && p_dPort->p_remotePort)
      {
        tmpDiag << "Port:" << pn << " exist only in discovered model." << endl;
        numMissed++;
      }
      else if (p_sPort && p_sPort->p_remotePort)
      {
        tmpDiag << "Port:" << pn << " exist only in specification model."
                << endl;
        numMissed++;
      }
      continue;
    }

    // we do not care about cases where we miss a
    // discovered link:
    if (! p_dPort->p_remotePort) continue;

    // ports match so push remote side into BFS if ok
    if (!TopoMatchPorts(p_sPort, p_dPort, 1, tmpDiag)) {
      numMissed++;
      // if (numMissed > maxMissed) break;
    }
  }

  if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
    if (numMissed)
      if (numMissed <= maxMissed)
        cout << "-V- Qualified Nodes:" << p_sNode->name
             << " to:" << p_dNode->name << " with:" << numMissed
             << " missmatches!" <<endl;
      else
        cout << "-V- Disqualified Nodes:" << p_sNode->name
             << " to:" << p_dNode->name << " due to:" << numMissed
             << " missmatches!\n" << tmpDiag.str() << endl;

  return numMissed <= maxMissed;
}

// Mark nodes as matching
static inline void
TopoMarkMatcedNodes(IBNode *p_node1, IBNode *p_node2, int &matchCounter)
{
  if (p_node1->appData1.ptr || p_node2->appData1.ptr) {
    if (p_node1->appData1.ptr ==  p_node2->appData1.ptr)
    {
      if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
        cout << "-V- Skipping previously Matched nodes:" << p_node1->name
             << " and:" <<  p_node2->name << endl;
    } else {
      if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
        cout << "-V- Requested to mark matching nodes:" << p_node1->name
             << " and:" <<  p_node2->name << " previously matched to others" << endl;
    }

  } else {
    // do the cross links on the spec and disc fabrics:
    if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
      cout << "-V- Matched Node:" << p_node1->name
           << " and:" <<  p_node2->name << endl;
    p_node1->appData1.ptr = p_node2;
    p_node2->appData1.ptr = p_node1;
    matchCounter++;
  }
}

// Perform a BFS on both fabrics and cross point between matching nodes.
int
TopoBFSAndMatchFromPorts(
  IBPort *p_sPort, // Starting port on the specification fabrric
  IBPort *p_dPort,
  stringstream &diag)
{
  int numMatchedNodes = 0;
  int dNumNodes, sNumNodes;
  IBNode *p_sNode, *p_sRemNode;
  IBNode *p_dNode, *p_dRemNode;
  IBFabric *p_dFabric, *p_sFabric;
  int status;

  if (! TopoMatchPorts(p_sPort, p_dPort, 1, diag)) {
    diag << "Starting ports do not match. Did you switch the ports?" << endl;
    return 1;
  }

  // Mark the start node as matched:
  TopoMarkNodeAsMatchAlgoVisited(p_dPort->p_node);

  // if we do not have a remote port what do we really match?
  if (!p_dPort->p_remotePort) {
    diag << "No link connected to starting port. Nothing more to match."
         << endl;
    return 1;
  }

  p_dRemNode = p_dPort->p_remotePort->p_node;
  p_sRemNode = p_sPort->p_remotePort->p_node;

  // Mark local and remote nodes as matching
  TopoMarkMatcedNodes(p_dRemNode, p_sRemNode, numMatchedNodes);
  TopoMarkMatcedNodes(p_dPort->p_node, p_sPort->p_node, numMatchedNodes);

  // BFS through the matching ports only.
  // we keep track of the the discovered nodes only as it needs to be matched
  // already to get into this list and thus we have a pointer to the spec node.
  // To mark visited nodes we use the appData2.val
  list < IBNode * > bfsFifo;

  bfsFifo.push_back(p_dPort->p_remotePort->p_node);
  TopoMarkNodeAsMatchAlgoVisited(p_dPort->p_remotePort->p_node);

  // On discovered fabrics where the CA nodes are marked by name we
  // can start traversing from these nodes also - of they match any
  // spec system by name.
  p_dFabric = p_dPort->p_node->p_fabric;
  p_sFabric = p_sPort->p_node->p_fabric;
  if (p_dFabric->subnCANames) {

    if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
      cout << "-V- Matching nodes by name"  << endl;

    // we go through entire discovered fabric trying to find match by name
    for (map_str_pnode::iterator nI = p_dFabric->NodeByName.begin();
         nI != p_dFabric->NodeByName.end();
         nI++)
    {

      IBNode *p_node1 = (*nI).second;

      // so we try to find a node by the same name on the spec fabric.
      map_str_pnode::iterator snI = p_sFabric->NodeByName.find((*nI).first);

      // no match
      if (snI == p_sFabric->NodeByName.end())
      {
        if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
          cout << "-V- No match for:" << (*nI).first << endl;
        continue;
      }
      IBNode *p_node2 = (*snI).second;

      // make sure they are not previously match somehome
      if (p_node1->appData1.ptr || p_node2->appData1.ptr) continue;


      // do not rush into matching - double check all the nodes ports ...
      int anyMissmatch = 0;
      if (p_node1->numPorts != p_node2->numPorts) continue;
      for (unsigned int pn = 1; !anyMissmatch && (pn <= p_node1->numPorts);
           pn++)
      {
        IBPort *p_dPort = p_node1->getPort(pn);
        IBPort *p_sPort = p_node2->getPort(pn);

        if (! TopoMatchPorts(p_sPort, p_dPort, 1, diag))
        {
          anyMissmatch++;
          if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
            cout << "-V- Matched node:" <<  (*nI).first
                 << " by name - but some ports are different." << endl;
        }


        if (0 && p_dPort->p_remotePort)
        {
          IBNode *p_dRemNode = p_dPort->p_remotePort->p_node;
          IBNode *p_sRemNode = p_sPort->p_remotePort->p_node;
          if (! TopoQalifyNodesMatching(p_sRemNode, p_dRemNode))
          {
            anyMissmatch++;
            if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
              cout << "-V- Disqualified start nodes match:"
                   << p_node1->name << " by rem nodes" << endl;
          }
        }

        if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
          cout << "-V- Using name match for nodes:" << p_node1->name << endl;
        // set the cross pointers and visited flag:
        TopoMarkNodeAsMatchAlgoVisited(p_node1);

        TopoMarkMatcedNodes(p_node1, p_node2, numMatchedNodes);
        // If we do not start from the HCAs we avoid cases where the
        // wrong leaf is connected and the leaf is deep enough to hide
        // it
        // bfsFifo.push_back(p_node1);
      }
    }
  }

  // track any further unmatch:
  int anyUnmatch = 0;

  // BFS loop
  while (!bfsFifo.empty()) {
    p_dNode = bfsFifo.front();
    bfsFifo.pop_front();
    // just makeing sure
    if (! p_dNode->appData1.ptr) {
      cerr << "TopoMatchFabrics: Got to a BFS node with no previous match?"
           << endl;
      abort();
    }

    p_sNode = (IBNode *)p_dNode->appData1.ptr;
    if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
      cout << "-V- Visiting Node:" << p_sNode->name << endl;

    // Try to match all ports of this node
    for (unsigned int pn = 1; pn <= p_dNode->numPorts; pn++) {
      IBPort *p_dPort = p_dNode->getPort(pn);
      IBPort *p_sPort = p_sNode->getPort(pn);

      if (!p_sPort && !p_dPort) {
        continue;
      } else if (!p_sPort) {
        diag << "Non existing Spec Port for: "
             << p_dPort->getName() << endl;
        anyUnmatch++;
        continue;
      } else if (!p_dPort) {
        diag << "Non existing Discovered Port for: "
             << p_sPort->getName() << endl;
        anyUnmatch++;
        continue;
      }

      // ports match so push remote side into BFS if ok
      if (TopoMatchPorts(p_sPort, p_dPort, 1, diag)) {
        // ports matched but is there a remote side?
        if (p_dPort->p_remotePort) {
          p_dRemNode = p_dPort->p_remotePort->p_node;
          p_sRemNode = p_sPort->p_remotePort->p_node;

          // we need to qualify the match (looking one more step ahead)
          if (TopoQalifyNodesMatching(p_sRemNode, p_dRemNode)) {
            // propagate the matching of the nodes:
            TopoMarkMatcedNodes(p_dRemNode, p_sRemNode, numMatchedNodes);

            // if not already matched
            if (!TopoIsNodeMatchAlgoVisited(p_dPort->p_remotePort->p_node)) {
              bfsFifo.push_back(p_dPort->p_remotePort->p_node);
              TopoMarkNodeAsMatchAlgoVisited(p_dPort->p_remotePort->p_node);
            }
          }
        }
      } else {
        anyUnmatch++;
      }
    }
  }

  status = anyUnmatch;
  sNumNodes = p_sPort->p_node->p_fabric->NodeByName.size();
  dNumNodes = p_dPort->p_node->p_fabric->NodeByName.size();
  if (numMatchedNodes != sNumNodes) {
    diag << "Some nodes are missing!" << endl;
    status = 1;
  }

  if (numMatchedNodes != dNumNodes) {
    diag << "Some extra or unmatched nodes were discoeverd." << endl;
    status = 1;
  }
  return 0;
}

//////////////////////////////////////////////////////////////////////////////

// Second step in matching - refine missmatched nodes:
// Based on the previous matching - produce a set of all spec nodes
// that are connected to other matched spec nodes.
// Then go over all these nodes and produce a "best fit" match for them:
// The nodes will be connected on the spec model to a set of other nodes.
// Go over all the node ports:
//  If connected to a matched node
//   Check to see what node is connected to the same port of the disc node
//   If it is un-matched - add it to the map of optential nodes adn
//      incr the match value count.
// Now observe the map of potential matching nodes:
// If there is a node that is  mapped by > half the number of ports
// mark it as matching.
typedef map < IBNode *, int , less < IBNode * > >  map_pnode_int;

int
TopoMatchNodeByAdjacentMatched(
  IBNode *p_sNode
  )
{
  int succeedMatch;

  // This map will hold the number of matching ports for each candidate
  // discovered node
  map_pnode_int dNodeNumMatches;

  // we track the total number of connected ports of the spec node
  int numConnPorts = 0;

  // Go over all the node ports:
  for (unsigned int pn = 1; pn <= p_sNode->numPorts; pn++) {
    IBPort *p_sPort = p_sNode->getPort(pn);

    //  If connected to a remote port
    if (! p_sPort || ! p_sPort->p_remotePort) continue;

    numConnPorts++;

    IBPort *p_sRemPort = p_sPort->p_remotePort;

    // But the remote spec node must be matched to be considered
    IBNode *p_dRemNode = (IBNode *)p_sRemPort->p_node->appData1.ptr;
    if (! p_dRemNode) continue;

    //   Check to see what node is connected to the same port of the disc node
    IBPort *p_dRemPort = p_dRemNode->getPort(p_sRemPort->num);

    // is it connected ?
    if (! p_dRemPort || ! p_dRemPort->p_remotePort) continue;

    IBNode *p_dCandidateNode = p_dRemPort->p_remotePort->p_node;

    // It must be un-matched
    if (p_dCandidateNode->appData1.ptr) continue;

    // OK so it is a valid candidate
    // - add it to the map of optential nodes adn
    //      incr the match value count.
    map_pnode_int::iterator cnI = dNodeNumMatches.find(p_dCandidateNode);
    if (cnI == dNodeNumMatches.end()) {
      dNodeNumMatches[p_dCandidateNode] = 1;
    } else {
      (*cnI).second++;
    }
  }

  // Now observe the map of potential matching nodes:
  // If there is a node that is  mapped by > half the number of ports
  // mark it as matching.
  for (map_pnode_int::iterator cnI = dNodeNumMatches.begin();
       cnI != dNodeNumMatches.end();
       cnI++) {
    if ( (*cnI).second > numConnPorts / 2) {
      TopoMarkMatcedNodes(p_sNode, (*cnI).first, succeedMatch);
    }
  }
  return succeedMatch;
}

// Provide the list of un-matched spec nodes that
// are adjecant to a matched nodes
list < IBNode *>
TopoGetAllSpecUnMatchedAdjacentToMatched(
  IBFabric *p_sFabric
  )
{
  list < IBNode *> adjNodes;
  for (map_str_pnode::iterator nI = p_sFabric->NodeByName.begin();
       nI != p_sFabric->NodeByName.end();
       nI++) {
    IBNode *p_node = (*nI).second;

    // if the node is already matcehd skip it:
    if (p_node->appData1.ptr) continue;

    // go over all the node ports and check adjacent node.
    int done = 0;
    for (unsigned int pn = 1;
         (pn <= p_node->numPorts) && !done;
         pn++) {
      IBPort *p_port = p_node->getPort(pn);
      // if there is a remote port
      if (p_port && p_port->p_remotePort) {
        // check if the other node is matched.
        if (p_port->p_remotePort->p_node->appData1.ptr) {
          // add the node to the list and break the for
          done = 1;
          adjNodes.push_back(p_node);
        }
      }
    }
  }
  return adjNodes;
}

// Second Matching step
// Return the number of matched nodes by this step
int
TopoMatchSpecNodesByAdjacentNode(
  IBFabric *p_sFabric
  )
{
  list < IBNode *> unMatchedWithAdjacentMatched;
  int numMatched = 0;

  unMatchedWithAdjacentMatched =
    TopoGetAllSpecUnMatchedAdjacentToMatched(p_sFabric);

  for( list < IBNode *>::iterator nI = unMatchedWithAdjacentMatched.begin();
       nI != unMatchedWithAdjacentMatched.end();
       nI++)
  {
    numMatched += TopoMatchNodeByAdjacentMatched(*nI);
  }
}

//////////////////////////////////////////////////////////////////////////////


// Report missmatched nodes by examining entire system and looking for
// all system and then a single board (matching regexp).
// So the report will be optimized:
// If the entire system is missing - report only at this level
// If an entire board of the system missing - report only at this level
// Otherwise report at the specific node only.
static int
TopoReportMismatchedNode(
  IBNode *p_node,
  int reportMissing, // 0 = reportExtra ...
  stringstream &diag)
{
  int anyMissmatch = 0;
  int MaxConnRep = 12;
  // we assume if a previous check was done we would have
  // never been called since the "reported" mark would have been set
  IBSystem *p_system = p_node->p_system;

  // we always mark the board of the node by examining all but the "UXXX"
  char *p_lastSlash = rindex(p_node->name.c_str(), '/');
  char nodeBoardName[512];
  int  boardNameLength;
  if (!p_lastSlash) {
    strcpy(nodeBoardName, "NONE");
    boardNameLength = 0;
  } else {
    boardNameLength = p_lastSlash - p_node->name.c_str();
    strncpy(nodeBoardName, p_node->name.c_str(), boardNameLength);
    nodeBoardName[boardNameLength] = '\0';
  }

  int anyOfBoardMatch = 0;
  int anyOfSystemMatch = 0;
  list< IBNode *> boardNodes;

  // visit all nodes of the the specified system.
  for (map_str_pnode::iterator nI = p_system->NodeByName.begin();
       nI != p_system->NodeByName.end();
       nI++) {
    IBNode *p_node = (*nI).second;

    // see if it of the same board:
    if (!strncmp(p_node->name.c_str(), nodeBoardName, boardNameLength)) {
      // on same board
      boardNodes.push_back(p_node);
      if (p_node->appData1.ptr) {
        // it was matched to discovered node!
        anyOfBoardMatch++;
        anyOfSystemMatch++;
        // since we only need one to match the board we do not need to
        // continue...
        break;
      }
    } else {
      if (p_node->appData1.ptr) {
        anyOfSystemMatch++;
      }
    }
  }

  // got the markings:
  if (! anyOfSystemMatch) {
    if (reportMissing) {
      diag << "Missing System:" << p_system->name << "("
           << p_system->type << ")" << endl;

      // we limit the number of reported connections ...
      int numRep = 0;
      for (map_str_psysport::iterator spI = p_system->PortByName.begin();
           (spI != p_system->PortByName.end()) && (numRep < MaxConnRep);
           spI++) {
        IBSysPort *p_sysPort = (*spI).second;
        if (p_sysPort->p_remoteSysPort) {
          numRep++;
          diag << "   Should be connected by cable from port: "
               << (*spI).first
               << "(" << p_sysPort->p_nodePort->p_node->name << "/P"
               << p_sysPort->p_nodePort->num << ")"
               << " to:" << p_sysPort->p_remoteSysPort->p_system->name
               << "/" << p_sysPort->p_remoteSysPort->name
               << "(" << p_sysPort->p_remoteSysPort->p_nodePort->p_node->name
               << "/P" << p_sysPort->p_remoteSysPort->p_nodePort->num << ")"
               << endl;
        }
      }
      if (numRep == MaxConnRep) diag << "   ..." << endl;
      diag << endl;
    } else {
      diag << "Extra System:" << p_system->name << endl;
      int numRep = 0;
      for (unsigned int pn = 1;
           (pn <= p_node->numPorts) && (numRep < MaxConnRep);
           pn++) {
        IBPort *p_port = p_node->getPort(pn);
        if (p_port && p_port->p_remotePort) {
          numRep++;
          if (p_port->p_remotePort->p_node->appData1.ptr) {
            IBNode *p_sNode =
              (IBNode *)p_port->p_remotePort->p_node->appData1.ptr;
            // NOTE: we can not assume all ports were matched!
            diag << "   Connected by cable from port: P" << pn
                 << " to:"
                 << p_sNode->name << "/P" << p_port->p_remotePort->num
                 << endl;
          } else {
            diag << "   Connected by cable from port: P" << pn
                 << " to:" << p_port->p_remotePort->getName() << endl;
          }
        }
      }
      if (numRep == MaxConnRep) diag << "   ..." << endl;
      diag << endl;
    }
    anyMissmatch++;

    // also we do not need any more checks on this system
    for (map_str_pnode::iterator nI = p_system->NodeByName.begin();
         nI != p_system->NodeByName.end();
         nI++) {
      IBNode *p_node = (*nI).second;
      TopoMarkNodeAsReported(p_node);
    }
  } else if (! anyOfBoardMatch) {
    if (reportMissing) {
      diag << "Missing System Board:" << nodeBoardName << endl;
      diag << endl;
    } else {
      diag << "Extra System Board:" << nodeBoardName << endl;
      diag << endl;
    }
    anyMissmatch++;

    for (list< IBNode *>::iterator nI = boardNodes.begin();
         nI != boardNodes.end();
         nI++) {
      TopoMarkNodeAsReported(*nI);
    }
  } else {
    if (reportMissing) {
      diag << "Missing Node:" << p_system->name
           << "/" << p_node->name << endl;
      int numRep = 0;
      for (unsigned int pn = 1;
           (pn <= p_node->numPorts) && (numRep < MaxConnRep);
           pn++) {
        IBPort *p_port = p_node->getPort(pn);
        if (p_port && p_port->p_remotePort) {
          numRep++;
          diag << "   Should be connected by cable from port:" << pn
               << " to:" << p_port->getName() << endl;
        }
      }
      if (numRep == MaxConnRep) diag << "   ..." << endl;
      diag << endl;
    } else {
      diag << "Extra Node:" << p_system->name
           << "/" << p_node->name << endl;
      int numRep = 0;
      for (unsigned int pn = 1;
           (pn <= p_node->numPorts) && (numRep < MaxConnRep);
           pn++) {
        IBPort *p_port = p_node->getPort(pn);
        if (p_port && p_port->p_remotePort) {
          numRep++;
          if (p_port->p_remotePort->p_node->appData1.ptr) {
            IBNode *p_sNode =
              (IBNode *)p_port->p_remotePort->p_node->appData1.ptr;
            IBPort *p_tmpPort = p_sNode->getPort(p_port->p_remotePort->num);
            if (p_tmpPort)
              diag << "   Connected by cable from port:" << pn
                   << " to:"
                   << p_tmpPort->getName()
                   << endl;
            else
              diag << "   Connected by cable from port:" << pn
                   << " to:"
                   << p_sNode->name << "/P" << p_port->p_remotePort->num
                   << endl;
          } else {
            diag << "   Connected by cable from port:" << pn
                 << " to:" << p_port->p_remotePort->getName() << endl;
          }
        }
      }
      if (numRep == MaxConnRep) diag << "   ..." << endl;
      diag << endl;
    }
    anyMissmatch++;

    TopoMarkNodeAsReported(p_node);
  }
  return(anyMissmatch);
}

// Given two matching nodes - report un-matching links.
// To avoid duplicated reporting:
// * We only report missmatching links to matched nodes.
// * We only report link to nodes with bigger pointer value
// RETURN number of missmatches
static int
TopoReportMatchedNodesUnMatchingLinks(
  IBNode *p_sNode,
  IBNode *p_dNode,
  stringstream &diag)
{
  int anyMissmatch = 0;
  // missmatch is when port numbers differ
  // or the remote node is not the same.
  IBPort *p_sPort, *p_dRemPort;
  IBPort *p_dPort, *p_sRemPort;

  for (unsigned int pn = 1; pn <= p_dNode->numPorts; pn++) {
    p_dPort = p_dNode->getPort(pn);
    p_sPort = p_sNode->getPort(pn);
    if (p_dPort)
      p_dRemPort = p_dPort->p_remotePort;
    else
      p_dRemPort = NULL;

    if (p_sPort)
      p_sRemPort = p_sPort->p_remotePort;
    else
      p_sRemPort = NULL;

    // so we have four cases
    if (p_dRemPort && p_sRemPort) {
      // can we ignore this report:
      if (!p_dRemPort->p_node->appData1.ptr)
        continue;

      IBNode *p_actRemSNode = (IBNode *)p_dRemPort->p_node->appData1.ptr;
      IBPort *p_actRemSPort = p_actRemSNode->getPort(p_dRemPort->num);

      // make sure the expected remote spec node is what we got.
      if (p_actRemSNode != p_sRemPort->p_node) {
        // clasify internal and external cables
        if (p_sNode->p_system != p_actRemSNode->p_system) {
          IBPort *p_repPort = p_actRemSNode->getPort(p_dRemPort->num);
          if (p_repPort)
            diag << "Wrong cable connecting:" << p_sPort->getName()
                 << " to:" << p_repPort->getName()
                 << " instead of:" << p_sRemPort->getName() << endl;
          else
            diag << "Wrong cable connecting:" << p_sPort->getName()
                 << " to:" << p_actRemSNode->name << "/P" << p_dRemPort->num
                 << " instead of:" << p_sRemPort->getName() << endl;
        } else {
          diag << "Wrong Internal Link connecting:" << p_sPort->getName()
               << " to:" << p_actRemSNode->name << "/P" << p_dRemPort->num
               << " instead of:" << p_sRemPort->getName() << endl;
        }
        anyMissmatch++;
      } else {
        // make sure same port remote number
        if (p_dRemPort->num != p_sRemPort->num) {
          if (p_sNode->p_system != p_actRemSNode->p_system) {
            IBPort *p_repPort = p_actRemSNode->getPort(p_dRemPort->num);
            if (p_repPort)
              diag << "Wrong cable connecting:" << p_sPort->getName()
                   << " to:" << p_repPort->getName()
                   << " instead of:" << p_sRemPort->getName() << endl;
            else
              diag << "Wrong cable connecting:" << p_sPort->getName()
                   << " to:" << p_actRemSNode->name << "/P" << p_dRemPort->num
                   << " instead of:" << p_sRemPort->getName() << endl;
          } else {
            diag << "Wrong Internal Link connecting:" << p_sPort->getName()
                 << " to:" << p_actRemSNode->name << "/P" << p_dRemPort->num
                 << " instead of:" << p_sRemPort->getName() << endl;
          }
          anyMissmatch++;
        }
      }
      // anyway make sure we got the width and speed.
      if (p_sPort->width != p_dPort->width) {
        diag << "Wrong link width on:" << p_sPort->getName()
             << ". Expected:" << width2char(p_sPort->width)
             << " got:" << width2char(p_dPort->width) << endl;
        anyMissmatch++;
      }
      if (p_sPort->speed != p_dPort->speed) {
        diag << "Wrong link speed on:" << p_sPort->getName()
             << ". Expected:" << speed2char(p_sPort->speed)
             << " got:" << speed2char(p_dPort->speed) << endl;
        anyMissmatch++;
      }
      // done with the case both spec and dicsovered links exists
    } else if (!p_dRemPort && p_sRemPort) {
      // We have a missing cable/link

      // can we ignore this report if not both spec nodes matched
      // or not up going ...
      if (!p_sRemPort->p_node->appData1.ptr)
        continue;

      // we can ignore cases where the other side of the link is
      // connected - since it will be reported later
      IBPort *p_actRemPort =
        ((IBNode *)p_sRemPort->p_node->appData1.ptr)->getPort(p_sRemPort->num);
      if (p_actRemPort && p_actRemPort->p_remotePort)
        continue;

      // as the spec connections are reciprocal we do not want double the
      // report
      if (p_sPort > p_sRemPort)
      {
        // clasify the link as cable or internal
        if (p_sPort->p_sysPort || p_sRemPort->p_sysPort) {
          diag << "Missing cable connecting:" << p_sPort->getName()
               << " to:" <<  p_sRemPort->getName() << endl;
        } else {
          diag << "Missing internal Link connecting:" << p_sPort->getName()
               << " to:" << p_sRemPort->getName() << endl;
        }
      }
      anyMissmatch++;

    } else if (p_dRemPort && !p_sRemPort) {
      // Only a discovered link exists:

      // can we ignore this report if not both discovered nodes matched
      // or not up going ...
      if (!p_dRemPort->p_node->appData1.ptr)
        continue;

      // we can ignore cases where the other side of the link was
      // supposed to be connected - since it will be reported later as wrong
      IBPort *p_actRemPort =
        ((IBNode *)p_dRemPort->p_node->appData1.ptr)->getPort(p_dRemPort->num);
      if (p_actRemPort && p_actRemPort->p_remotePort)
        continue;

      // we also ignore it by comparing pointer values on discoeverd
      // fabric to avoid double reporting.
      if (p_dRemPort < p_dPort) continue;

      string portName;
      if (p_dRemPort->p_node->appData1.ptr) {
        IBPort *p_port =
          ((IBNode *)p_dRemPort->p_node->appData1.ptr)->getPort(p_dRemPort->num);
        // We can not guarantee all ports match on matching nodes
        if (p_port)
          portName = p_port->getName();
        else
        {
          char buff[256];
          sprintf(buff, "%s/P%d",
                  ((IBNode *)p_dRemPort->p_node->appData1.ptr)->name.c_str(),
                  p_dRemPort->num);

          portName = string(buff);
        }
      } else {
        portName = p_dRemPort->getName();
      }

      string specPortName;
      if (p_sPort)
        specPortName = p_sPort->getName();
      else {
        char buf[16];
        sprintf(buf,"%d",pn);
        specPortName = p_sNode->name + "/" + buf;
      }

      // clasify the link as cable or internal
      if ((p_dNode->p_system != p_dRemPort->p_node->p_system) ||
          (p_sPort && p_sPort->p_sysPort) ) {
        diag << "Extra cable connecting:" << specPortName
             << " to:" << portName  << endl;
      } else {
        diag << "Extra internal Link connecting:" << specPortName
             << " to:" << portName << endl;
      }
      anyMissmatch++;
    }
  }
  if (anyMissmatch) diag << endl;

  return(anyMissmatch);
}

static void
TopoCleanUpBeforeMerge(IBFabric *p_sFabric, IBFabric *p_dFabric)
{
  IBNode *p_node;
  // since we only use the appData1 and appData2 on all node  ...
  for (map_str_pnode::iterator nI = p_sFabric->NodeByName.begin();
       nI != p_sFabric->NodeByName.end();
       nI++) {
    p_node = (*nI).second;
    p_node->appData1.ptr = 0;
    p_node->appData2.val = 0;
  }

  for (map_str_pnode::iterator nI = p_dFabric->NodeByName.begin();
       nI != p_dFabric->NodeByName.end();
       nI++) {
    p_node = (*nI).second;
    p_node->appData1.ptr = 0;
    p_node->appData2.val = 0;
  }
}

// Report Topology Missmatched and Build the Merged Fabric:
int
TopoReportMissmatches(
  IBPort *p_sPort, // Starting port on the specification fabrric
  IBPort *p_dPort,
  stringstream &diag)
{
  IBNode *p_sNode;
  IBNode *p_dNode;
  int anyMissmatchedSpecNodes = 0;
  int anyMissmatchedDiscNodes = 0;
  int anyMissmatchedLinks = 0;

  // since we do not want to report errors created by previous node failure
  // to discover or match we will BFS from the start ports.

  // NOTE: we only put matched nodes in the fifo.
  list < IBNode * > bfsFifo;

  // If the starting nodes match:
  if (p_dPort->p_node->appData1.ptr)
    bfsFifo.push_back(p_dPort->p_node);

  // BFS through the fabric reporting
  while (! bfsFifo.empty()) {
    p_dNode = bfsFifo.front();
    bfsFifo.pop_front();
    // we got in here only with matching nodes:
    p_sNode = (IBNode *)p_dNode->appData1.ptr;
    if (!p_sNode) {
      cerr << "How did we get in BFS with missmatching nodes!" << endl;
      exit (1);
    }

    // Try to match all ports of the current nodes
    // we assume port counts match since the nodes match
    for (unsigned int pn = 1; pn <= p_dNode->numPorts; pn++) {
      IBPort *p_dPort = p_dNode->getPort(pn);
      IBPort *p_sPort = p_sNode->getPort(pn);

      if (! p_dPort || !p_sPort) continue;

      IBPort *p_dRemPort = p_dPort->p_remotePort;
      IBPort *p_sRemPort = p_sPort->p_remotePort;

      // we only do care about spec nodes for now:
      if (!p_sRemPort ) continue;

      // if we did visit it by this reporting algorithm:
      if (TopoIsNodeMarkedAsReported(p_sRemPort->p_node)) continue;

      // if the remote spec node is not marked matched:
      if (!p_sRemPort->p_node->appData1.ptr) {
        if (TopoReportMismatchedNode(p_sRemPort->p_node, 1, diag))
          anyMissmatchedSpecNodes++;
      } else {
        // mark as visited.
        TopoMarkNodeAsReported(p_sRemPort->p_node);

        // ok so we matched the nodes - put them in for next step:
        if (p_dRemPort) {
           if (p_dRemPort->p_node->appData1.ptr)
              bfsFifo.push_back(p_dRemPort->p_node);
        }
      }
    } // all ports
  } // next nodes available...

  if (anyMissmatchedSpecNodes) diag << endl;

  IBFabric *p_dFabric = p_dPort->p_node->p_fabric;

  // now when we are done reporting missing - let us report extra nodes:
  // but we only want to count those who touch matching nodes BFS wise...
  // If the starting nodes match:
  if (p_dPort->p_node->appData1.ptr) {
    bfsFifo.push_back(p_dPort->p_node);
  } else {
    diag << "Even starting ports do not match! "
         << "Expected:" << p_sPort->getName()
         << " but it is probably not connected correctly." <<  endl;
    anyMissmatchedDiscNodes++;
  }

  // we track visited nodes in here by clearing their visited bits

  // BFS through the fabric reporting
  while (! bfsFifo.empty()) {
    p_dNode = bfsFifo.front();
    bfsFifo.pop_front();

    int anyPortMatch = 0;
    // Try to match all ports of the current nodes
    // we assume port counts match since the nodes match
    for (unsigned int pn = 1; pn <= p_dNode->numPorts; pn++) {

      IBPort *p_tmpPort = p_dNode->getPort(pn);

      if (! p_tmpPort) continue;

      IBPort *p_dRemPort = p_tmpPort->p_remotePort;

      if (!p_dRemPort) continue;

      IBNode *p_node = p_dRemPort->p_node;

      // we only care about missmatched discovered nodes
      if (! p_node->appData1.ptr) {
        // if not already visited.
        if (! TopoIsNodeMarkedAsReported(p_node))
          if (TopoReportMismatchedNode(p_node, 0, diag))
            anyMissmatchedDiscNodes++;
      } else {
        // if not already visited.
        if (! TopoIsNodeMarkedAsReported(p_node))
          // it is an OK node so we traverse through
          bfsFifo.push_back(p_node);
        anyPortMatch++;
      }
    } // all ports

    p_sNode = (IBNode *)p_dNode->appData1.ptr;
    if (!anyPortMatch) {
      diag << "None of node:" << p_sNode->name
           << " remote nodes match the topology."
           << " No further extra nodes reported" << endl;
    }

    TopoMarkNodeAsReported(p_dNode);
  } // next nodes available...

  if (anyMissmatchedDiscNodes) diag << endl;

  // finaly we want to report any missmatched cables between matching nodes
  for (map_str_pnode::iterator nI = p_dFabric->NodeByName.begin();
       nI != p_dFabric->NodeByName.end();
       nI++) {
    p_dNode = (*nI).second;
    p_sNode = (IBNode *)p_dNode->appData1.ptr;
    if ( p_sNode ) {
      // report any missmatched links on this node.
      if (TopoReportMatchedNodesUnMatchingLinks(p_sNode, p_dNode, diag))
        anyMissmatchedLinks++;
    }
  }

  if (anyMissmatchedLinks) diag << endl;

  return anyMissmatchedLinks +
    anyMissmatchedDiscNodes +
    anyMissmatchedSpecNodes;
}

// Return 0 if fabrics match 1 otherwise.
int
TopoMatchFabrics(
  IBFabric *p_sFabric,      // The specification fabric
  IBFabric *p_dFabric,      // The discovered fabric
  char     *anchorNodeName, // The name of the system to be the anchor point
  int       anchorPortNum,  // The port number of the anchor port
  uint64_t  anchorPortGuid, // Guid of the anchor port
  char **messages)
{
  stringstream diag, tmpDiag;
  int status = 0;

  IBNode *p_sNode;
  IBPort *p_sPort;
  IBPort *p_dPort;

  // get the anchor port on the spec fabric - by name:
  p_sNode = p_sFabric->getNode(anchorNodeName);
  if (! p_sNode) {
    diag << "Fail to find anchor node:"
         << anchorNodeName << " on the specification fabric." << endl;
    status = 1;
    goto Exit;
  }

  p_sPort = p_sNode->getPort(anchorPortNum);
  if (! p_sPort) {
    diag << "Fail to find anchor port:"
         << anchorNodeName <<  anchorPortNum
         << " in the specification fabric." << endl;
    status = 1;
    goto Exit;
  }

  // get the anchor port on the discovered fabric - by guid.
  p_dPort = p_dFabric->getPortByGuid(anchorPortGuid);
  if (! p_dPort) {
    diag << "Fail to find anchor port guid:"
         << guid2str(anchorPortGuid)
         << " in the discovered fabric." << endl;
    status = 1;
    goto Exit;
  }

  // Cleanup the flags we use for tracking matching and progress
  TopoCleanUpBeforeMerge(p_sFabric, p_dFabric);

  // Do a BFS matching nodes from each fabrics. When this leaves
  // the appData1.ptr will cross point. status is 0 if there is no
  // difference
  status = TopoBFSAndMatchFromPorts(p_sPort, p_dPort, tmpDiag);
  if (status) {
    cout << "-W- Topology Matching First Phase Found Missmatches:\n"
         << tmpDiag.str() << endl;
  }

  // Do the second step in matching - rely on preexisting matched nodes
  // and try to map the unmatched.
  TopoMatchSpecNodesByAdjacentNode(p_sFabric);

  if (TopoReportMissmatches(p_sPort, p_dPort, diag))
    status = 1;

 Exit:

  string msg(diag.str());
  int msgLen = strlen(msg.c_str());
  if (msgLen) {
    *messages = (char *)malloc(msgLen + 1);
    strncpy(*messages, msg.c_str(), msgLen);
    (*messages)[msgLen] = '\0';
  } else {
    *messages = NULL;
  }
  return(status);
}

// Given a disc node pointer create the merged system and node by inspecting
// the merged spec fabric too.
// The node will have all it's ports setup (no links) and the system and
// sysPorts as well
static IBNode *
TopoCopyNodeToMergedFabric(
  IBFabric *p_mFabric,
  IBNode   *p_dNode)
{
  IBNode    *p_sNode = (IBNode *)p_dNode->appData1.ptr;
  IBSystem  *p_system = 0;
  IBSysPort *p_sysPort = 0;
  IBNode    *p_node = 0;

  string nodeName = p_dNode->name;
  string sysName =  p_dNode->p_system->name;
  string sysType =  p_dNode->p_system->type;

  // if we have a matching spec node we use that instead:
  if ( p_sNode ) {
    nodeName = p_sNode->name;
    sysName =  p_sNode->p_system->name;
    sysType =  p_sNode->p_system->type;
  }

  // make sure the system exists:
  // NOTE - we can not use the makeSystem of the fabric since it
  // will instantiate the entire system.
  p_system = p_mFabric->getSystem(sysName);
  if (!p_system) {
    p_system = new IBSystem(sysName, p_mFabric, sysType);
    // copy other system info:
    p_system->guid_set(p_dNode->p_system->guid_get());
  }

  // create the node:
  p_node = p_mFabric->getNode(nodeName);
  if (! p_node) {
    p_node =
      p_mFabric->makeNode(nodeName, p_system, p_dNode->type,
                          p_dNode->numPorts);

    // copy extra info:
    p_node->guid_set(p_dNode->guid_get());
    p_node->devId  = p_dNode->devId;
    p_node->revId  = p_dNode->revId;
    p_node->vendId = p_dNode->vendId;

    if (p_sNode)
      p_node->attributes = p_sNode->attributes;

    if (p_dNode && p_dNode->attributes.size())
      if (p_node->attributes.size()) {
        p_node->attributes += string(",") + p_dNode->attributes;
      } else {
        p_node->attributes = p_dNode->attributes;
      }

    // create the node ports:
    for (unsigned int pn = 1; pn <=  p_dNode->numPorts; pn++) {

      // we only care if the discovered port exists:
      IBPort *p_dPort = p_dNode->getPort(pn);
      if (! p_dPort) continue;

      // some fabrics might be generated with all ports
      // pre-allocated.
      IBPort *p_port = p_node->getPort(pn);
      if (!p_port) p_port = new IBPort(p_node, pn);

      // copy some vital data:
      p_port->guid_set(p_dPort->guid_get());
      p_port->base_lid = p_dPort->base_lid;
      p_mFabric->setLidPort(p_port->base_lid, p_port);
      if (p_mFabric->maxLid < p_port->base_lid)
        p_mFabric->maxLid = p_port->base_lid;

      // if there is a matching spec port we use it and get the
      // sys port name etc
      IBPort *p_sPort = 0;
      if (p_sNode) p_sPort = p_sNode->getPort(pn);
      if (p_sPort) {
        // if we had a spec sysPort make it:
        if (p_sPort->p_sysPort) {
          p_sysPort = new IBSysPort(p_sPort->p_sysPort->name, p_system);
          p_sysPort->p_nodePort = p_port;
          p_port->p_sysPort = p_sysPort;
        } else {
          p_port->p_sysPort = 0;
        }
      } else {
        // the discovered fabric might have a sysport?
        if (p_dPort->p_sysPort) {
          p_sysPort = new IBSysPort(p_dPort->p_sysPort->name, p_system);
          p_sysPort->p_nodePort = p_port;
          p_port->p_sysPort = p_sysPort;
        } else {
          p_port->p_sysPort = 0;
        }
      }
    }
  }
  return p_node;
}

// Copy the link from the p_dPort to it's remote port to the
// given merged port.
static void
TopoCopyLinkToMergedFabric(
  IBFabric *p_mFabric,
  IBPort   *p_mPort,
  IBPort   *p_dPort)
{

  // make sure the remote node exists or copy it to the merged fabric
  IBNode *p_remNode =
    TopoCopyNodeToMergedFabric(p_mFabric, p_dPort->p_remotePort->p_node);

  // find the remote port on the merged fabric
  IBPort *p_remPort = p_remNode->getPort(p_dPort->p_remotePort->num);
  if (!p_remPort ) {
    cerr << "-F- No Remote port:" << p_dPort->p_remotePort->num
         << " on node:" << p_remNode->name << endl;
    exit(1);
  }

  // we need to create sys ports connection if both ports are on sys ports
  if (p_remPort->p_sysPort && p_mPort->p_sysPort) {
    p_remPort->p_sysPort->connect(p_mPort->p_sysPort,
                                  p_dPort->width,
                                  p_dPort->speed);
  }
  else
    // The following error messages are actually not required at
    // all. If there is a missmatch on an internal node this will happen.
    /*
      if (p_remPort->p_sysPort) {
      cout << "-E- Linking:" << p_mPort->getName() << " to:"
      << p_remPort->p_node->name
      << "/" << p_dPort->p_remotePort->num << endl;
      cout << "-F- BAD LINK since Remote System port:"
      << p_remPort->p_sysPort->name << " exists, but no sys port for:"
      << p_mPort->getName() << endl;
      // exit(1);
      } else if (p_mPort->p_sysPort) {
      cout << "-F- BAD LINK since local has System port:"
      << p_mPort->p_sysPort->name << " exists, but no sys port for:"
      << p_remPort->getName() << endl;
      // exit(1);
      } else
    */
  {
    p_mPort->connect(p_remPort, p_dPort->width, p_dPort->speed);
    p_remPort->connect(p_mPort, p_dPort->width, p_dPort->speed);
  }
}

// Build a merged fabric from a matched discovered and spec fabrics:
// * Every node from the discovered fabric must appear
// * We sued matched nodes adn system names.
int
TopoMergeDiscAndSpecFabrics(
  IBFabric  *p_sFabric,
  IBFabric  *p_dFabric,
  IBFabric  *p_mFabric)
{

  // go through all nodes of the discovered fabric.
  // copy all their systems, and links...
  p_dFabric->setLidPort(0, NULL);
  p_dFabric->minLid = 1;
  p_dFabric->maxLid = 0;

  for (map_str_pnode::iterator nI = p_dFabric->NodeByName.begin();
       nI != p_dFabric->NodeByName.end();
       nI++) {
    IBNode *p_dNode = (*nI).second;

    // make sure the node exists as well as the system and ports and
    // sysports:
    IBNode *p_node = TopoCopyNodeToMergedFabric(p_mFabric, p_dNode);

    // go over all ports and connect accordingly:
    for (unsigned int pn = 1; pn <=  p_dNode->numPorts; pn++) {
      IBPort *p_dPort = p_dNode->getPort(pn);
      IBPort *p_port = p_node->getPort(pn);

      // we got a remote connection:
      if (p_port && p_dPort && p_dPort->p_remotePort) {
        TopoCopyLinkToMergedFabric(p_mFabric, p_port, p_dPort);
      }
    }
  }
  p_mFabric->minLid = p_dFabric->minLid;
  return 0;
}






Generated by  Doxygen 1.6.0   Back to index