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

TraceRoute.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$
 */

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

// Trace a direct route from the given SM node port
int TraceDRPathRoute (IBPort *p_smNodePort, list_int drPathPortNums) {
  IBPort *p_port = p_smNodePort;
  IBNode *p_node;
  IBPort *p_remPort;
  IBNode *p_remNode;
  IBPort *p_nextPort;
  unsigned int outPortNum;
  unsigned int hop = 0;
  list_int::iterator pI = drPathPortNums.begin();

  // check we haev at least two hops:
  if (drPathPortNums.size() < 2) {
       cout << "-E- We expect at least 2 hops to get out of the SM Node! (got:"
                  << drPathPortNums.size() << ")" << endl;
       return(1);
  }

  // we require it to start with zero - marking the internal hop

  if (*pI != 0) {
       cout << "-E- Direct Route Ports list must start with a zero !" << endl;
       return(1);
  }

  // The second port in the we require it to start with zero - marking the internal hop
  pI++;
  if (*pI != p_port->num) {
       cout << "-E- Direct Route Ports second hop must match the SM port number !"
                  << " (got:" << *pI << ")" << endl;
       return(1);
  }

  // we are at the port of the SM node so we are at hop 1.
  hop = 1;
  pI++; // points to next hop in the list

  // we traverse to null port or max number of hops reached.
  while (p_port && (hop < drPathPortNums.size())) {
            // get the node
            p_node = p_port->p_node;

            if (p_port->p_sysPort) {
              // is external port:
              cout << "[" << setw(3) <<hop << "] FROM Host:" << p_node->p_system->name.c_str()
                         << " Plug:" << p_port->p_sysPort->name.c_str() << endl;
              cout << "           Node:"  << p_node->name.c_str() << " Port:" << p_port->num << endl;
            } else {
              // internal so provide only internal data:
              cout << "[" << setw(3) << hop << "] FROM Node:"  << p_node->name.c_str() << " Port:"
                         << p_port->num << endl;
            }

            // we calc next step port:
            p_nextPort = NULL;

            // start going to the other side:
            p_remPort = p_port->p_remotePort;
            if (p_remPort != NULL) {
              p_remNode = p_remPort->p_node;

              // The to section:
              if (p_remPort->p_sysPort) {
                   // is external port:
                   cout << "      TO   Host:" << p_remNode->p_system->name.c_str()
                              << " Plug:" << p_remPort->p_sysPort->name.c_str() << endl;
                   cout << "           Node:"  << p_remNode->name.c_str() << " Port:" << p_remPort->num << endl;
              } else {
                   // internal so provide only internal data:
                   cout << "      TO   Node:"  << p_remNode->name.c_str() << " Port:" << p_remPort->num << endl;
              }

              if (pI != drPathPortNums.end()) {
                   // calc the next port
                   outPortNum = *pI - 1;
                   // we could get stuck on bad port num
                   if (outPortNum > p_remNode->numPorts || outPortNum < 0) {
                        cout << "-E- Bad port number:" << outPortNum << " hop:" << hop << endl;
                        return 1;
                   }

                   // port not connected
                   if (p_remNode->Ports[outPortNum] == NULL) {
                        cout << "[" << setw(3) << hop << "] Broken Route: not connected port:" << outPortNum << endl;
                        return 1;
                   }

                   p_nextPort = p_remNode->Ports[outPortNum];
              }

              pI++;
              hop++;
            }
            p_port = p_nextPort;
  }

  return 0;
}

typedef set< IBNode *, less< IBNode * > > set_p_node;

