[ofa-general] [PATCH] ibutils: Enhanced credit loop analysis

Yevgeny Kliteynik kliteyn at dev.mellanox.co.il
Tue Oct 7 02:31:17 PDT 2008


[On behalf of Vladimir Zdornov]

Enhanced credit loop analysis.
Multiple VL/SL support added.
Loops are detected using DFS.

Signed-off-by:  Vladimir Zdornov <zdv at mellanox.co.il>

---
 ibdm/datamodel/CredLoops.cpp |  643 ++++++++++++------------------------------
 ibdm/datamodel/Fabric.cpp    |  214 ++++++++++++++
 ibdm/datamodel/Fabric.h      |  104 +++++++-
 ibdm/src/osm_check.cpp       |  214 +++++++++------
 4 files changed, 619 insertions(+), 556 deletions(-)

diff --git a/ibdm/datamodel/CredLoops.cpp b/ibdm/datamodel/CredLoops.cpp
index 30cff4b..70e5879 100644
--- a/ibdm/datamodel/CredLoops.cpp
+++ b/ibdm/datamodel/CredLoops.cpp
@@ -46,55 +46,67 @@
  *
  */

-#define RT_NOT_USED 0
-#define RT_USED     1
-#define RT_VISITED  2
-#define RT_LOOP_TRACED 4
-
 //////////////////////////////////////////////////////////////////////////////

