~ubuntu-branches/ubuntu/utopic/ibutils/utopic-proposed

« back to all changes in this revision

Viewing changes to ibdm/ibdm/CredLoops.cpp

  • Committer: Package Import Robot
  • Author(s): Ana Beatriz Guerrero Lopez
  • Date: 2014-07-04 11:26:44 UTC
  • mfrom: (5.1.3 experimental)
  • Revision ID: package-import@ubuntu.com-20140704112644-en6fo4oq2wrio7a3
Tags: 1.5.7-3
* Upload to unstable.
* Add a watch file.
* Add fields Vcs-Browser/Vcs-Git.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 2004 Mellanox Technologies LTD. All rights reserved.
 
2
 * Copyright (c) 2004-2010 Mellanox Technologies LTD. All rights reserved.
3
3
 *
4
4
 * This software is available to you under a choice of one of two
5
5
 * licenses.  You may choose to be licensed under the terms of the GNU
29
29
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
30
 * SOFTWARE.
31
31
 *
32
 
 * $Id$
33
32
 */
34
33
 
35
34
#include "Fabric.h"
45
44
 * fabric
46
45
 *
47
46
 */
48
 
 
49
 
//////////////////////////////////////////////////////////////////////////////
50
 
 
 
47
//////////////////////////////////////////////////////////////////////////////
 
48
//
 
49
// |------|  p1=p_port            |------| p2=p_portNext
 
50
// |      |                       |      |
 
51
// |    p1|>--------------------->|    p2|----------------
 
52
// |      |  \   channels         |      |   \   channels
 
53
// |------|   \--|=====|          |------|    \--|=====|
 
54
//               | VL0 |-|      next chan        | VL0 |
 
55
//               |-----| |     |========|        |-----|
 
56
//               | VL1 |  \    | P0-VL0 |   ---->| VL1 |
 
57
//               |-----|   \   |--------|  /     |-----|
 
58
//               | ... |    \->| P0-VL1 |-/      | ... |
 
59
//               |=====|  sl2vl|--------|        |=====|
 
60
//                             | P0-... |
 
61
//                             |========|
 
62
//                             | P1-VL0 |
 
63
//                             |--------|
 
64
//                             | P1-VL1 |
 
65
//                             |--------|
 
66
//                             | P1-... |
 
67
//                             |========|
 
68
//                             | ...... |
 
69
//                             |========|
 
70
//                             | Pn-VL0 |
 
71
//                             |========|
 
72
//
 
73
//////////////////////////////////////////////////////////////////////////////
 
74
using namespace std;
 
75
 
 
76
 
 
77
//////////////////////////////////////////////////////////////////////////////
 
78
// We keep global flags to control how the check is being done:
 
79
 
 
80
// If non zero will consider all switch to switch paths too
 
81
static int CrdLoopIncludeUcastSwitchPaths = 0;
 
82
 
 
83
// If non zero consider multicast paths too
 
84
static int CrdLoopIncludeMcastPaths = 0;
 
85
 
 
86
// Map each MLID to a list of SL's that may be used for this MGRP traffic
 
87
// If no entry is set then we will assume all traffic on SL=0
 
88
#define map_mlid_sl_list  map<int, list< int >, less<int> >
 
89
static map_mlid_sl_list mlidSLs;
 
90
 
 
91
 
 
92
//////////////////////////////////////////////////////////////////////////////
51
93
// Apply DFS on a dependency graph
52
 
 
53
 