// Trace the path between the lids based on min hop count only
int
TraceRouteByMinHops (IBFabric *p_fabric,
                                          unsigned int slid , unsigned int dlid) {
  IBPort *p_port = p_fabric->getPortByLid(slid), *p_remPort, *p_nextPort;
  IBNode *p_node, *p_remNode;
  unsigned int hop = 0;
  set_p_node visitedNodes;

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

  // find the physical port we out from:
  p_port = p_port->p_node->getFirstMinHopPort(dlid);
  if (!p_port) {
    cout << "-E- Fail to obtain minhop port for switch:" << slid << endl;
    return(1);
  }

  cout << "--------------------------- TRACE PATH BY MIN HOPS -------------------------" << endl;
  cout << "-I- Tracing by Min Hops from lid:" << slid
             << " to lid:" << dlid << endl;
  // we traverse to target dlid
  while (p_port) {
            // get the node
            p_node = p_port->p_node;

            if (p_port->p_sysPort) {
              // is external port:
              cout << "[" << setw(3) << hop << "] FROM Host:" << p_node->p_system->name.c_str()
                         << " Plug:" << p_port->p_sysPort->name.c_str() << endl;
              cout << "           Node:"  << p_node->name.c_str() << " Port:" << p_port->num << endl;
            } else {
              // internal so provide only internal data:
              cout << "[" << setw(3) << hop << "] FROM Node:"  << p_node->name.c_str() << " Port:"
                         << p_port->num << endl;
            }

            // we calc next step port:
            p_nextPort = NULL;

            // start going to the other side:
            p_remPort = p_port->p_remotePort;
            if (p_remPort != NULL) {
              p_remNode = p_remPort->p_node;

        // did we already visit this node?
        set_p_node::iterator sI = visitedNodes.find(p_remNode);
        if (sI != visitedNodes.end()) {
          cout << "-E- Run into loop in min hop path at node:" << p_remNode->name << endl;
          return 1;
        }
        visitedNodes.insert(p_remNode);

              // The to section:
              if (p_remPort->p_sysPort) {
                   // is external port:
                   cout << "      TO   Host:" << p_remNode->p_system->name.c_str()
                              << " Plug:" << p_remPort->p_sysPort->name.c_str() << endl;
                   cout << "           Node:"  << p_remNode->name.c_str() << " Port:" << p_remPort->num << endl;
              } else {
                   // internal so provide only internal data:
                   cout << "      TO   Node:"  << p_remNode->name.c_str() << " Port:" << p_remPort->num << endl;
              }

              // we need next port only if we are on a switch:
              if (p_remNode->type == IB_SW_NODE) {
                   p_nextPort = p_remNode->getFirstMinHopPort(dlid);
              }
              hop++;
            }
            p_port = p_nextPort;
  }
  cout << "---------------------------------------------------------------------------\n" << endl;
  return 0;
}

// Trace a route from slid to dlid by LFT
int TraceRouteByLFT (
  IBFabric *p_fabric,
  unsigned int sLid , unsigned int dLid,
  unsigned int *hops,
  list_pnode *p_nodesList) {

  IBPort *p_port = p_fabric->getPortByLid(sLid);
  IBNode *p_node;
  IBPort *p_remotePort;
  unsigned int lidStep = 1 << p_fabric->lmc;
  int hopCnt = 0;

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

  if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE) {
       cout << "--------------------------- TRACE PATH BY FDB -----------------------------" << endl;
       cout << "-V- Tracing from lid:" << sLid << " to lid:"
                  << dLid << endl;
  }

  if (hops) *hops = 0;

  // 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;
       }
       p_node = p_port->p_remotePort->p_node;
       if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
            cout << "-V- Arrived at Node:" << p_node->name
                    << " Port:" << p_port->p_remotePort->num << endl;
  } else {
       // it is a switch :
       p_node = p_port->p_node;
  }


  // 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;
  }

  // traverse:
  int done = 0;
  while (!done) {
       // insert the node pointer to the list
       if (p_nodesList) {
            p_nodesList->push_back(p_node);
       }

       // calc next node:
       int pn = p_node->getLFTPortForLid(dLid);
       if (pn == IB_LFT_UNASSIGNED) {
            cout << "-E- Unassigned LFT for lid:" << dLid << " Dead end at:" << p_node->name << endl;
            return 1;
       }

    // if the port number is 0 we must have reached the target
    if (pn == 0)
    {
      uint16_t base_lid = 0;
      // get lid of any port of this node
      for (unsigned int portNum = 0;
           (base_lid == 0) && (portNum <= p_node->numPorts); portNum++)
      {
        IBPort *p_port = p_node->getPort(portNum);
        if (p_port) base_lid = p_port->base_lid;
      }
      if (base_lid == 0) {
        cout << "-E- Fail to find node:" << p_node->name
             << " base lid?" << endl;
        return 1;
      }

      if ((base_lid > dLid) || (base_lid + lidStep - 1 < dLid)) {
        cout << "-E- Dead end at port 0 of node:" << p_node->name << endl;
        return 1;
      }

      return 0;
    }

       // get the port on the other side
       p_port = p_node->getPort(pn);
       if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
            cout << "-V- Going out on port:" << pn << endl;

       if (! (p_port &&
                    p_port->p_remotePort &&
                    p_port->p_remotePort->p_node)) {
            cout << "-E- Dead end at:" << p_node->name << endl;
            return 1;
       }

       if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
            cout << "-V- Arrived at Node:" << p_port->p_remotePort->p_node->name
                    << " Port:" << p_port->p_remotePort->num << endl;

       p_remotePort = p_port->p_remotePort;
       // check if we are done:
       done = ((p_remotePort->base_lid <= dLid) &&
                        (p_remotePort->base_lid+lidStep - 1 >= dLid));

       p_node = p_remotePort->p_node;
       if (hops) (*hops)++;
       if (hopCnt++ > 256) {
            cout << "-E- Aborting after 256 hops - loop in LFT?" << endl;
            return 1;
       }
  }

  if (FabricUtilsVerboseLevel & FABU_LOG_VERBOSE)
       cout << "---------------------------------------------------------------------------\n" << endl;

  return 0;
}


Generated by  Doxygen 1.6.0   Back to index