-// Allocate the tables on the switches
-int
-CrdLoopInitRtTbls(IBFabric *p_fabric) {
-  IBNode *p_node;
-
-  // Go over all SW nodes in the fabric and build a table
-  // of input to output ports links. Each element should track
-  // effect and traversal flags.
-  for( map_str_pnode::iterator nI = p_fabric->NodeByName.begin();
-		 nI != p_fabric->NodeByName.end();
-		 nI++) {
+// Apply DFS on a dependency graph

-	 p_node = (*nI).second;
-	 if (p_node->type != IB_SW_NODE) continue;
+int CrdLoopDFS(VChannel* ch) {
+  // Already been there
+  if (ch->getFlag() == Closed)
+    return 0;
+  // Credit loop
+  if (ch->getFlag() == Open) {
+    return 1;
+  }
+  // Mark as open
+  ch->setFlag(Open);
+  // Make recursive steps
+  for (int i=0; i<ch->getDependSize();i++) {
+    VChannel* next = ch->getDependency(i);
+    if (next) {
+      if (CrdLoopDFS(next))
+	return 1;
+    }
+  }
+  // Mark as closed
+  ch->setFlag(Closed);
+  return 0;
+}

-	 uint8_t *p_tbl =
-		new uint8_t[p_node->numPorts*p_node->numPorts];
+//////////////////////////////////////////////////////////////////////////////

-	 memset(p_tbl, RT_NOT_USED,
-			  sizeof(uint8_t)*p_node->numPorts*p_node->numPorts);
+// Go over CA's apply DFS on the dependency graphs starting from CA's port

-	 if (! p_tbl) {
-		cout << "-F- Fail to allocate memory for port routing table" << endl;
-		exit(2);
-	 }
+int CrdLoopFindLoops(IBFabric* p_fabric) {
+  unsigned int lidStep = 1 << p_fabric->lmc;

-	 // We use the appData1 of the node to store the routing links
-	 // info
-	 if (p_node->appData1.ptr) {
-		cout << "-W- Application Data Pointer already set for node:"
-			  << p_node->name << endl;
-		delete [] p_tbl;
-	 } else {
-		p_node->appData1.ptr = (void *)p_tbl;
+  // go over all CA ports in the fabric
+  for (int i = p_fabric->minLid; i <= p_fabric->maxLid; i += lidStep) {
+	 IBPort *p_Port = p_fabric->PortByLid[i];
+	 if (!p_Port || (p_Port->p_node->type == IB_SW_NODE)) continue;
+	 // Go over all CA's channels and find untouched one
+	 for (int j=0;j < p_fabric->getNumSLs(); j++) {
+	   dfs_t state = p_Port->channels[j]->getFlag();
+	   if (state == Open) {
+	     cout << "-E- open channel outside of DFS" << endl;
+	     return 1;
+	   }
+	   // Already processed, continue
+	   if (state == Closed)
+	     continue;
+	   // Found starting point
+	   if (CrdLoopDFS(p_Port->channels[j]))
+	     return 1;
 	 }
   }
   return 0;
 }

+
 //////////////////////////////////////////////////////////////////////////////

 // Trace a route from slid to dlid by LFT
+// Add dependency edges
 int CrdLoopMarkRouteByLFT (
   IBFabric *p_fabric,
   unsigned int sLid , unsigned int dLid
@@ -102,99 +114,97 @@ int CrdLoopMarkRouteByLFT (

   IBPort *p_port = p_fabric->getPortByLid(sLid);
   IBNode *p_node;
-  IBPort *p_remotePort;
+  IBPort *p_portNext;
   unsigned int lidStep = 1 << p_fabric->lmc;
-  int inPortNum = 0, outPortNum = 0;
-  uint8_t *p_tbl;
-  int hopCnt = 0;
+  int outPortNum = 0, inputPortNum = 0, hopCnt = 0;
+  bool done;

   // make sure:
-  if (! p_port) {
+  if (!p_port) {
 	 cout << "-E- Provided source:" << sLid
 			<< " lid is not mapped to a port!" << endl;
 	 return(1);
   }

-  // if the port is not a switch - go to the next switch:
-  if (p_port->p_node->type != IB_SW_NODE) {
-	 // try the next one:
-	 if (!p_port->p_remotePort) {
-		cout << "-E- Provided starting point is not connected !"
-			  << "lid:" << sLid << endl;
-		return 1;
-	 }
-	 inPortNum = p_port->p_remotePort->num;
-	 p_node = p_port->p_remotePort->p_node;
-  } else {
-	 // it is a switch :
-	 p_node = p_port->p_node;
-  }
+  // Retrieve the relevant SL
+  uint8_t SL, VL;
+  SL = VL = p_port->p_node->getPSLForLid(dLid);

+  if (!p_port->p_remotePort) {
+    cout << "-E- Provided starting point is not connected !"
+	 << "lid:" << sLid << endl;
+    return 1;
+  }

-  // verify we are finally of a switch:
-  if (p_node->type != IB_SW_NODE) {
-	 cout << "-E- Provided starting point is not connected to a switch !"
-			<< "lid:" << sLid << endl;
-	 return 1;
+  if (SL == IB_SLT_UNASSIGNED) {
+    cout << "-E- SL to destination is unassigned !"
+         << "slid: " << sLid << "dlid:" << dLid << endl;
+    return 1;
   }

-  // traverse:
-  int done = 0;
+  // check if we are done:
+  done = ((p_port->p_remotePort->base_lid <= dLid) &&
+	  (p_port->p_remotePort->base_lid+lidStep - 1 >= dLid));
   while (!done) {
-	 // calc next node:
-	 outPortNum = p_node->getLFTPortForLid(dLid);
-	 if (outPortNum == IB_LFT_UNASSIGNED) {
-		cout << "-E- Unassigned LFT for lid:" << dLid << " Dead end at:" << p_node->name << endl;
-		return 1;
-	 }
-
-	 // get the port on the other side
-	 p_port = p_node->getPort(outPortNum);
-
-	 if (! (p_port &&
-			  p_port->p_remotePort &&
-			  p_port->p_remotePort->p_node)) {
-		cout << "-E- Dead end at:" << p_node->name << endl;
-		return 1;
-	 }
-
-	 // Track it please:
-	 p_tbl = (uint8_t *)p_node->appData1.ptr;
-	 if (! p_tbl) {
-		cout << "-F- Got a non initialized routing table pointer!" << endl;
-		exit(2);
-	 }
-
-	 // cout << "-V- Add usage Node:" << p_node->name
-	 //		<< " In:" << inPortNum << " to:" << outPortNum <<  endl;
-
-	 p_tbl[(inPortNum - 1)*p_node->numPorts + outPortNum - 1] = RT_USED;
+    // Get the node on the remote side
+    p_node = p_port->p_remotePort->p_node;
+    // Get remote port's number
+    inputPortNum = p_port->p_remotePort->num;
+    // Get number of ports on the remote side
+    int numPorts = p_node->numPorts;
+    // Init vchannel's number of possible dependencies
+    p_port->channels[VL]->setDependSize((numPorts+1)*p_fabric->getNumVLs());
+
+    // Get port num of the next hop
+    outPortNum = p_node->getLFTPortForLid(dLid);
+    // Get VL of the next hop
+    int nextVL = p_node->getSLVL(inputPortNum,outPortNum,SL);
+
+    if (outPortNum == IB_LFT_UNASSIGNED) {
+      cout << "-E- Unassigned LFT for lid:" << dLid << " Dead end at:" << p_node->name << endl;
+      return 1;
+    }

-	 p_remotePort = p_port->p_remotePort;
-	 inPortNum = p_remotePort->num;
+    if (nextVL == IB_SLT_UNASSIGNED) {
+      cout << "-E- Unassigned SL2VL entry, iport: "<< inputPortNum<<", oport:"<<outPortNum<<", SL:"<<(int)SL<< endl;
+      return 1;
+    }

-	 // check if we are done:
-	 done = ((p_remotePort->base_lid <= dLid) &&
-				(p_remotePort->base_lid+lidStep - 1 >= dLid));
+      // get the next port on the other side
+    p_portNext = p_node->getPort(outPortNum);

-	 p_node = p_remotePort->p_node;
-	 if (hopCnt++ > 256) {
-		cout << "-E- Aborting after 256 hops - loop in LFT?" << endl;
-		return 1;
-	 }
+    if (! (p_portNext &&
+	   p_portNext->p_remotePort &&
+	   p_portNext->p_remotePort->p_node)) {
+      cout << "-E- Dead end at:" << p_node->name << endl;
+      return 1;
+    }
+    // Now add an edge
+    p_port->channels[VL]->setDependency(outPortNum*p_fabric->getNumVLs()+nextVL,p_portNext->channels[nextVL]);
+    // Advance
+    p_port = p_portNext;
+    VL = nextVL;
+    if (hopCnt++ > 256) {
+      cout << "-E- Aborting after 256 hops - loop in LFT?" << endl;
+      return 1;
+    }
+    //Check if done
+    done = ((p_port->p_remotePort->base_lid <= dLid) &&
+	    (p_port->p_remotePort->base_lid+lidStep - 1 >= dLid));
   }

   return 0;
 }

-//////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+// Go over all CA to CA paths and connect dependant vchannel by an edge

-// Go over all CA to CA paths and mark the output links
-// input links connections on these paths in the routing tables.
 int
-CrdLoopPopulateRtTbls(IBFabric *p_fabric) {
+CrdLoopConnectDepend(IBFabric* p_fabric)
+{
   unsigned int lidStep = 1 << p_fabric->lmc;
-  int anyError = 0, paths = 0;
+  int anyError = 0;
   unsigned int i,j;

   // go over all ports in the fabric
@@ -215,22 +225,20 @@ CrdLoopPopulateRtTbls(IBFabric *p_fabric) {
 		if (! p_dstPort) continue;

 		if (p_dstPort->p_node->type == IB_SW_NODE) continue;
-
 		unsigned int dLid = p_dstPort->base_lid;
-
 		// go over all LMC combinations:
-		for (unsigned int l = 0; l < lidStep; l++) {
-		  paths++;
-
-		  // Trace the path but record the input to output ports used.
-		  if (CrdLoopMarkRouteByLFT(p_fabric, sLid + l, dLid + l)) {
-			 cout << "-E- Fail to find a path from:"
-					<< p_srcPort->p_node->name << "/" << p_srcPort->num
-					<< " to:" << p_dstPort->p_node->name << "/" << p_dstPort->num
-					<< endl;
-			 anyError++;
-		  }
-		} // all LMC lids
+		for (unsigned int l1 = 0; l1 < lidStep; l1++) {
+		  for (unsigned int l2 = 0; l2 < lidStep; l2++) {
+		    // Trace the path but record the input to output ports used.
+		    if (CrdLoopMarkRouteByLFT(p_fabric, sLid + l1, dLid + l2)) {
+		      cout << "-E- Fail to find a path from:"
+			   << p_srcPort->p_node->name << "/" << p_srcPort->num
+			   << " to:" << p_dstPort->p_node->name << "/" << p_dstPort->num
+			   << endl;
+		      anyError++;
+		    }
+		  }// all LMC lids 2 */
+		} // all LMC lids 1 */
 	 } // all targets
   } // all sources

@@ -239,316 +247,34 @@ CrdLoopPopulateRtTbls(IBFabric *p_fabric) {
 	 return 1;
   }

-  cout << "-I- Marked " << paths << " CA to CA Paths" << endl;
   return 0;
 }

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

-// BFS from all CA's and require all inputs for an
-// output node to be marked visited to go through it.
-int
-CrdLoopBfsFromCAs(IBFabric *p_fabric) {
-  int loops = 0;
-  list< IBPort *> thisStepPorts, nextStepPorts;
-
-  // go over all CA nodes and track the input ports for next step
-  IBNode *p_node;
-  IBPort *p_port;
-
-  for( map_str_pnode::iterator nI = p_fabric->NodeByName.begin();
-		 nI != p_fabric->NodeByName.end();
-		 nI++) {
-
-	 p_node = (*nI).second;
-	 if (p_node->type != IB_CA_NODE) continue;
-
-	 // get the remote input port
-	 for (unsigned int pn = 1; pn <= p_node->numPorts; pn++) {
-		p_port = p_node->getPort(pn);
-
-		if (p_port && p_port->p_remotePort) {
-		  // add to the list
-		  thisStepPorts.push_back(p_port->p_remotePort);
-		}
-	 }
-  }
-
-  // while you have next step ports
-  while ( ! thisStepPorts.empty()) {
-	 loops++;
-
-	 nextStepPorts.clear();
-
-	 // go over all this step ports
-	 while (! thisStepPorts.empty()) {
-		p_port = thisStepPorts.front();
-		thisStepPorts.pop_front();
-
-		p_node = p_port->p_node ;
-
-		if (p_node->type != IB_SW_NODE) continue;
-
-		uint8_t *p_tbl = (uint8_t *)p_node->appData1.ptr;
-		int inPortNum = p_port->num;
-
-		// go over all the out ports marked by this input port:
-		for (unsigned int outPortNum = 1;
-           outPortNum <= p_node->numPorts; outPortNum++) {
-		  int idx = (inPortNum - 1)*p_node->numPorts + outPortNum - 1;
-		  // check if port was marked as used:
-		  if (p_tbl[idx] == RT_USED) {
-			 // zero the port USED:
-			 p_tbl[idx] = (RT_USED | RT_VISITED);
-
-			 // now check if all the effecting ports are cleard:
-			 int foundUnVisited = 0;
-			 for (unsigned int pn = 0; !foundUnVisited && (pn < p_node->numPorts);
-               pn++) {
-				idx = pn*p_node->numPorts + outPortNum - 1;
-				if (p_tbl[idx] == RT_USED) foundUnVisited = 1;
-			 }
-
-			 // only when we do not have a marked but not visited  we
-			 // can progress to next port:
-			 if (!foundUnVisited) {
-				// we only add ports if the are now unvisited:
-				IBPort *p_oPort = p_node->getPort(outPortNum);
-				if (p_oPort && p_oPort->p_remotePort) {
-				  nextStepPorts.push_back(p_oPort->p_remotePort);
-				}
-			 }
-		  }
-		}
-	 } // all this step ports
-
-	 // Copy next step ports to cur ports:
-	 thisStepPorts = nextStepPorts;
-  }
-
-  cout << "-I- Propagted ranking through Fabric in:"
-		 << loops << " BFS steps" << endl;
-  return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-// Dump Routing Tables:
-int
-CrdLoopDumpRtTbls(IBFabric *p_fabric) {
-  // go over all switches in the fabric
-  IBNode *p_node;
-
-  // Go over all SW nodes in the fabric and build a table
-  // of input to output ports links. Each element should track
-  // effect and traversal flags.
-  for( map_str_pnode::iterator nI = p_fabric->NodeByName.begin();
-		 nI != p_fabric->NodeByName.end();
-		 nI++) {
-
-	 p_node = (*nI).second;
-	 if (p_node->type != IB_SW_NODE) continue;
-
-	 cout << "---- RT TBL DUMP -----" << endl;
-	 cout << "SW:" << p_node->name << endl;
-
-	 uint8_t *p_tbl = (uint8_t*)p_node->appData1.ptr;
-
-	 // header
-	 cout << "I\\O ";
-	 for (unsigned int outPortNum = 1; outPortNum <= p_node->numPorts;
-         outPortNum++)
-		cout << setw(3) << outPortNum << " ";
-	 cout << endl;
-
-	 // Now go over all out ports and check all input port.
-	 for (unsigned int inPortNum = 1; inPortNum <= p_node->numPorts;
-         inPortNum++) {
-		cout << setw(3) << inPortNum <<  " ";
-		// go over all the out ports marked by this input port:
-		for (unsigned int outPortNum = 1; outPortNum <= p_node->numPorts;
-           outPortNum++) {
-		  int idx = (inPortNum - 1)*p_node->numPorts + outPortNum - 1;
-		  if (p_tbl[idx] == RT_USED)
-			 cout << setw(3) << "USE ";
-		  else if (p_tbl[idx] == (RT_USED | RT_VISITED))
-			 cout << setw(3) << "VIS ";
-		  else {
-			 cout << setw(3) << "   ";
-		  }
-		}
-		cout << endl;
-	 }
-  }
-  return(0);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-// Trace a loop through a given node ports pair
-// We DFS fowrard and report all nodes of all the loops found.
-int
-CrdLoopTraceLoop(IBFabric *p_fabric,
-					  IBNode *p_endNode,
-					  int inPortNum,
-					  IBNode *p_startNode,
-					  int outPortNum,
-					  string path = string(""),
-					  int hops = 0,
-                 int doNotPrintPath = 0
-					  ) {
-
-  // find the other end of the link if any
-  IBPort *p_port = p_startNode->getPort(outPortNum);
-
-  // we need to have a port and remote port
-  if (! p_port || !p_port->p_remotePort) return 0;
-
-  IBNode *p_remNode = p_port->p_remotePort->p_node;
-
-  // we never go through CAs
-  if (p_remNode->type != IB_SW_NODE) return 0;
-
-  uint8_t *p_tbl = (uint8_t*)p_remNode->appData1.ptr;
-
-  // if it is the target end node and port
-  if (p_remNode == p_endNode && p_port->p_remotePort->num == inPortNum) {
-	 // print the path
-	 cout << "--------------------------------------------" << endl;
-	 cout << "-E- Found a credit loop on:" << p_endNode->name
-			<< " from port:" << inPortNum << " to port:"
-			<< outPortNum << endl;
-    if (! doNotPrintPath) {
-      cout << path << endl;
-      cout << p_endNode->name << " " << inPortNum << endl;
-    }
-	 return(1);
-  } else {
-	 // track the number of downwards paths found.
-	 int numPaths = 0;
-	 static char buf[128];
-
-	 // we will track where we come from
-	 sprintf(buf, "%s %u -> ",
-				p_remNode->name.c_str(),p_port->p_remotePort->num);
-
-	 // it is possible we already visited this node since we trace a
-	 // loop that is different then our own.
-	 if (path.find(buf) != string::npos) {
-      if (! doNotPrintPath)
-        cout << "-W- Marking a 'scroll' side loop at:"
-             << p_remNode->name << "/" << p_port->p_remotePort->num << endl;
-
-		// to avoid going into this scroll again
-		// we encode a return code that should mark the
-		// path as a scroll:
-		return -1;
-	 }
-
-	 // abort if hops count is bigger then 1000
-	 if (hops > 1000) {
-      if (! doNotPrintPath)
-        cout << "-W- Aborting path:" << path << endl;
-		return 0;
-	 }
-
-	 // add yourself to the path
-	 string fwdPath = path + string("\n") + string(buf);
-
-	 // go over all out ports not aleady marked routed from this in port
-	 for (unsigned int pn = 1; pn <= p_remNode->numPorts; pn++) {
-		int idx = (p_port->p_remotePort->num - 1)*p_remNode->numPorts + pn - 1;
-
-		// do we have a used but not visited connection:
-		if (p_tbl[idx] == RT_USED) {
-		  // traverse forward
-		  sprintf(buf, "%u", pn);
-		  int foundPaths =
-			 CrdLoopTraceLoop(p_fabric, p_endNode, inPortNum,
-									p_remNode, pn, fwdPath + string(buf), hops++,
-                           doNotPrintPath);
-
-		  // we might have encountered a scroll (return value < 0)
-		  // so we sould ignore it in the global count.
-		  if (foundPaths > 0) numPaths += foundPaths;
-
-		  // if found a loop or a scroll downwards mark the local port pair.
-		  if (foundPaths) {
-			 p_tbl[idx] = RT_LOOP_TRACED & RT_USED;
-		  }
-		}
-	 }
-	 return(numPaths);
-  }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-// Report all Switch ports that are still marked as not
-// fully visited.
-int
-CrdLoopReportLoops(IBFabric *p_fabric, int doNotPrintPath) {
-  int anyError = 0;
-
-  // go over all switches in the fabric looking for used link to link
-  // that was not marked as visited.
-  IBNode *p_node;
-
-  // Go over all SW nodes in the fabric and build a table
-  // of input to output ports links. Each element should track
-  // effect and traversal flags.
-  for( map_str_pnode::iterator nI = p_fabric->NodeByName.begin();
-		 nI != p_fabric->NodeByName.end();
-		 nI++) {
-
-	 p_node = (*nI).second;
-	 if (p_node->type != IB_SW_NODE) continue;
-
-	 uint8_t *p_tbl = (uint8_t*)p_node->appData1.ptr;
-
-	 // Now go over all out ports and check all input port.
-	 for (unsigned int inPortNum = 1; inPortNum <= p_node->numPorts;
-         inPortNum++) {
-		// go over all the out ports marked by this input port:
-		for (unsigned int outPortNum = 1; outPortNum <= p_node->numPorts;
-           outPortNum++) {
-		  int idx = (inPortNum - 1)*p_node->numPorts + outPortNum - 1;
-
-		  if (p_tbl[idx] == RT_USED) {
-			 char buf[16];
-			 sprintf(buf, " %u", outPortNum);
-			 int loops = CrdLoopTraceLoop(p_fabric, p_node, inPortNum,
-                                       p_node, outPortNum,
-													p_node->name + string(buf),
-                                       0, doNotPrintPath
-													);
-			 anyError += loops;
-		  }
-		}
-	 }
-  }
-  if (anyError) cout << "--------------------------------------" << endl;
-  return anyError;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
 // Prepare the data model
 int
 CrdLoopPrepare(IBFabric *p_fabric) {
-  IBNode *p_node;
-
-  // Go over all SW nodes in the fabric and cleanup
-  for( map_str_pnode::iterator nI = p_fabric->NodeByName.begin();
-		 nI != p_fabric->NodeByName.end();
-		 nI++) {
-
-	 p_node = (*nI).second;
-	 if (p_node->type != IB_SW_NODE) continue;
+  unsigned int lidStep = 1 << p_fabric->lmc;

-	 if (p_node->appData1.ptr) {
-		p_node->appData1.ptr = NULL;
-	 }
+  // go over all ports in the fabric
+  for (int i = p_fabric->minLid; i <= p_fabric->maxLid; i += lidStep) {
+    IBPort *p_Port = p_fabric->PortByLid[i];
+    if (!p_Port) continue;
+    IBNode *p_node = p_Port->p_node;
+    int nL;
+    if (p_node->type == IB_CA_NODE)
+      nL = p_fabric->getNumSLs();
+    else
+      nL = p_fabric->getNumVLs();
+    // Go over all node's ports
+    for (int k=0;k<p_node->Ports.size();k++) {
+      IBPort* p_Port = p_node->Ports[k];
+      // Init virtual channel array
+      p_Port->channels.resize(nL);
+      for (int j=0;j<nL;j++)
+	p_Port->channels[j] = new VChannel;
+    }
   }
   return 0;
 }
@@ -556,23 +282,25 @@ CrdLoopPrepare(IBFabric *p_fabric) {
 // Cleanup the data model
 int
 CrdLoopCleanup(IBFabric *p_fabric) {
-  IBNode *p_node;
-
-  // Go over all SW nodes in the fabric and cleanup
-  for( map_str_pnode::iterator nI = p_fabric->NodeByName.begin();
-		 nI != p_fabric->NodeByName.end();
-		 nI++) {
-
-	 p_node = (*nI).second;
-	 if (p_node->type != IB_SW_NODE) continue;
+  unsigned int lidStep = 1 << p_fabric->lmc;

-	 if (p_node->appData1.ptr) {
-		uint8_t *p_tbl = (uint8_t *)p_node->appData1.ptr;
-		delete [] p_tbl;
-		p_node->appData1.ptr = NULL;
-	 }
+  // go over all ports in the fabric
+  for (int i = p_fabric->minLid; i <= p_fabric->maxLid; i += lidStep) {
+    IBPort *p_Port = p_fabric->PortByLid[i];
+    if (!p_Port) continue;
+    IBNode *p_node = p_Port->p_node;
+    int nL;
+    if (p_node->type == IB_CA_NODE)
+      nL = p_fabric->getNumSLs();
+    else
+      nL = p_fabric->getNumVLs();
+    // Go over all node's ports
+    for (int k=0;k<p_node->Ports.size();k++) {
+      IBPort* p_Port = p_node->Ports[k];
+      for (int j=0;j<nL;j++)
+	delete p_Port->channels[j];
+    }
   }
-  return 0;
 }

 //////////////////////////////////////////////////////////////////////////////
@@ -580,45 +308,30 @@ CrdLoopCleanup(IBFabric *p_fabric) {
 // Top Level Subroutine:
 int
 CrdLoopAnalyze(IBFabric *p_fabric) {
+  int res=0;

-  cout << "-I- Analyzing Fabric for Credit Loops (one VL used)." << endl;
-
-  CrdLoopPrepare(p_fabric);
-
-  // Allocate routing tables on all switches (appData1.ptr)
-  CrdLoopInitRtTbls(p_fabric);
-
-  // Go over all CA to CA paths and mark the output links
-  // input links connections on these paths
-  if (CrdLoopPopulateRtTbls(p_fabric)) {
-	 cout << "-E- Fail to populate the Routing Tables." << endl;
-	 return(1);
+  cout << "-I- Analyzing Fabric for Credit Loops "<<(int)p_fabric->getNumSLs()<<" SLs, "<<(int)p_fabric->getNumVLs()<< " VLs used...";
+  // Init data structures
+  if (CrdLoopPrepare(p_fabric)) {
+    cout << "-E- Fail to prepare data structures." << endl;
+    return(1);
   }
-
-  // CrdLoopDumpRtTbls(p_fabric);
-
-  // Start BFS from all CA's and require all inputs for an
-  // output node to be marked visited to go through it.
-  if (CrdLoopBfsFromCAs(p_fabric)) {
-	 cout << "-E- Fail to BFS from all CA nodes through the Routing Tables." << endl;
-	 return(1);
-  }
-
-  // Report all Switch ports that are still marked as not
-  // fully visited.
-  int numLoopPorts;
-  int doNotPrintPath = 1;
-  if ((numLoopPorts = CrdLoopReportLoops(p_fabric, doNotPrintPath))) {
-	 cout << "-E- Found:" << numLoopPorts
-			<< " Credit Loops" << endl;
-  } else {
-	 cout << "-I- No credit loops found." << endl;
+  // Create the dependencies
+  if (CrdLoopConnectDepend(p_fabric)) {
+    cout << "-E- Fail to build dependency graphs." << endl;
+    return(1);
   }
+  // Find the loops if exist
+  res = CrdLoopFindLoops(p_fabric);
+  if (!res)
+    cout << " no credit loops found" << endl;
+  else
+    cout << endl << "-E- credit loops in routing"<<endl;

   // cleanup:
   CrdLoopCleanup(p_fabric);

-  return 0;
+  return res;
 }


diff --git a/ibdm/datamodel/Fabric.cpp b/ibdm/datamodel/Fabric.cpp
index 272d808..6ef2f9d 100644
--- a/ibdm/datamodel/Fabric.cpp
+++ b/ibdm/datamodel/Fabric.cpp
@@ -454,6 +454,67 @@ IBNode::getLFTPortForLid (unsigned int lid) {
 }

 //////////////////////////////////////////////////////////////////////////////
+
+// Set the PSL Table:
+void
+IBNode::setPSLForLid (unsigned int lid, unsigned int maxLid, uint8_t sl) {
+  if (PSL.empty())
+  {
+    PSL.resize(maxLid + 1);
+    for(unsigned int i = 0; i<PSL.size(); i++)
+      PSL[i] = IB_SLT_UNASSIGNED;
+  }
+  PSL[lid] = sl;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Get the PSL Table:
+uint8_t
+IBNode::getPSLForLid (unsigned int lid) {
+  if (PSL.empty())
+    return 0;
+
+ if (PSL.size() < lid+1)
+    return IB_SLT_UNASSIGNED;
+
+  return PSL[lid];
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Set the SL2VL Table:
+void
+IBNode::setSLVL (unsigned int iport,unsigned int oport,uint8_t sl, uint8_t vl) {
+  // Create an empty table
+  if (SLVL.empty())
+  {
+    SLVL.resize(numPorts+1);
+    for (int i=0;i<SLVL.size();i++) {
+      SLVL[i].resize(numPorts+1);
+      for (int j=0;j<SLVL[i].size();j++) {
+	SLVL[i][j].resize(IB_NUM_SL);
+	for (int k=0;k<SLVL[i][j].size();k++)
+	  SLVL[i][j][k] = IB_SLT_UNASSIGNED;
+      }
+    }
+  }
+  SLVL[iport][oport][sl] = vl;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Get the SLVL Table:
+uint8_t
+IBNode::getSLVL (unsigned int iport,unsigned int oport,uint8_t sl) {
+  // Identity mapping
+  if (SLVL.empty())
+    return sl;
+
+  return SLVL[iport][oport][sl];
+}
+
+//////////////////////////////////////////////////////////////////////////////
 // Set the Multicast FDB table
 void
 IBNode::setMFTPortForMLid(
@@ -2017,6 +2078,159 @@ IBFabric::parseFdbFile(string fn) {
    return anyErr;
 }

+//////////////////////////////////////////////////////////////////////////////
+
+// Parse PSL file and set the SLT tables accordingly
+int
+IBFabric::parsePSLFile(string fn) {
+   ifstream f(fn.c_str());
+   int maxLid = 0;
+
+   char sLine[1024];
+   // 0x0002c90000000099 154 0
+   // srcguid dlid sl
+   regExp slLine("0x([0-9a-z]+) ([0-9]+) ([0-9]+)");
+   rexMatch *p_rexRes;
+
+   if (f.fail())
+   {
+      cout << "-E- Fail to open file:" << fn.c_str() << endl;
+      return 1;
+   }
+
+   cout << "-I- Parsing SL file:" << fn.c_str() << endl;
+
+   int anyErr = 0;
+
+   // Find max HCA LID
+   while (f.good()) {
+      f.getline(sLine,1024);
+      p_rexRes = slLine.apply(sLine);
+      if (p_rexRes)
+      {
+	unsigned int lid = strtoull(p_rexRes->field(2).c_str(), NULL, 10);
+	maxLid = lid > maxLid ? lid:maxLid;
+      }
+      /*else
+      {
+	cout << "-E- Wrong file format:" << fn.c_str() << endl;
+	anyErr++;
+	}*/
+   }
+   f.close();
+
+   // Make second pass and build the tables
+   f.open(fn.c_str(),ifstream::in);
+   if (f.fail())
+   {
+      cout << "-E- Fail to open file:" << fn.c_str() << endl;
+      return 1;
+   }
+
+   while (f.good()) {
+      f.getline(sLine,1024);
+
+      p_rexRes = slLine.apply(sLine);
+      if (p_rexRes)
+      {
+	uint64_t guid = strtoull(p_rexRes->field(1).c_str(), NULL, 16);
+	unsigned int lid = strtoull(p_rexRes->field(2).c_str(), NULL, 10);
+	uint8_t sl = strtoull(p_rexRes->field(3).c_str(), NULL, 10);
+
+	IBNode* p_node = getNodeByGuid(guid);
+        if (!p_node)
+        {
+           cout << "-E- Fail to find node with guid:"
+                << guid << endl;
+           anyErr++;
+        }
+	else
+	{
+	  // Update number of used SLs
+	  numSLs = sl+1 > numSLs ? sl+1:numSLs;
+	  // Insert table entry
+	  p_node->setPSLForLid(lid,maxLid,sl);
+	}
+	delete p_rexRes;
+      }
+      /*else
+      {
+	cout << "-E- Wrong file format:" << fn.c_str() << endl;
+	anyErr++;
+	}*/
+   }
+   cout << "-I- Defined "<< (int)numSLs << " SLs in use" <<endl;
+   f.close();
+
+   return anyErr;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Parse SLVL file and set the SL2VL tables accordingly
+int
+IBFabric::parseSLVLFile(string fn) {
+  numVLs = 1;
+  ifstream f(fn.c_str());
+
+  char sLine[1024];
+  // 0x0002c90000000201 5 1 0x01 0x23 0x45 0x67 0x89 0xab 0xcd 0xe7
+  // guid iport oport 0x(sl0)(sl1) 0x(sl2)(sl3)...
+  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])");
+  rexMatch *p_rexRes;
+
+  if (f.fail()) {
+    cout << "-E- Fail to open file:" << fn.c_str() << endl;
+    return 1;
+  }
+
+  cout << "-I- Parsing SLVL file:" << fn.c_str() << endl;
+
+  int anyErr = 0;
+
+   // Parse the file
+   while (f.good()) {
+      f.getline(sLine,1024);
+
+      p_rexRes = slLine.apply(sLine);
+      if (p_rexRes)
+      {
+	uint64_t guid = strtoull(p_rexRes->field(1).c_str(), NULL, 16);
+	unsigned int iport = strtoull(p_rexRes->field(2).c_str(), NULL, 10);
+	unsigned int  oport = strtoull(p_rexRes->field(3).c_str(), NULL, 10);
+
+	IBNode* p_node = getNodeByGuid(guid);
+        if (!p_node)
+        {
+           cout << "-E- Fail to find node with guid:"
+                << guid << endl;
+           anyErr++;
+        }
+	else
+	{
+	  for (int i=0;i<IB_NUM_SL;i++) {
+	    // Extract the VL value
+	    uint8_t vl = strtoull(p_rexRes->field(4+i).c_str(), NULL, 16);
+	    numVLs = numVLs > vl+1 ? numVLs : vl+1;
+	    // Set the table entry
+	    p_node->setSLVL(iport,oport,i,vl);
+	  }
+	}
+	delete p_rexRes;
+      }
+      /*else
+      {
+	cout << "-E- Wrong file format:" << fn.c_str() << endl;
+	anyErr++;
+	}*/
+   }
+   cout << "-I- Defined "<< (int)numVLs << " VLs in use" <<endl;
+
+   f.close();
+
+   return anyErr;
+}
+
 ///////////////////////////////////////////////////////////////////////////

 // Parse an OpenSM MCFDBs file and set the MFT table accordingly
diff --git a/ibdm/datamodel/Fabric.h b/ibdm/datamodel/Fabric.h
index 9e5a741..44fd8e4 100644
--- a/ibdm/datamodel/Fabric.h
+++ b/ibdm/datamodel/Fabric.h
@@ -64,8 +64,11 @@

 #define IB_LID_UNASSIGNED 0
 #define IB_LFT_UNASSIGNED 255
+#define IB_SLT_UNASSIGNED 255
 #define IB_HOP_UNASSIGNED 255

+#define IB_NUM_SL 16
+
 #if __WORDSIZE == 64
 #define PRIx64 "lx"
 #else
@@ -91,15 +94,18 @@ typedef vector<vec_int > vec_vec_int;
 typedef vector<uint8_t > vec_byte;
 typedef vector<uint32_t > vec_word;
 typedef vector<vec_byte > vec_vec_byte;
+typedef vector<vec_vec_byte > vec3_byte;

 typedef vector<class IBPort * > vec_pport;
 typedef vector<class IBNode * > vec_pnode;
+typedef vector<class VChannel * > vec_pvch;
 typedef map< string, class IBSysPort *, strless > map_str_psysport;
 typedef map< string, class IBNode *, strless > map_str_pnode;
 typedef map< string, class IBSystem *, strless > map_str_psys;
 typedef map< uint64_t, class IBPort *, less<uint64_t> > map_guid_pport;
 typedef map< uint64_t, class IBNode *, less<uint64_t> > map_guid_pnode;
 typedef map< uint64_t, class IBSystem *, less<uint64_t> > map_guid_psys;
+typedef map< string, int, strless > map_str_int;
 typedef list<class IBNode * > list_pnode;
 typedef list<class IBSystem * > list_psystem;
 typedef list<int > list_int;
@@ -121,6 +127,9 @@ typedef set< uint16_t, less< uint16_t > > set_uint16;
 #define FABU_LOG_VERBOSE 0x4
 #define IBNODE_UNASSIGNED_RANK 0xFF

+// DFS constants type
+typedef enum {Untouched,Open,Closed} dfs_t;
+
 //
 // GLOBALS
 //
@@ -198,6 +207,48 @@ static inline string guid2str(uint64_t guid) {
 };

 //
+// Virtual Channel class
+// Used for credit loops verification
+//
+
+class VChannel {
+  vec_pvch depend;               // Vector of dependencies
+  dfs_t flag;                    // DFS state
+ public:
+  // Constructor
+  VChannel() {
+    flag = Untouched;
+  };
+  //Getters/Setters
+  inline void setDependSize(int numDepend) {
+    if (depend.size() != (unsigned)numDepend) {
+      depend.resize(numDepend);
+      for (int i=0;i<numDepend;i++) {
+	depend[i] = NULL;
+      }
+    }
+  };
+  inline int getDependSize() {
+    return depend.size();
+  };
+  inline dfs_t getFlag() {
+    return flag;
+  };
+
+  inline void setFlag(dfs_t f) {
+    flag = f;
+  };
+
+  inline void setDependency(int i,VChannel* p) {
+    depend[i]=p;
+  };
+
+  inline VChannel* getDependency(int i) {
+    return depend[i];
+  };
+};
+
+//
 // IB Port class.
 // This is not the "End Node" but the physical port of
 // a node.
@@ -208,8 +259,9 @@ class IBPort {
   class IBPort    * p_remotePort; // Port connected on the other side of link
   class IBSysPort * p_sysPort;    // The system port (if any) connected to
   class IBNode    * p_node;       // The node the port is part of.
-  int			      num;            // Physical ports are identified by number.
-  unsigned int	   base_lid;       // The base lid assigned to the port.
+  vec_pvch        channels;       // Virtual channels associated with the port
+  int		  num;            // Physical ports are identified by number.
+  unsigned int	  base_lid;       // The base lid assigned to the port.
   IBLinkWidth     width;          // The link width of the port
   IBLinkSpeed     speed;          // The link speed of the port
   unsigned int    counter1;       // a generic value to be used by various algorithms
@@ -250,8 +302,8 @@ typedef union _PrivateAppData {
 class IBNode {
   uint64_t guid;
  public:
-  string			   name;         // Name of the node (instance name of the chip)
-  IBNodeType 		type;      // Either a CA or SW
+  string	  name;      // Name of the node (instance name of the chip)
+  IBNodeType 	  type;      // Either a CA or SW
   uint32_t        devId;     // The device ID of the node
   uint32_t        revId;     // The device revision Id.
   uint32_t        vendId;    // The device Vendor ID.
@@ -260,10 +312,12 @@ class IBNode {
   class IBFabric *p_fabric;  // What fabric we belong to.
   unsigned int	   numPorts;  // Number of physical ports
   string          attributes;// Comma-sep string of arbitrary attributes k=v
-  vec_pport		   Ports;     // Vector of all the ports
-  vec_vec_byte		MinHopsTable; // Table describing minimal hop count through
+  vec_pport	  Ports;     // Vector of all the ports
+  vec_vec_byte	  MinHopsTable; // Table describing minimal hop count through
                                 // each port to each target lid
   vec_byte        LFT;       // The LFT of this node (for switches only)
+  vec_byte        PSL;       // PSL table (CAxCA->SL mapping) of this node (for CAs only)
+  vec3_byte       SLVL;      // SL2VL table of this node (for switches only)
   vec_word        MFT;       // The Multicast forwarding table
   PrivateAppData  appData1;  // Application Private Data #1
   PrivateAppData  appData2;  // Application Private Data #2
@@ -316,6 +370,18 @@ class IBNode {
   // Get the LFT for a given lid
   int getLFTPortForLid (unsigned int lid);

+  // Set the PSL table
+  void setPSLForLid (unsigned int lid, unsigned int maxLid, uint8_t sl);
+
+  // Add entry to SL2VL table
+  void setSLVL(unsigned int iport,unsigned int oport,uint8_t sl, uint8_t vl);
+
+  // Get the PSL table for a given lid
+  uint8_t getPSLForLid(unsigned int lid);
+
+  // Get the SL2VL table entry
+  uint8_t getSLVL(unsigned int iport, unsigned int oport, uint8_t sl);
+
   // Set the Multicast FDB table
   void setMFTPortForMLid(unsigned int lid, unsigned int portNum);

@@ -423,6 +489,8 @@ class IBFabric {
   unsigned int   lmc;          // LMC value used
   uint8_t        defAllPorts;  // If not zero all ports (unconn) are declared
   uint8_t        subnCANames;  // The Subnet.lst has host names for CA's
+  uint8_t        numSLs;       // Number of used SLs
+  uint8_t        numVLs;       // Number of used VLs
   set_uint16     mcGroups;     // A set of all active multicast groups

   // Constructor
@@ -430,6 +498,8 @@ class IBFabric {
     maxLid = 0;
     defAllPorts = 1;
     subnCANames = 1;
+    numSLs = 1;
+    numVLs = 1;
     lmc = 0;
     minLid = 0;
     PortByLid.push_back(NULL); // make sure we always have one for LID=0
@@ -493,6 +563,12 @@ class IBFabric {
   // Parse OpenSM FDB dump file
   int parseFdbFile(string fn);

+  // Parse PSL mapping
+  int parsePSLFile(string fn);
+
+  // Parse SLVL mapping
+  int parseSLVLFile(string fn);
+
   // Parse an OpenSM MCFDBs file and set the MFT table accordingly
   int parseMCFdbFile(string fn);

@@ -513,6 +589,22 @@ class IBFabric {
 	 return (PortByLid[lid]);
   };

+  inline void setNumSLs(uint8_t nSL) {
+    numSLs=nSL;
+  };
+
+  inline uint8_t getNumSLs() {
+    return numSLs;
+  };
+
+  inline void setNumVLs(uint8_t nVL) {
+    numVLs=nVL;
+  };
+
+  inline uint8_t getNumVLs() {
+    return numVLs;
+  };
+
   // dump out the contents of the entire fabric
   void dump(ostream &sout);

diff --git a/ibdm/src/osm_check.cpp b/ibdm/src/osm_check.cpp
index e1e03e3..f1d2895 100644
--- a/ibdm/src/osm_check.cpp
+++ b/ibdm/src/osm_check.cpp
@@ -45,7 +45,7 @@ void
 show_usage() {
   cout << "Usage: there are two modes: Design/Verify" << endl;
   cout << "  Design: ibdmchk [-v][-h][-e][-u][-l <lmc>][-r <roots file>] -t <topology file> -n <SM Node> -p <SM Port>" << endl;
-  cout << "  Verify: ibdmchk [-v][-h][-l <lmc>][-r <roots file>] [-s <subnet file>] [-f <fdb file>] [-m <mcfdb file>]" << endl;
+  cout << "  Verify: ibdmchk [-v][-h][-l <lmc>][-r <roots file>] [-s <subnet file>] [-f <fdb file>] [-m <mcfdb file>] [-c <path-sl file>] [-d <sl2vl file>]\n\n" << endl;
 }

 void
@@ -72,7 +72,7 @@ show_help() {
     << "  -p|--port <SM Port> = the port number by which the SM nodes is attached to the fabric.\n"
     << "\n"
     << "  Options:\n"
-    << "  -v|--verbose = verbsoe mode\n"
+    << "  -v|--verbose = verbose mode\n"
     << "  -h|--help = provide this help message\n"
     << "  -l|--lmc <lmc> = LMC value > 0 means assigning 2^lmc lids to each port.\n"
     << "  -e|--enh = use enhanced routing algorithm when LMC > 0 and report the resulting paths\n"
@@ -82,11 +82,15 @@ show_help() {
     << "\n"
     << "  CLUSTER VERIFICATION:\n"
     << "  Usage:\n"
-    << "   ibdmchk [-v][-h][-r <roots file>] [-s <subnet file>] [-f <fdb file>] [-l <lmc>]\n\n"
+    << "   ibdmchk [-v][-h][-r <roots file>] [-s <subnet file>] [-f <fdb file>] [-m <mcfdb file>] [-l <lmc>] [-c <path-sl file>] [-d <sl2vl file>]\n\n"
     << "  Description:\n"
     << "   After the cluster is built and OpenSM is run (using flag -D 0x43) it reports the\n"
     << "   subnet and FDB tables into the files osm-subnet.lst, osm.fdbs and osm.fdbs in\n"
-	 << "   /var/log/ (or subnet.lst, osm.fdbs and osm.mcfdbs into /tmp in older versions).\n"
+    << "   /var/log/ (or subnet.lst, osm.fdbs and osm.mcfdbs into /tmp in older versions).\n"
+    << "   If more than one SL is known to be used additional file holding CAxCA->SL mapping \n"
+    << "   is generated (format: 0xsrc_guid dlid sl) . In this case the SL2VL mapping is \n"
+    << "   optionally supplied in an additional file (format: 0xsw_guid inport outport 0x(sl0)(sl1),\n"
+    << "   0x(sl2)(sl3),...). Without SL2VL mapping file an identity mapping is used.\n"
     << "   Based on these files the utility checks all CA to CA connectivity. Further analysis\n"
     << "   for credit deadlock potential is performed and reported. \n"
     << "   In case of an LMC > 0 it reports histograms for how many systems and nodes\n"
@@ -96,13 +100,15 @@ show_help() {
     << "  -l|--lmc <lmc> = The LMC value used while running OpenSM. Mandatory if not the default 0.\n"
     << "\n"
     << "  Options:\n"
-    << "  -v|--verbose = verbsoe mode\n"
+    << "  -v|--verbose = verbose mode\n"
     << "  -h|--help = provide this help message\n"
     << "  -s|--subnet <file> = OpenSM subnet.lst file (/var/log/osm-subnet.lst or /tmp/subnet.lst)\n"
     << "  -f|--fdb <file> = OpenSM dump of Ucast LFDB. Use -D 0x41 to generate it.\n"
     << "     (default is /var/log/osm.fdbs or /tmp/osm.fdbs).\n"
     << "  -m|--mcfdb <file> = OpenSM dump of Multicast LFDB. Use -D 0x41 to generate it.\n"
     << "     (default is /var/log/osm.mcfdbs or /tmp/osm.mcfdbs).\n"
+    << "  -c|--psl <file> = CAxCA->SL mapping. \n"
+    << "  -d|--slvl <file> = SL2VL mapping. \n"
     << "  -r|--roots <roots file> = a file holding all root nodes guids (one per line).\n"
     << "\n"
     << "Author: Eitan Zahavi, Mellanox Technologies LTD.\n"
@@ -189,6 +195,8 @@ int main (int argc, char **argv) {
   string mcFdbFile = string("");
   string TopoFile = string("");
   string SmNodeName = string("");
+  string PSLFile = string("");
+  string SLVLFile = string("");
   string RootsFileName = string("");
   int EnhancedRouting = 0;
   int lmc = 0;
@@ -197,11 +205,11 @@ int main (int argc, char **argv) {
   int AllPaths = 0;

   /*
-	* Parseing of Command Line
+	* Parsing of Command Line
 	*/

   char next_option;
-  const char * const short_option = "vhl:s:f:m:el:t:p:n:uar:";
+  const char * const short_option = "vhl:s:f:m:el:t:p:n:uar:c:d:";
   /*
 	 In the array below, the 2nd parameter specified the number
 	 of arguments as follows:
@@ -217,13 +225,15 @@ int main (int argc, char **argv) {
 		{	"subnet",	1,	NULL,	's'},
 		{	"fdb",	   1,	NULL,	'f'},
 		{	"mcfdb",	   1,	NULL,	'm'},
+		{       "psl",          1,      NULL,   'c'},
+		{       "slvl",         1,      NULL,   'd'},
 		{	"topology",	1,	NULL,	't'},
-      {  "node",     1, NULL, 'n'},
+		{  "node",     1, NULL, 'n'},
   		{	"port",	   1,	NULL,	'p'},
-      {  "enh",      0, NULL, 'e'},
-      {  "updn",     0, NULL, 'u'},
-      {  "roots",    1, NULL, 'r'},
-      {  "all",      0, NULL, 'a'},
+		{  "enh",      0, NULL, 'e'},
+		{  "updn",     0, NULL, 'u'},
+		{  "roots",    1, NULL, 'r'},
+		{  "all",      0, NULL, 'a'},
 		{	NULL,		0,	NULL,	 0 }	/* Required at the end of the array */
 	 };

@@ -274,6 +284,20 @@ int main (int argc, char **argv) {
 		subnetFile = string(optarg);
 		break;

+	 case 'c':
+	        /*
+		  Specifies CAxCA->SL
+		*/
+	        PSLFile = string(optarg);
+	        break;
+
+	 case 'd':
+	        /*
+		  Specifies SL->VL
+		*/
+	        SLVLFile = string(optarg);
+	        break;
+
 	 case 't':
 		/*
 		  Specifies Topology
@@ -342,6 +366,7 @@ int main (int argc, char **argv) {
     printf(" SM Node ........ %s\n", SmNodeName.c_str());
     printf(" SM Port ........ %u\n", SmPortNum);
     printf(" LMC ............ %u\n", lmc);
+
     if (EnhancedRouting && lmc > 0)
       printf(" Using Enhanced Routing\n");
     if (RootsFileName.size())
@@ -352,75 +377,74 @@ int main (int argc, char **argv) {
       exit(1);
     }

-	// get the SM Port
-	IBNode *p_smNode = fabric.getNode(SmNodeName);
-	if (! p_smNode ) {
-	  cout << "-E- Fail to find SM node:" << SmNodeName << endl;
-	  exit(1);
-	}
+    // get the SM Port
+    IBNode *p_smNode = fabric.getNode(SmNodeName);
+    if (! p_smNode ) {
+      cout << "-E- Fail to find SM node:" << SmNodeName << endl;
+      exit(1);
+    }

-	IBPort *p_smPort = p_smNode->getPort(SmPortNum);
-	if (! p_smPort) {
-	  cout <<  "-E- Fail to find SM Port: " << SmNodeName
-			 << "/" << SmPortNum << endl;
-	  exit(1);
+    IBPort *p_smPort = p_smNode->getPort(SmPortNum);
+    if (! p_smPort) {
+      cout <<  "-E- Fail to find SM Port: " << SmNodeName
+	   << "/" << SmPortNum << endl;
+      exit(1);
+    }
+
+    // assign lids
+    if (SubnMgtAssignLids(p_smPort,lmc)) {
+      cout << "-E- Fail to assign LIDs." << endl;
+      exit(1);
+    }
+
+    // we need to run min hop calculation anyway
+    if (SubnMgtCalcMinHopTables(&fabric)) {
+      cout << "-E- Fail to update Min Hops Tables." << endl;
+      exit(1);
+    }
+
+    if (UseUpDown) {
+      list <IBNode *> rootNodes;
+      if (RootsFileName.size()) {
+	rootNodes = ParseRootNodeNamesFile(&fabric, RootsFileName);
+      }
+      else {
+	rootNodes = SubnMgtFindRootNodesByMinHop(&fabric);
+      }
+
+      if (!rootNodes.empty()) {
+	cout << "-I- Recognized " << rootNodes.size() << " root nodes:" << endl;
+	for (list <IBNode *>::iterator nI = rootNodes.begin();
+	     nI != rootNodes.end(); nI++) {
+	  cout << " " << (*nI)->name << endl;
 	}
+	cout << "---------------------------------------------------------------------------\n" << endl;

-	// assign lids
-	if (SubnMgtAssignLids(p_smPort,lmc)) {
-	  cout << "-E- Fail to assign LIDs." << endl;
+	map_pnode_int nodesRank;
+	SubnRankFabricNodesByRootNodes(&fabric, rootNodes, nodesRank);
+
+	if (SubnMgtCalcUpDnMinHopTbls(&fabric, nodesRank)) {
+	  cout << "-E- Fail to update Min Hops Tables." << endl;
 	  exit(1);
 	}
+      } else {
+	cout << "-E- Fail to recognize any root nodes. Up/Down is not active!" << endl;
+      }
+    }
+
+    if (!EnhancedRouting) {
+
+      if (SubnMgtOsmRoute(&fabric)) {
+	cout << "-E- Fail to update LFT Tables." << endl;
+	exit(1);
+      }
+    } else {
+      if (SubnMgtOsmEnhancedRoute(&fabric)) {
+	cout << "-E- Fail to update LFT Tables." << endl;
+	exit(1);
+      }
+    }

-   // we need to run min hop calculation anyway
-   if (SubnMgtCalcMinHopTables(&fabric)) {
-     cout << "-E- Fail to update Min Hops Tables." << endl;
-     exit(1);
-   }
-
-   if (UseUpDown) {
-     list <IBNode *> rootNodes;
-     if (RootsFileName.size())
-     {
-       rootNodes = ParseRootNodeNamesFile(&fabric, RootsFileName);
-     }
-     else
-     {
-       rootNodes = SubnMgtFindRootNodesByMinHop(&fabric);
-     }
-
-     if (!rootNodes.empty()) {
-       cout << "-I- Recognized " << rootNodes.size() << " root nodes:" << endl;
-       for (list <IBNode *>::iterator nI = rootNodes.begin();
-            nI != rootNodes.end(); nI++) {
-         cout << " " << (*nI)->name << endl;
-       }
-       cout << "---------------------------------------------------------------------------\n" << endl;
-
-       map_pnode_int nodesRank;
-       SubnRankFabricNodesByRootNodes(&fabric, rootNodes, nodesRank);
-
-       if (SubnMgtCalcUpDnMinHopTbls(&fabric, nodesRank)) {
-         cout << "-E- Fail to update Min Hops Tables." << endl;
-         exit(1);
-       }
-     } else {
-       cout << "-E- Fail to recognize any root nodes. Up/Down is not active!" << endl;
-     }
-   }
-
-	if (!EnhancedRouting) {
-
-	  if (SubnMgtOsmRoute(&fabric)) {
-		 cout << "-E- Fail to update LFT Tables." << endl;
-		 exit(1);
-	  }
-	} else {
-	  if (SubnMgtOsmEnhancedRoute(&fabric)) {
-		 cout << "-E- Fail to update LFT Tables." << endl;
-		 exit(1);
-	  }
-	}

   } else {
 	  int anyMissingFile = 0;
@@ -463,6 +487,14 @@ int main (int argc, char **argv) {
     printf(" FDB File = %s\n", fdbFile.c_str());
     printf(" MCFDB File = %s\n", mcFdbFile.c_str());
     printf(" Subnet File = %s\n", subnetFile.c_str());
+    if (PSLFile.size() >0)
+      printf(" SL File = %s\n", PSLFile.c_str());
+    else
+      printf(" SL File = NONE, using single SL\n");
+    if (SLVLFile.size() >0)
+      printf(" SLVL File = %s\n", SLVLFile.c_str());
+    else
+      printf(" SLVL File = NONE, using identity mapping\n");
     printf(" LMC = %u\n", lmc);
     printf("-------------------------------------------------\n");

@@ -478,6 +510,18 @@ int main (int argc, char **argv) {
       exit(1);
     }

+    if (PSLFile.size() && fabric.parsePSLFile(PSLFile)) {
+      cout << "-E- Fail to parse SL file:" << PSLFile << endl;
+      exit(1);
+    }
+
+    fabric.setNumVLs(fabric.getNumSLs());
+
+    if (SLVLFile.size() && fabric.parseSLVLFile(SLVLFile)) {
+      cout << "-E- Fail to parse SL file:" << SLVLFile << endl;
+      exit(1);
+    }
+
     if (fabric.parseMCFdbFile(mcFdbFile)) {
       cout << "-E- Fail to parse multicast fdb file:" << mcFdbFile << endl;
       exit(1);
@@ -509,20 +553,20 @@ int main (int argc, char **argv) {
   int anyErr = 0;

   if (RootsFileName.size())
-  {
-    if (TopoFile.size())
     {
-      rootNodes = ParseRootNodeNamesFile(&fabric, RootsFileName);
+      if (TopoFile.size())
+	{
+	  rootNodes = ParseRootNodeNamesFile(&fabric, RootsFileName);
+	}
+      else
+	{
+	  rootNodes = ParseRootNodeGuidsFile(&fabric, RootsFileName);
+	}
     }
-    else
+  else
     {
-      rootNodes = ParseRootNodeGuidsFile(&fabric, RootsFileName);
+      rootNodes = SubnMgtFindRootNodesByMinHop(&fabric); //(Causes segmentation fault with DOR)
     }
-  }
-  else
-  {
-    rootNodes = SubnMgtFindRootNodesByMinHop(&fabric);
-  }

   if (!rootNodes.empty()) {
     cout << "-I- Recognized " << rootNodes.size() << " root nodes:" << endl;
-- 
1.5.1.4






More information about the general mailing list