int CrdLoopDFS(VChannel* ch) {
54
 
  // Already been there
55
 
  if (ch->getFlag() == Closed)
 
94
int CrdLoopDFS(VChannel* ch)
 
95
{
 
96
    // Already been there
 
97
    if (ch->getFlag() == Closed)
 
98
        return 0;
 
99
    // Credit loop
 
100
    if (ch->getFlag() == Open) {
 
101
        cout << "Found credit loop on: " << ch->pPort->getName()
 
102
                 << " VL: " << ch->vl << endl;
 
103
        return 1;
 
104
    }
 
105
    // Mark as open
 
106
    ch->setFlag(Open);
 
107
    // Make recursive steps
 
108
    for (int i=0; i<ch->getDependSize();i++) {
 
109
        VChannel* next = ch->getDependency(i);
 
110
        if (next) {
 
111
            if (CrdLoopDFS(next)) {
 
112
                cout << "  - BT credit loop through: " << ch->pPort->getName()
 
113
                     << " VL: " << ch->vl << endl;
 
114
                return 1;
 
115
            }
 
116
        }
 
117
    }
 
118
    // Mark as closed
 
119
    ch->setFlag(Closed);
56
120
    return 0;
57
 
  // Credit loop
58
 
  if (ch->getFlag() == Open) {
59
 
    return 1;
60
 
  }
61
 
  // Mark as open
62
 
  ch->setFlag(Open);
63
 
  // Make recursive steps
64
 
  for (int i=0; i<ch->getDependSize();i++) {
65
 
    VChannel* next = ch->getDependency(i);
66
 
    if (next) {
67
 
      if (CrdLoopDFS(next))
68
 
        return 1;
69
 
    }
70
 
  }
71
 
  // Mark as closed
72
 
  ch->setFlag(Closed);
73
 
  return 0;
74
121
}
75
122
 
 
123
 
76
124
//////////////////////////////////////////////////////////////////////////////
77
 
 
78
125
// Go over CA's apply DFS on the dependency graphs starting from CA's port
79
 
 
80
 
int CrdLoopFindLoops(IBFabric* p_fabric) {
81
 
  unsigned int lidStep = 1 << p_fabric->lmc;
82
 
 
83
 
  // go over all CA ports in the fabric
84
 
  for (int i = p_fabric->minLid; i <= p_fabric->maxLid; i += lidStep) {
85
 
         IBPort *p_Port = p_fabric->PortByLid[i];
86
 
         if (!p_Port || (p_Port->p_node->type == IB_SW_NODE)) continue;
87
 
         // Go over all CA's channels and find untouched one
88
 
         for (int j=0;j < p_fabric->getNumSLs(); j++) {
89
 
           dfs_t state = p_Port->channels[j]->getFlag();
90
 
           if (state == Open) {
91
 
             cout << "-E- open channel outside of DFS" << endl;
92
 
             return 1;
93
 
           }
94
 
           // Already processed, continue
95
 
           if (state == Closed)
96
 
             continue;
97
 
           // Found starting point
98
 
           if (CrdLoopDFS(p_Port->channels[j]))
99
 
             return 1;
100
 
         }
101
 
  }
102
 
  return 0;
 
126
int CrdLoopFindLoops(IBFabric* p_fabric)
 
127
{
 
128
    unsigned int lidStep = 1 << p_fabric->lmc;
 
129
 
 
130
    // go over all CA ports in the fabric
 
131
    for (int i = p_fabric->minLid; i <= p_fabric->maxLid; i += lidStep) {
 
132
        IBPort *p_Port = p_fabric->PortByLid[i];
 
133
        if (!p_Port || (p_Port->p_node->type == IB_SW_NODE)) continue;
 
134
        // Go over all CA's channels and find untouched one
 
135
        for (int j=0;j < p_fabric->getNumSLs(); j++) {
 
136
            dfs_t state = p_Port->channels[j]->getFlag();
 
137
            if (state == Open) {
 
138
                cout << "-E- open channel outside of DFS" << endl;
 
139
                return 1;
 
140
            }
 
141
            // Already processed, continue
 
142
            if (state == Closed)
 
143
                continue;
 
144
            // Found starting point
 
145
            if (CrdLoopDFS(p_Port->channels[j]))
 
146
                return 1;
 
147
        }
 
148
    }
 
149
    return 0;
103
150
}
104
151
 
105
152
 
106
153
//////////////////////////////////////////////////////////////////////////////
107
 
 
108
154
// Trace a route from slid to dlid by LFT
109
155
// Add dependency edges
110
 
int CrdLoopMarkRouteByLFT (
111
 
  IBFabric *p_fabric,
112
 
  unsigned int sLid , unsigned int dLid
113
 
  ) {
114
 
 
115
 
  IBPort *p_port = p_fabric->getPortByLid(sLid);
116
 
  IBNode *p_node;
117
 
  IBPort *p_portNext;
118
 
  unsigned int lidStep = 1 << p_fabric->lmc;
119
 
  int outPortNum = 0, inputPortNum = 0, hopCnt = 0;
120
 
  bool done;
121
 
 
122
 
  // make sure:
123
 
  if (!p_port) {
124
 
         cout << "-E- Provided source:" << sLid
125
 
                        << " lid is not mapped to a port!" << endl;
126
 
         return(1);
127
 
  }
128
 
 
129
 
  // Retrieve the relevant SL
130
 
  uint8_t SL, VL;
131
 
  SL = VL = p_port->p_node->getPSLForLid(dLid);
132
 
 
133
 
  if (!p_port->p_remotePort) {
134
 
    cout << "-E- Provided starting point is not connected !"
135
 
         << "lid:" << sLid << endl;
136
 
    return 1;
137
 
  }
138
 
 
139
 
  if (SL == IB_SLT_UNASSIGNED) {
140
 
    cout << "-E- SL to destination is unassigned !"
141
 
         << "slid: " << sLid << "dlid:" << dLid << endl;
142
 
    return 1;
143
 
  }
144
 
 
145
 
  // check if we are done:
146
 
  done = ((p_port->p_remotePort->base_lid <= dLid) &&
147
 
          (p_port->p_remotePort->base_lid+lidStep - 1 >= dLid));
148
 
  while (!done) {
149
 
    // Get the node on the remote side
150
 
    p_node = p_port->p_remotePort->p_node;
151
 
    // Get remote port's number
152
 
    inputPortNum = p_port->p_remotePort->num;
153
 
    // Get number of ports on the remote side
154
 
    int numPorts = p_node->numPorts;
155
 
    // Init vchannel's number of possible dependencies
156
 
    p_port->channels[VL]->setDependSize((numPorts+1)*p_fabric->getNumVLs());
157
 
 
158
 
    // Get port num of the next hop
159
 
    outPortNum = p_node->getLFTPortForLid(dLid);
160
 
    // Get VL of the next hop
161
 
    int nextVL = p_node->getSLVL(inputPortNum,outPortNum,SL);
162
 
 
163
 
    if (outPortNum == IB_LFT_UNASSIGNED) {
164
 
      cout << "-E- Unassigned LFT for lid:" << dLid << " Dead end at:" << p_node->name << endl;
165
 
      return 1;
166
 
    }
167
 
 
168
 
    if (nextVL == IB_SLT_UNASSIGNED) {
169
 
      cout << "-E- Unassigned SL2VL entry, iport: "<< inputPortNum<<", oport:"<<outPortNum<<", SL:"<<(int)SL<< endl;
170
 
      return 1;
171
 
    }
172
 
 
173
 
      // get the next port on the other side
174
 
    p_portNext = p_node->getPort(outPortNum);
175
 
 
176
 
    if (! (p_portNext &&
177
 
           p_portNext->p_remotePort &&
178
 
           p_portNext->p_remotePort->p_node)) {
179
 
      cout << "-E- Dead end at:" << p_node->name << endl;
180
 
      return 1;
181
 
    }
182
 
    // Now add an edge
183
 
    p_port->channels[VL]->setDependency(outPortNum*p_fabric->getNumVLs()+nextVL,p_portNext->channels[nextVL]);
184
 
    // Advance
185
 
    p_port = p_portNext;
186
 
    VL = nextVL;
187
 
    if (hopCnt++ > 256) {
188
 
      cout << "-E- Aborting after 256 hops - loop in LFT?" << endl;
189
 
      return 1;
190
 
    }
191
 
    //Check if done
 
156
int CrdLoopMarkRouteByLFT(IBFabric *p_fabric,
 
157
        unsigned int sLid , unsigned int dLid)
 
158
{
 
159
    IBPort *p_port = p_fabric->getPortByLid(sLid);
 
160
    IBNode *p_node;
 
161
    IBPort *p_portNext;
 
162
    unsigned int lidStep = 1 << p_fabric->lmc;
 
163
    int outPortNum = 0, inputPortNum = 0, hopCnt = 0;
 
164
    bool done;
 
165
 
 
166
    // make sure:
 
167
    if (!p_port) {
 
168
        cout << "-E- Provided source:" << sLid
 
169
                << " lid is not mapped to a port!" << endl;
 
170
        return(1);
 
171
    }
 
172
 
 
173
    // If started on a switch, need to use the correct output
 
174
    // port, not the first one found by getPortByLid
 
175
    if (p_port->p_node->type == IB_SW_NODE) {
 
176
        int outPortNum = p_port->p_node->getLFTPortForLid(dLid);
 
177
        if (outPortNum == IB_LFT_UNASSIGNED) {
 
178
            cout << "-E- Unassigned LFT for lid:" << dLid
 
179
                    << " Dead end at:" << p_port->p_node->name << endl;
 
180
            return 1;
 
181
        }
 
182
        p_port = p_port->p_node->getPort(outPortNum);
 
183
    }
 
184
 
 
185
    // Retrieve the relevant SL
 
186
    uint8_t SL, VL;
 
187
    SL = VL = p_port->p_node->getPSLForLid(dLid);
 
188
 
 
189
    if (!p_port->p_remotePort) {
 
190
        cout << "-E- Provided starting point is not connected !"
 
191
                << "lid:" << sLid << endl;
 
192
        return 1;
 
193
    }
 
194
 
 
195
    if (SL == IB_SLT_UNASSIGNED) {
 
196
        cout << "-E- SL to destination is unassigned !"
 
197
                << "slid: " << sLid << "dlid:" << dLid << endl;
 
198
        return 1;
 
199
    }
 
200
 
 
201
    // check if we are done:
192
202
    done = ((p_port->p_remotePort->base_lid <= dLid) &&
193
 
            (p_port->p_remotePort->base_lid+lidStep - 1 >= dLid));
194
 
  }
195
 
 
196
 
  return 0;
 
203
            (p_port->p_remotePort->base_lid+lidStep - 1 >= dLid));
 
204
    while (!done) {
 
205
        // Get the node on the remote side
 
206
        p_node = p_port->p_remotePort->p_node;
 
207
        // Get remote port's number
 
208
        inputPortNum = p_port->p_remotePort->num;
 
209
        // Get number of ports on the remote side
 
210
        int numPorts = p_node->numPorts;
 
211
        // Init vchannel's number of possible dependencies
 
212
        p_port->channels[VL]->setDependSize((numPorts+1)*p_fabric->getNumVLs());
 
213
 
 
214
        // Get port num of the next hop
 
215
        outPortNum = p_node->getLFTPortForLid(dLid);
 
216
        // Get VL of the next hop
 
217
        int nextVL = p_node->getSLVL(inputPortNum,outPortNum,SL);
 
218
 
 
219
        if (outPortNum == IB_LFT_UNASSIGNED) {
 
220
            cout << "-E- Unassigned LFT for lid:" << dLid << " Dead end at:" << p_node->name << endl;
 
221
            return 1;
 
222
        }
 
223
 
 
224
        if (nextVL == IB_SLT_UNASSIGNED) {
 
225
            cout << "-E- Unassigned SL2VL entry, iport: "<< inputPortNum<<", oport:"<<outPortNum<<", SL:"<<(int)SL<< endl;
 
226
            return 1;
 
227
        }
 
228
 
 
229
        // get the next port on the other side
 
230
        p_portNext = p_node->getPort(outPortNum);
 
231
 
 
232
        if (! (p_portNext &&
 
233
                p_portNext->p_remotePort &&
 
234
                p_portNext->p_remotePort->p_node)) {
 
235
            cout << "-E- Dead end at:" << p_node->name << endl;
 
236
            return 1;
 
237
        }
 
238
        // Now add an edge
 
239
        p_port->channels[VL]->setDependency(
 
240
                outPortNum*p_fabric->getNumVLs()+nextVL,p_portNext->channels[nextVL]);
 
241
        // Advance
 
242
        p_port = p_portNext;
 
243
        VL = nextVL;
 
244
        if (hopCnt++ > 256) {
 
245
            cout << "-E- Aborting after 256 hops - loop in LFT?" << endl;
 
246
            return 1;
 
247
        }
 
248
        //Check if done
 
249
        done = ((p_port->p_remotePort->base_lid <= dLid) &&
 
250
                (p_port->p_remotePort->base_lid+lidStep - 1 >= dLid));
 
251
    }
 
252
    return 0;
197
253
}
198
254
 
 
255
 
199
256
/////////////////////////////////////////////////////////////////////////////
200
 
 
201
257
// Go over all CA to CA paths and connect dependant vchannel by an edge
202
 
 
203
 
int
204
 
CrdLoopConnectDepend(IBFabric* p_fabric)
205
 
{
206
 
  unsigned int lidStep = 1 << p_fabric->lmc;
207
 
  int anyError = 0;
208
 
  unsigned int i,j;
209
 
 
210
 
  // go over all ports in the fabric
211
 
  for ( i = p_fabric->minLid; i <= p_fabric->maxLid; i += lidStep) {
212
 
         IBPort *p_srcPort = p_fabric->PortByLid[i];
213
 
 
214
 
         if (!p_srcPort || (p_srcPort->p_node->type == IB_SW_NODE)) continue;
215
 
 
216
 
         unsigned int sLid = p_srcPort->base_lid;
217
 
 
218
 
         // go over all the rest of the ports:
219
 
         for ( j = p_fabric->minLid; j <= p_fabric->maxLid; j += lidStep ) {
220
 
                IBPort *p_dstPort = p_fabric->PortByLid[j];
221
 
 
222
 
                // Avoid tracing to itself
223
 
                if (i == j) continue;
224
 
 
225
 
                if (! p_dstPort) continue;
226
 
 
227
 
                if (p_dstPort->p_node->type == IB_SW_NODE) continue;
228
 
                unsigned int dLid = p_dstPort->base_lid;
229
 
                // go over all LMC combinations:
230
 
                for (unsigned int l1 = 0; l1 < lidStep; l1++) {
231
 
                  for (unsigned int l2 = 0; l2 < lidStep; l2++) {
232
 
                    // Trace the path but record the input to output ports used.
233
 
                    if (CrdLoopMarkRouteByLFT(p_fabric, sLid + l1, dLid + l2)) {
234
 
                      cout << "-E- Fail to find a path from:"
235
 
                           << p_srcPort->p_node->name << "/" << p_srcPort->num
236
 
                           << " to:" << p_dstPort->p_node->name << "/" << p_dstPort->num
237
 
                           << endl;
238
 
                      anyError++;
239
 
                    }
240
 
                  }// all LMC lids 2 */
241
 
                } // all LMC lids 1 */
242
 
         } // all targets
243
 
  } // all sources
244
 
 
245
 
  if (anyError) {
246
 
         cout << "-E- Fail to traverse:" << anyError << " CA to CA paths" << endl;
247
 
         return 1;
248
 
  }
249
 
 
250
 
  return 0;
251
 
}
 
258
int
 
259
CrdLoopConnectUcastDepend(IBFabric* p_fabric)
 
260
{
 
261
    unsigned int lidStep = 1 << p_fabric->lmc;
 
262
    int anyError = 0;
 
263
    unsigned int i,j;
 
264
 
 
265
    // go over all ports in the fabric
 
266
    for ( i = p_fabric->minLid; i <= p_fabric->maxLid; i += lidStep) {
 
267
        IBPort *p_srcPort = p_fabric->PortByLid[i];
 
268
 
 
269
        if (!p_srcPort)
 
270
            continue;
 
271
        if (!CrdLoopIncludeUcastSwitchPaths &&
 
272
                (p_srcPort->p_node->type == IB_SW_NODE))
 
273
            continue;
 
274
 
 
275
        unsigned int sLid = p_srcPort->base_lid;
 
276
 
 
277
        // go over all the rest of the ports:
 
278
        for ( j = p_fabric->minLid; j <= p_fabric->maxLid; j += lidStep ) {
 
279
            IBPort *p_dstPort = p_fabric->PortByLid[j];
 
280
 
 
281
            // Avoid tracing to itself
 
282
            if (i == j)
 
283
                continue;
 
284
            if (! p_dstPort)
 
285
                continue;
 
286
            if (!CrdLoopIncludeUcastSwitchPaths &&
 
287
                    (p_dstPort->p_node->type == IB_SW_NODE))
 
288
                continue;
 
289
 
 
290
            unsigned int dLid = p_dstPort->base_lid;
 
291
            // go over all LMC combinations:
 
292
            for (unsigned int l1 = 0; l1 < lidStep; l1++) {
 
293
                for (unsigned int l2 = 0; l2 < lidStep; l2++) {
 
294
                    // Trace the path but record the input to output ports used.
 
295
                    if (CrdLoopMarkRouteByLFT(p_fabric, sLid + l1, dLid + l2)) {
 
296
                        cout << "-E- Fail to find a path from:"
 
297
                                << p_srcPort->p_node->name << "/" << p_srcPort->num
 
298
                                << " to:" << p_dstPort->p_node->name << "/" << p_dstPort->num
 
299
                                << endl;
 
300
                        anyError++;
 
301
                    }
 
302
                }// all LMC lids 2 */
 
303
            } // all LMC lids 1 */
 
304
        } // all targets
 
305
    } // all sources
 
306
 
 
307
    if (anyError) {
 
308
        cout << "-E- Fail to traverse:"
 
309
                << anyError << " CA to CA paths" << endl;
 
310
        return 1;
 
311
    }
 
312
    return 0;
 
313
}
 
314
 
 
315
 
 
316
/////////////////////////////////////////////////////////////////////////////
 
317
// Go over all Multicast Groups on all switches and add the dependecies
 
318
// they create to the dependency graph
 
319
// Return number of errors it found
 
320
int
 
321
CrdLoopConnectMcastDepend(IBFabric* p_fabric)
 
322
{
 
323
    // We support providing an SL list to each MLID by provining a special file
 
324
    // HACK: we can ignore connectivity check of the MCG and treat every switch
 
325
    // separately. The connectivity analysis can be run independently if loops
 
326
    // found.
 
327
 
 
328
    // HACK: the algorithm assumes constant SL2VL which is not port dependant!
 
329
    //       otherwise it should have been propagating traffic from each CA and SW on
 
330
    //       the MGRP such that the out VL of the previous port is known...
 
331
    //
 
332
    // Algorithm:
 
333
    // Foreach switch
 
334
    //   Create empty port-to-port P2P(sl,in,out) mask matrix for each SL
 
335
    //   Foreach MLID
 
336
    //     Foreach SL of MLID
 
337
    //        Copy the MFT(MLID) port mask to the matrix
 
338
    //   Foreach SL
 
339
    //      Lookup VL by SL - this is where the hack comes in handy
 
340
    //      Foreach in-port
 
341
    //         Foreach out-port
 
342
    //            Create the dependency edge (port-driving-in-port, VL, out-port, VL)
 
343
 
 
344
    int nErrs = 0;
 
345
    int addedEdges = 0;
 
346
 
 
347
    // foreach Switch
 
348
    for (map_str_pnode::const_iterator nI = p_fabric->NodeByName.begin();
 
349
            nI != p_fabric->NodeByName.end(); nI++) {
 
350
        IBNode *p_node = (*nI).second;
 
351
 
 
352
        // we only do MFT on switches
 
353
        if (p_node->type != IB_SW_NODE)
 
354
            continue;
 
355
 
 
356
        // allocate the array of dependencies:
 
357
        uint8_t sl_in_out_dep[16][p_node->numPorts+1][p_node->numPorts+1];
 
358
        memset(sl_in_out_dep, 0, sizeof(uint8_t)*16*(p_node->numPorts+1)*(p_node->numPorts+1));
 
359
 
 
360
        // foreach MLID
 
361
        for (unsigned int i = 0; i < p_node->MFT.size(); i++) {
 
362
            list<int> sls;
 
363
 
 
364
            // lookup SL's
 
365
            map_mlid_sl_list::const_iterator mlidI = mlidSLs.find(i+0xc000);
 
366
            if (mlidI != mlidSLs.end()) {
 
367
                sls = (*mlidI).second;
 
368
            } else {
 
369
                sls.push_back(0);
 
370
            }
 
371
 
 
372
            // now go over each SL at a time
 
373
            for (list<int>::const_iterator lI = sls.begin();
 
374
                    lI != sls.end();
 
375
                    lI++) {
 
376
                int sl = (*lI);
 
377
                // check all ports of the MFT
 
378
                uint64_t port_mask = p_node->MFT[i];
 
379
                for (unsigned int inPortNum = 1; inPortNum <= p_node->numPorts; inPortNum++) {
 
380
                    // we only care about port that are part of the MCG
 
381
                    if ((((uint64_t)1) << inPortNum) & port_mask) {
 
382
                        for (unsigned int outPortNum = 1; outPortNum <= p_node->numPorts; outPortNum++) {
 
383
                            if ((((uint64_t)1) << outPortNum) & port_mask) {
 
384
                                if (inPortNum != outPortNum) {
 
385
                                    sl_in_out_dep[sl][inPortNum][outPortNum] = 1;
 
386
                                }
 
387
                            }
 
388
                        }
 
389
                    }
 
390
                }
 
391
            }
 
392
        }
 
393
 
 
394
        // now convert the dependency matrix into channel graph edges:
 
395
        // Foreach SL
 
396
        for (unsigned int sl = 0; sl < 16; sl++) {
 
397
            for (unsigned int inPortNum = 1; inPortNum <= p_node->numPorts; inPortNum++) {
 
398
                for (unsigned int outPortNum = 1; outPortNum <= p_node->numPorts; outPortNum++) {
 
399
 
 
400
                    if (sl_in_out_dep[sl][inPortNum][outPortNum] != 1)
 
401
                        continue;
 
402
 
 
403
                    // Lookup VL by SL
 
404
                    int vl = p_node->getSLVL(inPortNum,outPortNum,sl);
 
405
 
 
406
                    // Create the dependency edge (port-driving-in-port, VL, out-port, VL)
 
407
                    IBPort *p_outPort = p_node->getPort(outPortNum);
 
408
                    if (! p_outPort) {
 
409
                        cout << "-E- Switch:" << p_node->name << " port:" << outPortNum
 
410
                                << " is included in some MFT but is not connnected" << endl;
 
411
                        nErrs++;
 
412
                        continue;
 
413
                    }
 
414
                    IBPort *p_inPort = p_node->getPort(inPortNum);
 
415
                    if (! p_inPort) {
 
416
                        cout << "-E- Switch:" << p_node->name << " port:" << inPortNum
 
417
                                << " is included in some MFT but is not connnected" << endl;
 
418
                        nErrs++;
 
419
                        continue;
 
420
                    }
 
421
                    IBPort *p_drvPort = p_inPort->p_remotePort;
 
422
                    if (! p_drvPort) {
 
423
                        cout << "-E- Switch:" << p_node->name << " port:" << inPortNum
 
424
                                << " is included in some MFT but has no remote port." << endl;
 
425
                        nErrs++;
 
426
                        continue;
 
427
                    }
 
428
 
 
429
                    if (p_drvPort->p_node->type != IB_SW_NODE)
 
430
                        continue;
 
431
 
 
432
                    // Init vchannel's number of possible dependencies
 
433
                    p_drvPort->channels[vl]->setDependSize((p_node->numPorts+1)*p_fabric->getNumVLs());
 
434
 
 
435
                    // HACK: we assume the same VL was used entering to this node
 
436
                    p_drvPort->channels[vl]->setDependency(outPortNum*p_fabric->getNumVLs()+vl,
 
437
                                                                     p_outPort->channels[vl]);
 
438
                    addedEdges++;
 
439
                }
 
440
            }
 
441
        }
 
442
    }
 
443
 
 
444
    // Ref from LFT code:
 
445
    // outPortNum is the FBD port
 
446
    // get the next port on the other side
 
447
    // p_portNext = p_node->getPort(outPortNum);
 
448
    // Now add an edge
 
449
    // p_port->channels[VL]->setDependency(outPortNum*p_fabric->getNumVLs()+nextVL,
 
450
    //                 p_portNext->channels[nextVL]);
 
451
    cout << "-I- MFT added " << addedEdges << " edges to links dependency graph" << endl;
 
452
    return(nErrs);
 
453
}
 
454
 
252
455
 
253
456
//////////////////////////////////////////////////////////////////////////////
254
 
 
255
457
// Prepare the data model
256
458
int
257
 
CrdLoopPrepare(IBFabric *p_fabric) {
258
 
  unsigned int lidStep = 1 << p_fabric->lmc;
259
 
 
260
 
  // go over all ports in the fabric
261
 
  for (int i = p_fabric->minLid; i <= p_fabric->maxLid; i += lidStep) {
262
 
    IBPort *p_Port = p_fabric->PortByLid[i];
263
 
    if (!p_Port) continue;
264
 
    IBNode *p_node = p_Port->p_node;
265
 
    int nL;
266
 
    if (p_node->type == IB_CA_NODE)
267
 
      nL = p_fabric->getNumSLs();
 
459
CrdLoopPrepare(IBFabric *p_fabric)
 
460
{
 
461
    unsigned int lidStep = 1 << p_fabric->lmc;
 
462
 
 
463
    // go over all ports in the fabric
 
464
    for (int i = p_fabric->minLid; i <= p_fabric->maxLid; i += lidStep) {
 
465
        IBPort *p_Port = p_fabric->PortByLid[i];
 
466
        if (!p_Port)
 
467
            continue;
 
468
        IBNode *p_node = p_Port->p_node;
 
469
        int nL;
 
470
        if (p_node->type == IB_CA_NODE)
 
471
            nL = p_fabric->getNumSLs();
 
472
        else
 
473
            nL = p_fabric->getNumVLs();
 
474
        // Go over all node's ports
 
475
        for (int k=0;k<p_node->Ports.size();k++) {
 
476
            IBPort* p_Port = p_node->Ports[k];
 
477
            // Init virtual channel array
 
478
            p_Port->channels.resize(nL);
 
479
            for (int j=0;j<nL;j++)
 
480
                p_Port->channels[j] = new VChannel(p_Port, j);
 
481
        }
 
482
    }
 
483
    return 0;
 
484
}
 
485
 
 
486
// Cleanup the data model
 
487
int
 
488
CrdLoopCleanup(IBFabric *p_fabric)
 
489
{
 
490
    unsigned int lidStep = 1 << p_fabric->lmc;
 
491
 
 
492
    // go over all ports in the fabric
 
493
    for (int i = p_fabric->minLid; i <= p_fabric->maxLid; i += lidStep) {
 
494
        IBPort *p_Port = p_fabric->PortByLid[i];
 
495
        if (!p_Port)
 
496
            continue;
 
497
        IBNode *p_node = p_Port->p_node;
 
498
        int nL;
 
499
        if (p_node->type == IB_CA_NODE)
 
500
            nL = p_fabric->getNumSLs();
 
501
        else
 
502
            nL = p_fabric->getNumVLs();
 
503
        // Go over all node's ports
 
504
        for (int k=0;k<p_node->Ports.size();k++) {
 
505
            IBPort* p_Port = p_node->Ports[k];
 
506
            for (int j=0;j<nL;j++)
 
507
                if (p_Port->channels[j])
 
508
                    ;//delete p_Port->channels[j];
 
509
        }
 
510
    }
 
511
}
 
512
 
 
513
 
 
514
//////////////////////////////////////////////////////////////////////////////
 
515
// Top Level Subroutine:
 
516
int
 
517
CrdLoopAnalyze(IBFabric *p_fabric)
 
518
{
 
519
    int res=0;
 
520
    cout << "-I- Analyzing Fabric for Credit Loops "
 
521
            << (int)p_fabric->getNumSLs() <<" SLs, "
 
522
            << (int)p_fabric->getNumVLs() << " VLs used." << endl;
 
523
 
 
524
    // Init data structures
 
525
    if (CrdLoopPrepare(p_fabric)) {
 
526
        cout << "-E- Fail to prepare data structures." << endl;
 
527
        return(1);
 
528
    }
 
529
    // Create the dependencies for unicast traffic
 
530
    if (CrdLoopConnectUcastDepend(p_fabric)) {
 
531
        cout << "-E- Fail to build dependency graphs." << endl;
 
532
        return(1);
 
533
    }
 
534
    // Do multicast if require
 
535
    if (CrdLoopIncludeMcastPaths) {
 
536
        if ( CrdLoopConnectMcastDepend(p_fabric) ) {
 
537
            cout << "-E- Fail to build multicast dependency graphs." << endl;
 
538
            return(1);
 
539
        }
 
540
    }
 
541
 
 
542
    // Find the loops if exist
 
543
    res = CrdLoopFindLoops(p_fabric);
 
544
    if (!res)
 
545
        cout << "-I- no credit loops found" << endl;
268
546
    else
269
 
      nL = p_fabric->getNumVLs();
270
 
    // Go over all node's ports
271
 
    for (int k=0;k<p_node->Ports.size();k++) {
272
 
      IBPort* p_Port = p_node->Ports[k];
273
 
      // Init virtual channel array
274
 
      p_Port->channels.resize(nL);
275
 
      for (int j=0;j<nL;j++)
276
 
        p_Port->channels[j] = new VChannel;
277
 
    }
278
 
  }
279
 
  return 0;
 
547
        cout << "-E- credit loops in routing"<<endl;
 
548
 
 
549
    // cleanup:
 
550
    CrdLoopCleanup(p_fabric);
 
551
    return res;
280
552
}
281
553
 
 
554
 
282
555
//////////////////////////////////////////////////////////////////////////////
283
 
 
284
 
// Top Level Subroutine:
285
556
int
286
 
CrdLoopAnalyze(IBFabric *p_fabric) {
287
 
  int res=0;
288
 
 
289
 
  cout << "-I- Analyzing Fabric for Credit Loops "<<(int)p_fabric->getNumSLs()<<" SLs, "<<(int)p_fabric->getNumVLs()<< " VLs used...";
290
 
  // Init data structures
291
 
  if (CrdLoopPrepare(p_fabric)) {
292
 
    cout << "-E- Fail to prepare data structures." << endl;
293
 
    return(1);
294
 
  }
295
 
  // Create the dependencies
296
 
  if (CrdLoopConnectDepend(p_fabric)) {
297
 
    cout << "-E- Fail to build dependency graphs." << endl;
298
 
    return(1);
299
 
  }
300
 
  // Find the loops if exist
301
 
  res = CrdLoopFindLoops(p_fabric);
302
 
  if (!res)
303
 
    cout << " no credit loops found" << endl;
304
 
  else
305
 
    cout << endl << "-E- credit loops in routing"<<endl;
306
 
 
307
 
  return res;
 
557
CredLoopMode(int include_switch_to_switch_paths, int include_multicast)
 
558
{
 
559
    CrdLoopIncludeUcastSwitchPaths = include_switch_to_switch_paths;
 
560
    CrdLoopIncludeMcastPaths = include_multicast;
 
561
    return 0;
308
562
}
309
 
 
310
 
 
311