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

« back to all changes in this revision

Viewing changes to ibmgtsim/src/sma.cpp

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2004 Mellanox Technologies LTD. All rights reserved.
 
3
 *
 
4
 * This software is available to you under a choice of one of two
 
5
 * licenses.  You may choose to be licensed under the terms of the GNU
 
6
 * General Public License (GPL) Version 2, available from the file
 
7
 * COPYING in the main directory of this source tree, or the
 
8
 * OpenIB.org BSD license below:
 
9
 *
 
10
 *     Redistribution and use in source and binary forms, with or
 
11
 *     without modification, are permitted provided that the following
 
12
 *     conditions are met:
 
13
 *
 
14
 *      - Redistributions of source code must retain the above
 
15
 *        copyright notice, this list of conditions and the following
 
16
 *        disclaimer.
 
17
 *
 
18
 *      - Redistributions in binary form must reproduce the above
 
19
 *        copyright notice, this list of conditions and the following
 
20
 *        disclaimer in the documentation and/or other materials
 
21
 *        provided with the distribution.
 
22
 *
 
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
24
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
25
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
26
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 
27
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 
28
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
29
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
30
 * SOFTWARE.
 
31
 *
 
32
 * $Id$
 
33
 */
 
34
 
 
35
/****h* IBMS/Sma
 
36
 * NAME
 
37
 * IB Subnet Manager Agent Simulator object
 
38
 *
 
39
 * DESCRIPTION
 
40
 * The simulator routes mad messages to the target node. This node
 
41
 *  MadProcessor SMA class is provided to handle and respond to these mads.
 
42
 *
 
43
 * AUTHOR
 
44
 * Nimrod Gindi, Mellanox
 
45
 *
 
46
 *********/
 
47
 
 
48
#include <iostream>
 
49
#include <fstream>
 
50
#include <stdlib.h>
 
51
#include <string>
 
52
 
 
53
#include "msgmgr.h"
 
54
#include "simmsg.h"
 
55
#include "sim.h"
 
56
#include "sma.h"
 
57
#include "helper.h"
 
58
 
 
59
#define TAVOR_DEVID 23108
 
60
#define ARBEL_DEVID 25208
 
61
#define ANAFA_DEVID 43132
 
62
#define ANAFA2_DEVID 47396
 
63
 
 
64
void
 
65
ibms_dump_mad(
 
66
  IN const  ibms_mad_msg_t  &madMsg,
 
67
  IN const  uint8_t         dir)
 
68
{
 
69
  if (dir == RCV)
 
70
  {
 
71
    MSGREG(inf100, 'M', "\n    Received Mad Dump\n$", "ibms_dump_mad");
 
72
    MSGSND(inf100, ibms_get_mad_header_str(madMsg.header));
 
73
  }
 
74
  else
 
75
  {
 
76
    MSGREG(inf101, 'M', "\n    Send Mad Dump\n$", "ibms_dump_mad");
 
77
    MSGSND(inf101, ibms_get_mad_header_str(madMsg.header));
 
78
  }
 
79
 
 
80
  switch (madMsg.header.attr_id) {
 
81
  case IB_MAD_ATTR_PORT_INFO:
 
82
    MSGREG(inf102, 'M', "\n   Port Info Dump\n$", "ibms_dump_mad");
 
83
    MSGSND(inf102, ibms_get_port_info_str((ib_port_info_t*)((ib_smp_t*) &madMsg.header)->data));
 
84
    break;
 
85
  case IB_MAD_ATTR_NODE_INFO:
 
86
    MSGREG(inf103, 'M', "\n   Node Info Dump\n$", "ibms_dump_mad");
 
87
    MSGSND(inf103, ibms_get_node_info_str((ib_node_info_t*)((ib_smp_t*) &madMsg.header)->data));
 
88
    break;
 
89
  default:
 
90
    MSGREG(warn1, 'W', "No handler written yet for this attribute:$", "ibms_dump_mad");
 
91
 
 
92
    MSGSND(warn1, cl_ntoh16(madMsg.header.attr_id));
 
93
    break;
 
94
  }
 
95
}
 
96
 
 
97
// CLASS SMATimer
 
98
 
 
99
SMATimer::SMATimer(int t):time(t)
 
100
{
 
101
  pthread_mutex_init(&timerMutex, NULL);
 
102
  tid = pthread_create(&th, NULL, SMATimer::timerRun, this);
 
103
  if (tid) {
 
104
    MSGREG(err0, 'E', "Couldn't create timer thread $ !", "processMad");
 
105
    MSGSND(err0, tid);
 
106
    }
 
107
  MSGREG(inf1, 'V', "SMA timer on!", "processMad");
 
108
  MSGSND(inf1);
 
109
}
 
110
 
 
111
void SMATimer::terminate()
 
112
{
 
113
  pthread_cancel(th);
 
114
}
 
115
 
 
116
void* SMATimer::timerRun(void* p)
 
117
{
 
118
  SMATimer* p_timer = (SMATimer*) p;
 
119
  while(1) {
 
120
    MSGREG(inf1, 'V', "Sleeping for $ secs !", "processMad");
 
121
    MSGSND(inf1,p_timer->time);
 
122
 
 
123
    sleep(p_timer->time);
 
124
    pthread_mutex_lock(&p_timer->timerMutex);
 
125
    unsigned i=0;
 
126
    while (i<p_timer->L.size()) {
 
127
      int res = p_timer->L[i].f(p_timer->L[i].data);
 
128
      if (!res)
 
129
        p_timer->L.erase(p_timer->L.begin()+i);
 
130
      else
 
131
        i++;
 
132
    }
 
133
    pthread_mutex_unlock(&p_timer->timerMutex);
 
134
  }
 
135
}
 
136
 
 
137
void SMATimer::reg (reg_t r)
 
138
{
 
139
  pthread_mutex_lock(&timerMutex);
 
140
  L.push_back(r);
 
141
  pthread_mutex_unlock(&timerMutex);
 
142
}
 
143
 
 
144
void SMATimer::unreg (void* data)
 
145
{
 
146
  pthread_mutex_lock(&timerMutex);
 
147
  for (unsigned i=0;i<L.size();i++)
 
148
    if (L[i].data == data) {
 
149
      L.erase(L.begin()+i);
 
150
      return;
 
151
    }
 
152
  pthread_mutex_unlock(&timerMutex);
 
153
}
 
154
 
 
155
// CLASS IBMSSma
 
156
 
 
157
SMATimer IBMSSma::mkeyTimer = SMATimer(T_FREQ);
 
158
 
 
159
int IBMSSma::cbMkey(void* data)
 
160
{
 
161
  portTiming* pT = (portTiming*) data;
 
162
  pthread_mutex_lock(&pT->mut);
 
163
  pT->counter--;
 
164
  if (pT->counter > 0) {
 
165
    pthread_mutex_unlock(&pT->mut);
 
166
    return 1;
 
167
  }
 
168
  // Need to zero m_key
 
169
  pT->pInfo->m_key = 0;
 
170
  pT->timerOn = 0;
 
171
  pthread_mutex_unlock(&pT->mut);
 
172
 
 
173
  return 0;
 
174
}
 
175
 
 
176
void IBMSSma::initSwitchInfo()
 
177
{
 
178
  IBNode              *pNodeData;
 
179
 
 
180
  pNodeData = pSimNode->getIBNode();
 
181
 
 
182
  pSimNode->switchInfo.lin_cap = CL_HTON16(0xbfff);
 
183
  pSimNode->switchInfo.rand_cap = 0;
 
184
  pSimNode->switchInfo.mcast_cap = CL_HTON16(0x1ff);
 
185
 
 
186
  pSimNode->switchInfo.lin_top = 0;
 
187
  pSimNode->switchInfo.def_port = 0;
 
188
  pSimNode->switchInfo.def_mcast_pri_port = 0;
 
189
  pSimNode->switchInfo.def_mcast_not_port = 0;
 
190
  pSimNode->switchInfo.life_state = 0;
 
191
  pSimNode->switchInfo.lids_per_port = 0;
 
192
  pSimNode->switchInfo.enforce_cap = CL_HTON16(32);
 
193
  pSimNode->switchInfo.flags = 0xA0; // capable partition enforce in/out
 
194
 
 
195
  MSGREG(inf1, 'V', "Initialization of node's SwitchInfo is Done !", "initSwitchInfo");
 
196
  MSGSND(inf1);
 
197
  pSimNode->sl2VlInPortEntry.resize((pSimNode->nodeInfo.num_ports) + 1);
 
198
  initSwitchSl2VlTable();
 
199
}
 
200
 
 
201
void IBMSSma::initNodeInfo()
 
202
{
 
203
  IBNode              *pNodeData;
 
204
 
 
205
  pNodeData = pSimNode->getIBNode();
 
206
  pSimNode->nodeInfo.base_version = 1 ;
 
207
  pSimNode->nodeInfo.class_version = 1 ;
 
208
  pSimNode->nodeInfo.num_ports = pNodeData->numPorts;
 
209
 
 
210
  // HACK: as the devId is not really meaningful due to IBDM limitation
 
211
  // we only rely on the type of device. HCAs get 64 PKeys switches: 24.
 
212
  if (pNodeData->type == 1)
 
213
  {
 
214
    //Switch
 
215
    pSimNode->nodeInfo.node_type = IB_NODE_TYPE_SWITCH;
 
216
    pSimNode->nodeInfo.partition_cap = CL_HTON16(24);
 
217
    initSwitchInfo();
 
218
  }
 
219
  else if (pNodeData->type == 2)
 
220
  {
 
221
    //HCA
 
222
    pSimNode->nodeInfo.node_type = IB_NODE_TYPE_CA;
 
223
    pSimNode->sl2VlInPortEntry.resize((pSimNode->nodeInfo.num_ports) + 1);
 
224
    pSimNode->nodeInfo.partition_cap = CL_HTON16(0x40);
 
225
    initCaSl2VlTable();
 
226
  }
 
227
  else
 
228
  {
 
229
    MSGREG(err0, 'E', "Node Type is un-known $ !", "initNodeInfo");
 
230
    MSGSND(err0, pNodeData->type);
 
231
  }
 
232
  pSimNode->nodeInfo.sys_guid = cl_hton64(pNodeData->guid_get());
 
233
  pSimNode->nodeInfo.node_guid = pSimNode->nodeInfo.sys_guid;
 
234
  pSimNode->nodeInfo.port_guid = pSimNode->nodeInfo.sys_guid;
 
235
 
 
236
  pSimNode->nodeInfo.device_id = cl_hton16(pNodeData->devId);
 
237
  pSimNode->nodeInfo.revision = cl_hton32(pNodeData->revId);
 
238
  {
 
239
    uint32_t tmpVendorLocalPort;
 
240
    tmpVendorLocalPort = pNodeData->vendId | (1 << 24);
 
241
    pSimNode->nodeInfo.port_num_vendor_id = cl_hton32(tmpVendorLocalPort);
 
242
  }
 
243
  MSGREG(inf1, 'V', "Initialization of node's NodeInfo is Done !", "initNodeInfo");
 
244
  MSGSND(inf1);
 
245
}
 
246
 
 
247
void IBMSSma::initPKeyTables()
 
248
{
 
249
 
 
250
   /* initialize pkeys */
 
251
   ib_pkey_table_t zeroPKeys;
 
252
   ib_pkey_table_t firstBlockPkeys;
 
253
   memset(&zeroPKeys, 0, sizeof(ib_pkey_table_t));
 
254
   memset(&firstBlockPkeys, 0, sizeof(ib_pkey_table_t));
 
255
   firstBlockPkeys.pkey_entry[0] = 0xffff;
 
256
 
 
257
   unsigned int numBlocks;
 
258
   vector< ib_pkey_table_t > emptyPkeyVector;
 
259
 
 
260
   for (unsigned int pn = 0; pn <= pSimNode->nodeInfo.num_ports; pn++)
 
261
   {
 
262
      pSimNode->nodePortPKeyTable.push_back(emptyPkeyVector);
 
263
      if ( (pSimNode->nodeInfo.node_type != IB_NODE_TYPE_SWITCH) || (pn == 0) )
 
264
         numBlocks = (cl_ntoh16(pSimNode->nodeInfo.partition_cap) + 31) / 32;
 
265
      else
 
266
        numBlocks = (cl_ntoh16(pSimNode->switchInfo.enforce_cap) + 31) / 32;
 
267
 
 
268
      for (unsigned int block = 0; block < numBlocks; block++)
 
269
      {
 
270
         if (block)
 
271
         {
 
272
            pSimNode->nodePortPKeyTable[pn].push_back(zeroPKeys);
 
273
         }
 
274
         else
 
275
         {
 
276
            pSimNode->nodePortPKeyTable[pn].push_back(firstBlockPkeys);
 
277
         }
 
278
      }
 
279
   }
 
280
}
 
281
 
 
282
void IBMSSma::initVlArbitTable()
 
283
{
 
284
  uint8_t                     i,j,k;
 
285
  ib_vl_arb_table_t           vlArbitEntry;
 
286
 
 
287
  for (i=0; i <= (pSimNode->nodeInfo.num_ports) ; i++)
 
288
  {
 
289
    //TODO when supporting enhanced port0 - will need to support 0 here as well
 
290
    // Zero is dummy for the moment
 
291
    for (j=0; j <= 4 ; j++)
 
292
    {
 
293
      for (k=0; k < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ; k++)
 
294
      {
 
295
        vlArbitEntry.vl_entry[k].vl = k % IB_MAX_NUM_VLS;
 
296
        vlArbitEntry.vl_entry[k].weight = 1;
 
297
      }
 
298
      (pSimNode->vlArbPortEntry[i]).push_back( vlArbitEntry );
 
299
    }
 
300
  }
 
301
 
 
302
  MSGREG(inf1, 'V', "Initialization of VL arbitration table is Done !", "initVlArbitTable");
 
303
  MSGSND(inf1);
 
304
}
 
305
 
 
306
void IBMSSma::initSwitchSl2VlTable()
 
307
{
 
308
  uint8_t                     i,j,k;
 
309
  ib_slvl_table_t             slToVlEntry;
 
310
 
 
311
  for (i=0; i <= (pSimNode->nodeInfo.num_ports) ; i++)
 
312
  {
 
313
    //TODO when supporting enhanced port0 - will need to support 0 here as well
 
314
    // Zero is dummy for the moment
 
315
    for (j=0; j <= (pSimNode->nodeInfo.num_ports) ; j++)
 
316
    {
 
317
      for (k=0; k < (IB_MAX_NUM_VLS/2) ; k++)
 
318
      {
 
319
        slToVlEntry.raw_vl_by_sl[k] = 0xf;
 
320
      }
 
321
      (pSimNode->sl2VlInPortEntry[i]).push_back( slToVlEntry );
 
322
    }
 
323
  }
 
324
 
 
325
  MSGREG(inf1, 'V', "Initialization of switch SL to VL table is Done !", "initSwitchSl2VlTable");
 
326
  MSGSND(inf1);
 
327
}
 
328
 
 
329
void IBMSSma::initCaSl2VlTable()
 
330
{
 
331
  uint8_t                     i,k;
 
332
  ib_slvl_table_t             slToVlEntry;
 
333
 
 
334
  for (i=0; i <= (pSimNode->nodeInfo.num_ports) ; i++)
 
335
  {
 
336
    for (k=0; k < (IB_MAX_NUM_VLS/2) ; k++)
 
337
    {
 
338
      slToVlEntry.raw_vl_by_sl[k] = 0xf;
 
339
    }
 
340
    (pSimNode->sl2VlInPortEntry[i]).push_back( slToVlEntry );
 
341
  }
 
342
 
 
343
  MSGREG(inf1, 'V', "Initialization of CA SL to VL table is Done !", "initCaSl2VlTable");
 
344
  MSGSND(inf1);
 
345
}
 
346
 
 
347
void IBMSSma::initPortInfo()
 
348
{
 
349
  MSG_ENTER_FUNC;
 
350
 
 
351
  uint8_t             i=0;
 
352
  ib_port_info_t      tmpPortInfo;
 
353
  IBPort              *pNodePortData;
 
354
  IBNode              *pNodeData;
 
355
 
 
356
  pNodeData = pSimNode->getIBNode();
 
357
 
 
358
  memset((void*)&tmpPortInfo, 0, sizeof(ib_port_info_t));
 
359
  if (pSimNode->nodeInfo.node_type == IB_NODE_TYPE_CA)
 
360
  {
 
361
    MSGREG(inf1, 'V', "Creating dummy port number $ for xCA !", "initPortInfo");
 
362
    MSGSND(inf1, i);
 
363
  }
 
364
  else if (pSimNode->nodeInfo.node_type == IB_NODE_TYPE_SWITCH)
 
365
  {
 
366
    // TODO add Enhanced Port Zero support
 
367
    MSGREG(inf2, 'V', "Creating Base port Zero for Switch !", "initPortInfo");
 
368
    MSGSND(inf2);
 
369
 
 
370
    //Init the port 0 of the switch according to it's capability
 
371
    tmpPortInfo.capability_mask = CL_HTON32(0x808);
 
372
    ib_port_info_set_lmc(&tmpPortInfo, 0);
 
373
    ib_port_info_set_mpb(&tmpPortInfo, 0);
 
374
    //we do not have to support this ! (HACK: Done to avoid OSM bugs)
 
375
    //  Base Port 0 case we need mtu_cap too:
 
376
    tmpPortInfo.mtu_cap = 1;
 
377
    ib_port_info_set_neighbor_mtu(&tmpPortInfo, 1);
 
378
    ib_port_info_set_vl_cap(&tmpPortInfo, 4);
 
379
    ib_port_info_set_port_state( &tmpPortInfo, IB_LINK_ACTIVE);
 
380
    ib_port_info_set_port_phys_state( 5, &tmpPortInfo);
 
381
 
 
382
    tmpPortInfo.subnet_timeout = 0;
 
383
    tmpPortInfo.resp_time_value = 0x6;
 
384
 
 
385
  }
 
386
  else
 
387
  {
 
388
    MSGREG(err0, 'E', "Attempt to initialize unknown device port !", "initPortInfo");
 
389
    MSGSND(err0);
 
390
    MSG_EXIT_FUNC;
 
391
    return;
 
392
  }
 
393
  pSimNode->nodePortsInfo.push_back( tmpPortInfo );
 
394
  i++;
 
395
 
 
396
  while (i <= pSimNode->nodeInfo.num_ports)
 
397
  {
 
398
    MSGREG(inf1, 'V', "Initializing port number $ !", "initPortInfo");
 
399
    MSGSND(inf1, i);
 
400
 
 
401
    memset((void*)&tmpPortInfo, 0, sizeof(ib_port_info_t));
 
402
    pNodePortData = pNodeData->getPort(i);
 
403
    if ((pNodePortData == NULL) || (pNodePortData->p_remotePort == NULL))
 
404
    {
 
405
      MSGREG(wrn0, 'W', "Attempt to reach port $ failed - no such port OR it's not connected!", "initPortInfo");
 
406
      MSGSND(wrn0, i);
 
407
      MSGREG(wrn1, 'W', " Entering dummy entry !", "initPortInfo");
 
408
      MSGSND(wrn1);
 
409
      //TODO handle not connected port generic - remove all assignments from below
 
410
      ib_port_info_set_port_state( &tmpPortInfo, IB_LINK_DOWN);
 
411
      ib_port_info_set_port_phys_state( 2, &tmpPortInfo);
 
412
      pSimNode->nodePortsInfo.push_back( tmpPortInfo );
 
413
      i++;
 
414
      continue;
 
415
    }
 
416
 
 
417
    tmpPortInfo.base_lid = cl_hton16(pNodePortData->base_lid);
 
418
    tmpPortInfo.capability_mask = CL_HTON32(0x808);
 
419
    tmpPortInfo.local_port_num = i;
 
420
    tmpPortInfo.link_width_enabled = pNodePortData->width;
 
421
    tmpPortInfo.link_width_supported = pNodePortData->width;
 
422
    tmpPortInfo.link_width_active = pNodePortData->width;
 
423
    {
 
424
      int linkSpeed = pNodePortData->speed;
 
425
 
 
426
      if (pNodePortData->speed == 2)
 
427
      {
 
428
        linkSpeed = 3;
 
429
      }
 
430
      else if (pNodePortData->speed == 4)
 
431
      {
 
432
        linkSpeed = 7;
 
433
      }
 
434
      // LinkSpeedSupported and PortState
 
435
      ib_port_info_set_port_state( &tmpPortInfo, IB_LINK_INIT);
 
436
      ib_port_info_set_link_speed_sup( linkSpeed, &tmpPortInfo);
 
437
      // LinkSpeedEnabled and LinkSpeedActive
 
438
      tmpPortInfo.link_speed = linkSpeed | (pNodePortData->speed << 4);
 
439
 
 
440
    }
 
441
 
 
442
    // PortPhysState and LinkDownDefaultState
 
443
    ib_port_info_set_port_phys_state( 5, &tmpPortInfo);
 
444
    ib_port_info_set_link_down_def_state( &tmpPortInfo, 2);
 
445
    tmpPortInfo.mtu_smsl = 1;
 
446
    ib_port_info_set_neighbor_mtu( &tmpPortInfo, 4);
 
447
    ib_port_info_set_vl_cap(&tmpPortInfo, 4);
 
448
         tmpPortInfo.vl_high_limit = 1;
 
449
         tmpPortInfo.vl_arb_high_cap = 8;
 
450
         tmpPortInfo.vl_arb_low_cap = 8;
 
451
         tmpPortInfo.mtu_cap = 4;
 
452
    tmpPortInfo.guid_cap = 32;
 
453
    tmpPortInfo.resp_time_value = 20;
 
454
 
 
455
    pSimNode->nodePortsInfo.push_back( tmpPortInfo );
 
456
    i++;
 
457
  }
 
458
  MSG_EXIT_FUNC;
 
459
  return;
 
460
}
 
461
 
 
462
 
 
463
IBMSSma::IBMSSma(IBMSNode *pSNode, list_uint16 mgtClasses) :
 
464
  IBMSMadProcessor(pSNode, mgtClasses)
 
465
{
 
466
  MSG_ENTER_FUNC;
 
467
 
 
468
  IBNode*     pNodeData;
 
469
 
 
470
  pNodeData = pSNode->getIBNode();
 
471
  //Init NodeInfo structure of the node
 
472
  initNodeInfo();
 
473
  //Init P_Key ports vector size
 
474
  pSimNode->nodePortPKeyTable.resize(pSimNode->nodeInfo.num_ports + 1);
 
475
  //Init PortInfo structure of the node + Init P_Key Tables of ports
 
476
  initPortInfo();
 
477
  //Init VL Arbitration ports vector size and table
 
478
  pSimNode->vlArbPortEntry.resize(pSimNode->nodeInfo.num_ports + 1);
 
479
  //Init ports' timing vector
 
480
  vPT.resize(pSimNode->nodeInfo.num_ports + 1);
 
481
  for (unsigned i=0;i<vPT.size();i++)
 
482
    if ((pSimNode->nodeInfo.node_type == IB_NODE_TYPE_SWITCH) || i!=0) {
 
483
      vPT[i].pInfo = &(pSimNode->nodePortsInfo[i]);
 
484
      pthread_mutex_init(&vPT[i].mut, NULL);
 
485
      vPT[i].timerOn = 0;
 
486
    }
 
487
  initVlArbitTable();
 
488
 
 
489
  initPKeyTables();
 
490
 
 
491
  MSG_EXIT_FUNC;
 
492
};
 
493
 
 
494
//--------------------------------------------------------------------------------
 
495
//--------------------------------------------------------------------------------
 
496
//--------------------------------------------------------------------------------
 
497
 
 
498
int IBMSSma::nodeDescMad(ibms_mad_msg_t &respMadMsg)
 
499
{
 
500
  MSG_ENTER_FUNC;
 
501
 
 
502
  ib_smp_t* pRespMad;
 
503
 
 
504
  MSGREG(inf1, 'I', "NodeDescription Get mad handling !", "nodeDescMad");
 
505
  MSGSND(inf1);
 
506
  pRespMad = (ib_smp_t*) &respMadMsg.header;
 
507
 
 
508
  string desc;
 
509
  if (pSimNode->nodeInfo.node_type != 2)
 
510
  {
 
511
    desc = (pSimNode->getIBNode())->p_system->name + string(" HCA-1 (Mellanox HCA)");
 
512
  }
 
513
  else
 
514
  {
 
515
    desc =  (pSimNode->getIBNode())->p_system->name + string(" Infiniscale-III Mellanox Technologies");
 
516
  }
 
517
 
 
518
  int descLen = desc.size();
 
519
  if (descLen > 64) descLen = 64;
 
520
  memcpy(pRespMad->data, desc.c_str(), descLen);
 
521
  if (descLen < 64) pRespMad->data[descLen] = 0;
 
522
  MSG_EXIT_FUNC;
 
523
  return 0;
 
524
}
 
525
 
 
526
int IBMSSma::nodeInfoMad(ibms_mad_msg_t &respMadMsg, uint8_t inPort)
 
527
{
 
528
  MSG_ENTER_FUNC;
 
529
 
 
530
  ib_smp_t* pRespMad;
 
531
 
 
532
  MSGREG(inf1, 'I', "NodeInfo Get mad handling !", "nodeInfoMad");
 
533
  MSGSND(inf1);
 
534
  pRespMad = (ib_smp_t*) &respMadMsg.header;
 
535
  ib_node_info_set_local_port_num( &(pSimNode->nodeInfo), inPort);
 
536
  memcpy (pRespMad->data, &(pSimNode->nodeInfo), sizeof(pSimNode->nodeInfo));
 
537
 
 
538
  /* provide the port guid for CA ports */
 
539
  if (pSimNode->nodeInfo.node_type != 2)
 
540
  {
 
541
    ib_node_info_t *p_node_info = (ib_node_info_t *)pRespMad->data;
 
542
    IBPort *pPort = pSimNode->getIBNode()->getPort(inPort);
 
543
    if (pPort)
 
544
      p_node_info->port_guid = cl_hton64(pPort->guid_get());
 
545
  }
 
546
 
 
547
  MSG_EXIT_FUNC;
 
548
  return 0;
 
549
}
 
550
 
 
551
int IBMSSma::lftMad(ibms_mad_msg_t &respMadMsg, ibms_mad_msg_t &reqMadMsg)
 
552
{
 
553
  MSG_ENTER_FUNC;
 
554
 
 
555
  ib_net16_t          status = 0;
 
556
  ib_smp_t*           pRespMad;
 
557
  uint8_t               lftBlock[64];
 
558
  uint32_t            lftIndex = 0;
 
559
  uint32_t            iter = 0;
 
560
 
 
561
  pRespMad = (ib_smp_t*) &respMadMsg.header;
 
562
 
 
563
  if ((uint16_t)(cl_ntoh16(pSimNode->switchInfo.lin_cap)/64) <
 
564
      cl_ntoh32(reqMadMsg.header.attr_mod))
 
565
  {
 
566
    MSGREG(err0, 'E',
 
567
           "Req. lft block is $ while SwitchInfo LFT Cap is $ !",
 
568
           "lftMad");
 
569
    MSGSND(err0, cl_ntoh32(reqMadMsg.header.attr_mod),
 
570
           cl_ntoh16(pSimNode->switchInfo.lin_cap));
 
571
    status = IB_MAD_STATUS_INVALID_FIELD;
 
572
 
 
573
    MSG_EXIT_FUNC;
 
574
    return status;
 
575
  }
 
576
 
 
577
  lftIndex = cl_ntoh32(reqMadMsg.header.attr_mod) * 64;
 
578
  iter = cl_ntoh32(reqMadMsg.header.attr_mod);
 
579
  MSGREG(inf3, 'V', "Linear Forwarding entry handled is $ and block number is $ ", "lftMad");
 
580
  MSGSND(inf3, lftIndex, iter);
 
581
 
 
582
  if (reqMadMsg.header.method == IB_MAD_METHOD_GET)
 
583
  {
 
584
    MSGREG(inf1, 'V', "LFT SubnGet !", "lftMad");
 
585
    MSGSND(inf1);
 
586
 
 
587
    //copy entries from lft according to index
 
588
    for (iter=0;iter<64;iter++) lftBlock[iter] =
 
589
                                  (pSimNode->getIBNode())->getLFTPortForLid(lftIndex + iter);
 
590
  }
 
591
  else
 
592
  {
 
593
    MSGREG(inf2, 'V', "LFT SubnSet !", "lftMad");
 
594
    MSGSND(inf2);
 
595
 
 
596
    memcpy ( &lftBlock[0], pRespMad->data, 64 * sizeof(uint8_t));
 
597
    //copy entries from lft according to index
 
598
    for (iter=0;iter<64;iter++)
 
599
      (pSimNode->getIBNode())->setLFTPortForLid(lftIndex + iter, lftBlock[iter]);
 
600
  }
 
601
 
 
602
  memcpy (pRespMad->data, &lftBlock[0], 64 * sizeof(uint8_t));
 
603
 
 
604
  MSG_EXIT_FUNC;
 
605
  return status;
 
606
}
 
607
 
 
608
int IBMSSma::vlArbMad(ibms_mad_msg_t &respMadMsg, ibms_mad_msg_t &reqMadMsg, uint8_t inPort)
 
609
{
 
610
  MSG_ENTER_FUNC;
 
611
 
 
612
  ib_net16_t          status = 0;
 
613
  ib_smp_t*           pRespMad;
 
614
  ib_smp_t*           pReqMad;
 
615
  uint8_t             portIndex, priorityIndex;
 
616
  ib_vl_arb_table_t   vlArbEntryElm;
 
617
  ib_vl_arb_table_t*  pVlArbEntryElm;
 
618
 
 
619
  if (pSimNode->nodeInfo.node_type == IB_NODE_TYPE_SWITCH)
 
620
  {
 
621
    portIndex = (cl_ntoh32(reqMadMsg.header.attr_mod) & 0xff);
 
622
  }
 
623
  else
 
624
  {
 
625
    portIndex = inPort;
 
626
  }
 
627
  priorityIndex = (cl_ntoh32(reqMadMsg.header.attr_mod) >> 16);
 
628
  if (priorityIndex == 0) {
 
629
    MSGREG(err0, 'E',
 
630
           "Req.  blockIndex is $ legal values are 1..4 !",
 
631
           "vlArbMad");
 
632
    MSGSND(err0, portIndex, pSimNode->nodeInfo.num_ports);
 
633
    status = IB_MAD_STATUS_INVALID_FIELD;
 
634
 
 
635
    MSG_EXIT_FUNC;
 
636
    return status;
 
637
  }
 
638
  if (portIndex > pSimNode->nodeInfo.num_ports)
 
639
  {
 
640
    MSGREG(err1, 'E',
 
641
           "Req. port is $ while Node number of ports is $ !",
 
642
           "vlArbMad");
 
643
    MSGSND(err1, portIndex, pSimNode->nodeInfo.num_ports);
 
644
    status = IB_MAD_STATUS_INVALID_FIELD;
 
645
 
 
646
    MSG_EXIT_FUNC;
 
647
    return status;
 
648
  }
 
649
  pRespMad = (ib_smp_t*) &respMadMsg.header;
 
650
  pReqMad = (ib_smp_t*) &reqMadMsg.header;
 
651
 
 
652
  MSGREG(inf0, 'V', "VL Arbitration entry handled for port $ and priority $ ", "vlArbMad");
 
653
  MSGSND(inf0, portIndex, priorityIndex);
 
654
 
 
655
  if (reqMadMsg.header.method == IB_MAD_METHOD_GET)
 
656
  {
 
657
    MSGREG(inf1, 'V', "VL Arbitration SubnGet !", "vlArbMad");
 
658
    MSGSND(inf1);
 
659
 
 
660
    vlArbEntryElm = (pSimNode->vlArbPortEntry[portIndex])[priorityIndex];
 
661
    memcpy ((void*)(pRespMad->data), (void*)(&vlArbEntryElm), sizeof(ib_vl_arb_table_t));
 
662
  }
 
663
  else
 
664
  {
 
665
    MSGREG(inf2, 'V', "VL Arbitration SubnSet !", "vlArbMad");
 
666
    MSGSND(inf2);
 
667
 
 
668
    pVlArbEntryElm = &(pSimNode->vlArbPortEntry[portIndex])[priorityIndex];
 
669
    memcpy ((void*)(pVlArbEntryElm), (void*)(pReqMad->data), sizeof(ib_vl_arb_table_t));
 
670
    memcpy ((void*)(pRespMad->data), (void*)(pReqMad->data), sizeof(ib_vl_arb_table_t));
 
671
  }
 
672
 
 
673
  MSG_EXIT_FUNC;
 
674
  return status;
 
675
}
 
676
 
 
677
int IBMSSma::sl2VlMad(ibms_mad_msg_t &respMadMsg, ibms_mad_msg_t &reqMadMsg, uint8_t inPort)
 
678
{
 
679
  MSG_ENTER_FUNC;
 
680
 
 
681
  ib_net16_t          status = 0;
 
682
  ib_smp_t*           pRespMad;
 
683
  ib_smp_t*           pReqMad;
 
684
  uint8_t             inputPortIndex, outputPortIndex;
 
685
  ib_slvl_table_t     sl2VlEntryElm;
 
686
  ib_slvl_table_t*    pSl2VlEntryElm;
 
687
 
 
688
  if (pSimNode->nodeInfo.node_type == IB_NODE_TYPE_SWITCH)
 
689
  {
 
690
    inputPortIndex = ((cl_ntoh32(reqMadMsg.header.attr_mod) >> 8) & 0xff);
 
691
    outputPortIndex = (cl_ntoh32(reqMadMsg.header.attr_mod) & 0xff);
 
692
  }
 
693
  else
 
694
  {
 
695
    inputPortIndex = 0;
 
696
    outputPortIndex = inPort;
 
697
  }
 
698
 
 
699
  if ((inputPortIndex > pSimNode->nodeInfo.num_ports) ||
 
700
      (outputPortIndex > pSimNode->nodeInfo.num_ports))
 
701
  {
 
702
    MSGREG(err0, 'E',
 
703
           "Req. mft input port is $ and output port is $ while Node number of ports is $ !",
 
704
           "sl2VlMad");
 
705
    MSGSND(err0, inputPortIndex, outputPortIndex, pSimNode->nodeInfo.num_ports);
 
706
    status = IB_MAD_STATUS_INVALID_FIELD;
 
707
 
 
708
    MSG_EXIT_FUNC;
 
709
    return status;
 
710
  }
 
711
  pRespMad = (ib_smp_t*) &respMadMsg.header;
 
712
  pReqMad = (ib_smp_t*) &reqMadMsg.header;
 
713
 
 
714
  MSGREG(inf0, 'V', "SL2VL entry handled for input port $ and output port $ ", "sl2VlMad");
 
715
  MSGSND(inf0, inputPortIndex, outputPortIndex);
 
716
 
 
717
  if (reqMadMsg.header.method == IB_MAD_METHOD_GET)
 
718
  {
 
719
    MSGREG(inf1, 'V', "SL2VL SubnGet !", "sl2VlMad");
 
720
    MSGSND(inf1);
 
721
 
 
722
    sl2VlEntryElm = (pSimNode->sl2VlInPortEntry[inputPortIndex])[outputPortIndex];
 
723
    memcpy ((void*)(pRespMad->data), (void*)(&sl2VlEntryElm), sizeof(ib_slvl_table_t));
 
724
  }
 
725
  else
 
726
  {
 
727
    MSGREG(inf2, 'V', "SL2VL SubnSet !", "sl2VlMad");
 
728
    MSGSND(inf2);
 
729
 
 
730
    pSl2VlEntryElm = &(pSimNode->sl2VlInPortEntry[inputPortIndex])[outputPortIndex];
 
731
    memcpy ((void*)(pSl2VlEntryElm), (void*)(pReqMad->data), sizeof(ib_slvl_table_t));
 
732
    memcpy ((void*)(pRespMad->data), (void*)(pReqMad->data), sizeof(ib_slvl_table_t));
 
733
  }
 
734
 
 
735
  MSG_EXIT_FUNC;
 
736
  return status;
 
737
}
 
738
 
 
739
int IBMSSma::mftMad(ibms_mad_msg_t &respMadMsg, ibms_mad_msg_t &reqMadMsg)
 
740
{
 
741
  MSG_ENTER_FUNC;
 
742
 
 
743
  ib_net16_t          status = 0;
 
744
  ib_smp_t*           pRespMad;
 
745
  ib_smp_t*           pReqMad;
 
746
  uint16_t            mftTableEntryIndex = (cl_ntoh32(reqMadMsg.header.attr_mod) & IB_MCAST_BLOCK_ID_MASK_HO);
 
747
  uint8_t             mftPortEntryIndex = (cl_ntoh32(reqMadMsg.header.attr_mod) >> IB_MCAST_POSITION_SHIFT);
 
748
  ib_mft_table_t*     pMftEntryElm;
 
749
 
 
750
  pRespMad = (ib_smp_t*) &respMadMsg.header;
 
751
  pReqMad = (ib_smp_t*) &reqMadMsg.header;
 
752
 
 
753
  // checking for:
 
754
  // 1. AM bits 0-8 =< SwitchInfo:MftCap
 
755
  // 2. ((((AM bits 28-31) + 1)*16)-1) <= NodeInfo:NumberOfPort
 
756
  if ((cl_ntoh16(pSimNode->switchInfo.mcast_cap)/IB_MCAST_BLOCK_SIZE) < mftTableEntryIndex)
 
757
  {
 
758
    MSGREG(err0, 'E',
 
759
           "Req. mft entry block is $ while SwitchInfo MFT Cap is $ !",
 
760
           "mftMad");
 
761
    MSGSND(err0, mftTableEntryIndex,
 
762
           cl_ntoh16(pSimNode->switchInfo.mcast_cap));
 
763
    status = IB_MAD_STATUS_INVALID_FIELD;
 
764
    MSG_EXIT_FUNC;
 
765
    return status;
 
766
  }
 
767
 
 
768
  if (mftPortEntryIndex * 16 > pSimNode->nodeInfo.num_ports)
 
769
  {
 
770
    MSGREG(err1, 'E',
 
771
           "Req. mft port block is $ while NodeInfo number of ports is $ !",
 
772
           "mftMad");
 
773
    MSGSND(err1, mftPortEntryIndex, pSimNode->nodeInfo.num_ports);
 
774
    status = IB_MAD_STATUS_INVALID_FIELD;
 
775
 
 
776
    MSG_EXIT_FUNC;
 
777
    return status;
 
778
  }
 
779
 
 
780
  MSGREG(inf3, 'E', "Multicast Forwarding entry handled portIdx $ blockIdx $ ", "mftMad");
 
781
  MSGSND(inf3, mftTableEntryIndex, mftPortEntryIndex);
 
782
 
 
783
  if (reqMadMsg.header.method == IB_MAD_METHOD_GET)
 
784
  {
 
785
    MSGREG(inf1, 'V', "MFT SubnGet !", "mftMad");
 
786
    MSGSND(inf1);
 
787
 
 
788
         if ( (mftPortEntryIndex >= pSimNode->switchMftPortsEntry.size()) ||
 
789
                        (mftTableEntryIndex >= pSimNode->switchMftPortsEntry[mftPortEntryIndex].size()))
 
790
         {
 
791
                 MSGREG(warn1, 'W', "MFT SubnGet with uninitialized values at portIdx:$ blockIdx:$  !", "mftMad");
 
792
                 MSGSND(warn1,mftPortEntryIndex, mftTableEntryIndex);
 
793
                 memset ((void*)(pRespMad->data), 0, sizeof(ib_mft_table_t));
 
794
                 MSG_EXIT_FUNC;
 
795
                 return status;
 
796
         }
 
797
 
 
798
    pMftEntryElm = &(pSimNode->switchMftPortsEntry[mftPortEntryIndex][mftTableEntryIndex]);
 
799
    memcpy ((void*)(pRespMad->data), (void*)(pMftEntryElm), sizeof(ib_mft_table_t));
 
800
  }
 
801
  else
 
802
  {
 
803
          unsigned i;
 
804
    MSGREG(inf2, 'V', "MFT SubnSet !", "mftMad");
 
805
    MSGSND(inf2);
 
806
 
 
807
         MSGREG(inf9, 'E', "MFT SubnSet $ base_port:$ block:$ entry 0 value:$", "mftMad");
 
808
 
 
809
         for (i = pSimNode->switchMftPortsEntry.size(); i <= mftPortEntryIndex; i++)
 
810
         {
 
811
                 vector < ib_mft_table_t > tmpVec;
 
812
                 pSimNode->switchMftPortsEntry.push_back(tmpVec);
 
813
         }
 
814
 
 
815
         for (i = pSimNode->switchMftPortsEntry[mftPortEntryIndex].size(); i <= mftTableEntryIndex; i++)
 
816
         {
 
817
                 ib_mft_table_t tmp;
 
818
                 memset(&tmp, 0, sizeof(ib_mft_table_t));
 
819
                 pSimNode->switchMftPortsEntry[mftPortEntryIndex].push_back(tmp);
 
820
         }
 
821
 
 
822
    pMftEntryElm = &(pSimNode->switchMftPortsEntry[mftPortEntryIndex][mftTableEntryIndex]);
 
823
    memcpy ((void*)(pMftEntryElm), (void*)(pReqMad->data), sizeof(ib_mft_table_t));
 
824
         char buff[16];
 
825
        sprintf(buff,"0x%04x", cl_ntoh16(pMftEntryElm->mft_entry[0]));
 
826
        MSGSND(inf9, pSimNode->getIBNode()->name,
 
827
                        mftPortEntryIndex, mftTableEntryIndex, buff);
 
828
    memcpy ((void*)(pRespMad->data), (void*)(pReqMad->data), sizeof(ib_mft_table_t));
 
829
  }
 
830
 
 
831
  MSG_EXIT_FUNC;
 
832
  return status;
 
833
}
 
834
 
 
835
int IBMSSma::switchInfoMad(ibms_mad_msg_t &respMadMsg, ibms_mad_msg_t &reqMadMsg)
 
836
{
 
837
  MSG_ENTER_FUNC;
 
838
 
 
839
  ib_net16_t          status = 0;
 
840
  ib_smp_t*           pRespMad;
 
841
 
 
842
  pRespMad = (ib_smp_t*) &respMadMsg.header;
 
843
 
 
844
  if (reqMadMsg.header.method == IB_MAD_METHOD_GET)
 
845
  {
 
846
    MSGREG(inf2, 'V', "SwitchInfo SubnGet !", "switchInfoMad");
 
847
    MSGSND(inf2);
 
848
  }
 
849
  else
 
850
  {
 
851
    MSGREG(inf3, 'V', "SwitchInfo SubnSet !", "switchInfoMad");
 
852
    MSGSND(inf3);
 
853
    {
 
854
      ib_smp_t*           pReqMad;
 
855
      ib_switch_info_t*   pReqSwitchInfo;
 
856
 
 
857
      pReqMad = (ib_smp_t*) &reqMadMsg.header;
 
858
      pReqSwitchInfo = (ib_switch_info_t*)(pReqMad->data);
 
859
 
 
860
      if (cl_ntoh16(pReqSwitchInfo->lin_top) >= cl_ntoh16(pSimNode->switchInfo.lin_cap))
 
861
      {
 
862
        MSGREG(err0, 'E',
 
863
               "SwitchInfo LFT Cap is $ and lower from req. LFT Top $ !",
 
864
               "switchInfoMad");
 
865
        MSGSND(err0, cl_ntoh16(pSimNode->switchInfo.lin_cap),
 
866
               cl_ntoh16(pReqSwitchInfo->lin_top));
 
867
        status = IB_MAD_STATUS_INVALID_FIELD;
 
868
 
 
869
        MSG_EXIT_FUNC;
 
870
        return status;
 
871
      }
 
872
 
 
873
      pSimNode->switchInfo.lin_top = pReqSwitchInfo->lin_top;
 
874
      pSimNode->switchInfo.def_port = pReqSwitchInfo->def_port;
 
875
      pSimNode->switchInfo.def_mcast_pri_port = pReqSwitchInfo->def_mcast_pri_port;
 
876
      pSimNode->switchInfo.def_mcast_not_port = pReqSwitchInfo->def_mcast_not_port;
 
877
 
 
878
      if (ib_switch_info_get_state_change(pReqSwitchInfo))
 
879
      {
 
880
        ib_switch_info_clear_state_change(pReqSwitchInfo);
 
881
      }
 
882
      else
 
883
      {
 
884
        if (ib_switch_info_get_state_change(&(pSimNode->switchInfo)))
 
885
          ib_switch_info_set_state_change(pReqSwitchInfo);
 
886
      }
 
887
      pSimNode->switchInfo.life_state = pReqSwitchInfo->life_state;
 
888
    }
 
889
  }
 
890
 
 
891
  memcpy (pRespMad->data, &(pSimNode->switchInfo), sizeof(ib_switch_info_t));
 
892
 
 
893
  MSG_EXIT_FUNC;
 
894
  return status;
 
895
}
 
896
 
 
897
int IBMSSma::setPortInfoGeneral(ibms_mad_msg_t &respMadMsg,
 
898
                                ibms_mad_msg_t &reqMadMsg,
 
899
                                uint8_t        inPort,
 
900
                                ib_port_info_t portInfoElm,
 
901
                                int            portNum)
 
902
{
 
903
  MSG_ENTER_FUNC;
 
904
  ib_net16_t          status = 0;
 
905
  ib_smp_t*           pReqMad;
 
906
  ib_port_info_t*     pReqPortInfo;
 
907
  ib_port_info_t*     pNodePortInfo;
 
908
 
 
909
  pReqMad = (ib_smp_t*) &reqMadMsg.header;
 
910
  pReqPortInfo = (ib_port_info_t*)(pReqMad->data);
 
911
  pNodePortInfo = &(pSimNode->nodePortsInfo[portNum]);
 
912
 
 
913
  if (ib_port_info_get_port_state(&portInfoElm) == IB_LINK_DOWN)
 
914
  {
 
915
    MSGREG(err0, 'W', "PortInfo PortState is Down - Port Not connected !", "setPortInfoGeneral");
 
916
    MSGSND(err0);
 
917
    status = IB_MAD_STATUS_INVALID_FIELD;
 
918
 
 
919
    MSG_EXIT_FUNC;
 
920
    return status;
 
921
  }
 
922
 
 
923
  pNodePortInfo->local_port_num = inPort;
 
924
  pNodePortInfo->m_key = pReqPortInfo->m_key;
 
925
  pNodePortInfo->subnet_prefix = pReqPortInfo->subnet_prefix;
 
926
 
 
927
  pNodePortInfo->m_key_lease_period = pReqPortInfo->m_key_lease_period;
 
928
  // TODO: check LinkWidthEnabled parameter from the SM (check very complexed)
 
929
  if (pReqPortInfo->link_width_enabled)
 
930
  {
 
931
    pNodePortInfo->link_width_enabled = pReqPortInfo->link_width_enabled;
 
932
  }
 
933
 
 
934
  {
 
935
    // state_info1 == LinkSpeedSupported and PortState
 
936
    uint8_t newPortState;
 
937
    uint8_t oldPortState;
 
938
 
 
939
    newPortState = ib_port_info_get_port_state(pReqPortInfo);
 
940
    oldPortState = ib_port_info_get_port_state(pNodePortInfo);
 
941
    if (((newPortState == IB_LINK_INIT) || (newPortState >= IB_LINK_ACT_DEFER)) ||
 
942
        ((oldPortState == IB_LINK_DOWN) &&
 
943
         ((newPortState == IB_LINK_ARMED) || (newPortState == IB_LINK_ACTIVE))) ||
 
944
        ((oldPortState == IB_LINK_ARMED) && (newPortState == IB_LINK_ARMED)) ||
 
945
        ((newPortState == IB_LINK_ACTIVE) &&
 
946
         ((oldPortState == IB_LINK_ACTIVE) && (newPortState == IB_LINK_INIT))))
 
947
    {
 
948
      MSGREG(err0, 'E', "PortInfo PortState set for $ from $ is invalid !", "setPortInfoGeneral");
 
949
      MSGSND(err0, newPortState, oldPortState);
 
950
      status = IB_MAD_STATUS_INVALID_FIELD;
 
951
 
 
952
      MSG_EXIT_FUNC;
 
953
      return status;
 
954
    }
 
955
 
 
956
    if (newPortState == IB_LINK_DOWN) newPortState = IB_LINK_INIT;
 
957
    // if all checks passed then set and change required
 
958
    if (newPortState)
 
959
    {
 
960
      ib_port_info_set_port_state(pNodePortInfo, newPortState);
 
961
    }
 
962
  }
 
963
 
 
964
  {   //state_info2 == PortPhysState and LinkDownDefaultState
 
965
    uint8_t newPortPhyState;
 
966
    uint8_t newDefDownPortState;
 
967
 
 
968
    newPortPhyState = ib_port_info_get_port_phys_state(pReqPortInfo);
 
969
    if (newPortPhyState >= 4)
 
970
    {
 
971
      MSGREG(err1, 'E', "PortInfo PortPhyState set for $ (higher or equal to 4) !", "setPortInfoGeneral");
 
972
      MSGSND(err1, newPortPhyState);
 
973
      status = IB_MAD_STATUS_INVALID_FIELD;
 
974
 
 
975
      MSG_EXIT_FUNC;
 
976
      return status;
 
977
    }
 
978
 
 
979
    newDefDownPortState = ib_port_info_get_link_down_def_state(pReqPortInfo);
 
980
    if (newDefDownPortState >= 3)
 
981
    {
 
982
      MSGREG(err2, 'E', "PortInfo LinkDownDefualt State set for $ (higher or equal to 3) !", "setPortInfoGeneral");
 
983
      MSGSND(err2, newDefDownPortState);
 
984
      status = IB_MAD_STATUS_INVALID_FIELD;
 
985
 
 
986
      MSG_EXIT_FUNC;
 
987
      return status;
 
988
    }
 
989
 
 
990
    if (newPortPhyState)
 
991
    {
 
992
      ib_port_info_set_port_phys_state(newPortPhyState, pNodePortInfo);
 
993
    }
 
994
    if (newDefDownPortState)
 
995
    {
 
996
      ib_port_info_set_link_down_def_state(pNodePortInfo, newDefDownPortState);
 
997
    }
 
998
  }   // END state_info2
 
999
 
 
1000
  {   // LinkSpeedEnabled and LinkSpeedActive
 
1001
    uint8_t     linkSpeedEn;
 
1002
 
 
1003
    linkSpeedEn = ib_port_info_get_link_speed_enabled(pReqPortInfo);
 
1004
    if ((linkSpeedEn >= 8) && (linkSpeedEn <= 0xe))
 
1005
    {
 
1006
      MSGREG(err3, 'E', "PortInfo Link speed enabled set for $ (between 0x8 and 0xe) !", "setPortInfoGeneral");
 
1007
      MSGSND(err3, linkSpeedEn);
 
1008
      status = IB_MAD_STATUS_INVALID_FIELD;
 
1009
 
 
1010
      MSG_EXIT_FUNC;
 
1011
      return status;
 
1012
    }
 
1013
    if (linkSpeedEn)
 
1014
    {
 
1015
      ib_port_info_set_link_speed_enabled(pNodePortInfo, linkSpeedEn);
 
1016
    }
 
1017
  }   // END LinkSpeedEnabled and LinkSpeedActive
 
1018
 
 
1019
  pNodePortInfo->vl_high_limit = pReqPortInfo->vl_high_limit;
 
1020
  pNodePortInfo->m_key_violations = pReqPortInfo->m_key_violations;
 
1021
  pNodePortInfo->p_key_violations = pReqPortInfo->p_key_violations;
 
1022
  pNodePortInfo->q_key_violations = pReqPortInfo->q_key_violations;
 
1023
  pNodePortInfo->subnet_timeout = pReqPortInfo->subnet_timeout;
 
1024
  pNodePortInfo->error_threshold = pReqPortInfo->error_threshold;
 
1025
 
 
1026
  MSG_EXIT_FUNC;
 
1027
  return status;
 
1028
}
 
1029
 
 
1030
/* set the IBPort base lid and keep the map of port by lid consistent */
 
1031
int IBMSSma::setIBPortBaseLid(
 
1032
  IBMSNode *pSimNode,
 
1033
  uint8_t   inPortNum,
 
1034
  uint16_t base_lid)
 
1035
{
 
1036
  IBNode*             pNode;
 
1037
  IBPort*             pPort = NULL;
 
1038
  unsigned int        portLidIndex;
 
1039
  unsigned int        minPortNum;
 
1040
  unsigned int        maxPortNum;
 
1041
  MSG_ENTER_FUNC;
 
1042
 
 
1043
  MSGREG(inf0, 'I', "Setting base_lid for node:$ port:$ to $",
 
1044
         "setIBPortBaseLid");
 
1045
  pNode = pSimNode->getIBNode();
 
1046
 
 
1047
  /*
 
1048
     We need a special case for switch port 0 changing
 
1049
     the reason is that there is no IBPort since they are all physical
 
1050
     what we do is to search for port 1 - N and set them properly.
 
1051
     Then we find and change the port by lid table.
 
1052
  */
 
1053
  if (pNode->type == IB_SW_NODE)
 
1054
  {
 
1055
    if (inPortNum == 0)
 
1056
    {
 
1057
      minPortNum = 1;
 
1058
      maxPortNum = pNode->numPorts;
 
1059
    }
 
1060
    else
 
1061
    {
 
1062
      MSGREG(w0, 'W', "Ignoring switch port $ != 0", "setIBPortBaseLid");
 
1063
      MSGSND(w0, inPortNum);
 
1064
      return 0;
 
1065
    }
 
1066
  }
 
1067
  else
 
1068
  {
 
1069
    minPortNum = maxPortNum = inPortNum;
 
1070
  }
 
1071
 
 
1072
  for (unsigned int portNum = minPortNum; portNum <= maxPortNum; portNum++)
 
1073
  {
 
1074
    pPort = pNode->getPort(portNum);
 
1075
    if (! pPort)
 
1076
    {
 
1077
      MSGREG(err9, 'E', "No Port $ on node:$!", "setIBPortBaseLid");
 
1078
      MSGSND(err9, portNum, pNode->name);
 
1079
      return 1;
 
1080
    }
 
1081
 
 
1082
    MSGSND(inf0, pNode->name, portNum, base_lid);
 
1083
 
 
1084
    /* keep track of the previous lid */
 
1085
    uint16_t prevLid = pPort->base_lid;
 
1086
 
 
1087
    /* assign the lid */
 
1088
    pPort->base_lid = base_lid;
 
1089
 
 
1090
    /* make sure the vector of port by lid has enough entries */
 
1091
    if (pNode->p_fabric->PortByLid.size() <= base_lid)
 
1092
    {
 
1093
      /* we add 20 entries each time */
 
1094
      pNode->p_fabric->PortByLid.resize(base_lid+20);
 
1095
      for ( portLidIndex = pNode->p_fabric->PortByLid.size();
 
1096
            portLidIndex < (unsigned int)(base_lid + 20);
 
1097
            portLidIndex++)
 
1098
      {
 
1099
        pNode->p_fabric->PortByLid[portLidIndex] = NULL;
 
1100
      }
 
1101
    }
 
1102
 
 
1103
    /* keep track of the max lid */
 
1104
    if (  pNode->p_fabric->maxLid  < base_lid )
 
1105
      pNode->p_fabric->maxLid = base_lid;
 
1106
 
 
1107
    /* need to cleanup the previous entry */
 
1108
    if (prevLid < pNode->p_fabric->PortByLid.size())
 
1109
      pNode->p_fabric->PortByLid[prevLid] = NULL;
 
1110
 
 
1111
    /* cleanup old base_lid for ports that used to have that lid ... */
 
1112
    IBPort *pPrevPort = pNode->p_fabric->PortByLid[base_lid];
 
1113
    if (pPrevPort && (pPrevPort != pPort))
 
1114
    {
 
1115
      /* for HCAs we can not have two ports pointing at the same lid */
 
1116
      /* for switches - it must be the same switch ... */
 
1117
      if ((pNode->type != IB_SW_NODE) || (pPrevPort->p_node != pNode))
 
1118
        pPrevPort->base_lid = 0;
 
1119
    }
 
1120
 
 
1121
  }
 
1122
 
 
1123
  /* now set the new port by lid */
 
1124
  pNode->p_fabric->PortByLid[base_lid] = pPort;
 
1125
 
 
1126
  MSG_EXIT_FUNC;
 
1127
  return 0;
 
1128
}
 
1129
 
 
1130
int IBMSSma::setPortInfoSwBasePort(ibms_mad_msg_t &respMadMsg,
 
1131
                                   ibms_mad_msg_t &reqMadMsg,
 
1132
                                   uint8_t        inPort,
 
1133
                                   ib_port_info_t portInfoElm,
 
1134
                                   int            portNum)
 
1135
{
 
1136
  MSG_ENTER_FUNC;
 
1137
  ib_net16_t          status = 0;
 
1138
  ib_smp_t*           pReqMad;
 
1139
  ib_port_info_t*     pReqPortInfo;
 
1140
  ib_port_info_t*     pNodePortInfo;
 
1141
 
 
1142
 
 
1143
  pReqMad = (ib_smp_t*) &reqMadMsg.header;
 
1144
  pReqPortInfo = (ib_port_info_t*)(pReqMad->data);
 
1145
  pNodePortInfo = &(pSimNode->nodePortsInfo[portNum]);
 
1146
 
 
1147
  if ((pReqPortInfo->base_lid == 0) || (cl_ntoh16(pReqPortInfo->base_lid) >= 0xbfff))
 
1148
  {
 
1149
    MSGREG(err6, 'E', "PortInfo Invalid Lid set to $ on SW Base port!", "setPortInfoSwBasePort");
 
1150
    MSGSND(err6, pReqPortInfo->base_lid);
 
1151
    status = IB_MAD_STATUS_INVALID_FIELD;
 
1152
 
 
1153
    MSG_EXIT_FUNC;
 
1154
    return status;
 
1155
  }
 
1156
  else
 
1157
  {
 
1158
    /* need to update the IBPort base lid on a change */
 
1159
    if (pNodePortInfo->base_lid != pReqPortInfo->base_lid)
 
1160
    {
 
1161
      setIBPortBaseLid(pSimNode, portNum, cl_ntoh16(pReqPortInfo->base_lid));
 
1162
      pNodePortInfo->base_lid = pReqPortInfo->base_lid;
 
1163
    }
 
1164
    else
 
1165
    {
 
1166
        MSGREG(inf1, 'V', "Lid does not require change by the SubnSet !", "setPortInfoSwBasePort");
 
1167
        MSGSND(inf1);
 
1168
    }
 
1169
 
 
1170
  }
 
1171
 
 
1172
  if ((pReqPortInfo->master_sm_base_lid == 0) || (cl_ntoh16(pReqPortInfo->master_sm_base_lid) >= 0xbfff))
 
1173
  {
 
1174
    MSGREG(err5, 'E', "PortInfo Invalid master SM Lid set for $ !", "setPortInfoSwBasePort");
 
1175
    MSGSND(err5, pReqPortInfo->master_sm_base_lid);
 
1176
    status = IB_MAD_STATUS_INVALID_FIELD;
 
1177
 
 
1178
    MSG_EXIT_FUNC;
 
1179
    return status;
 
1180
  }
 
1181
  else pNodePortInfo->master_sm_base_lid = pReqPortInfo->master_sm_base_lid;
 
1182
 
 
1183
  {
 
1184
    uint8_t  reqLmc;
 
1185
    uint8_t  mKeyProtectBits;
 
1186
 
 
1187
    reqLmc = ib_port_info_get_lmc(pReqPortInfo);
 
1188
    if (reqLmc != 0)
 
1189
    {
 
1190
      MSGREG(err3, 'E', "Base Port0 PortInfo LMC set for $ (must be 0) !", "setPortInfoSwBasePort");
 
1191
      MSGSND(err3, reqLmc);
 
1192
      status = IB_MAD_STATUS_INVALID_FIELD;
 
1193
 
 
1194
      MSG_EXIT_FUNC;
 
1195
      return status;
 
1196
    }
 
1197
    ib_port_info_set_lmc(pNodePortInfo, 0);
 
1198
 
 
1199
    mKeyProtectBits = ib_port_info_get_mpb(pReqPortInfo);
 
1200
    ib_port_info_set_mpb(pNodePortInfo, mKeyProtectBits);
 
1201
  }
 
1202
 
 
1203
  {
 
1204
    uint8_t     masterSmSl;
 
1205
 
 
1206
    masterSmSl = ib_port_info_get_smsl(pReqPortInfo);
 
1207
    ib_port_info_set_smsl(pNodePortInfo, masterSmSl);
 
1208
  }
 
1209
 
 
1210
  MSG_EXIT_FUNC;
 
1211
  return status;
 
1212
}
 
1213
 
 
1214
int IBMSSma::setPortInfoSwExtPort(ibms_mad_msg_t &respMadMsg,
 
1215
                                  ibms_mad_msg_t &reqMadMsg,
 
1216
                                  uint8_t        inPort,
 
1217
                                  ib_port_info_t portInfoElm,
 
1218
                                  int            portNum)
 
1219
{
 
1220
  MSG_ENTER_FUNC;
 
1221
  ib_net16_t          status = 0;
 
1222
  ib_smp_t*           pReqMad;
 
1223
  ib_port_info_t*     pReqPortInfo;
 
1224
  ib_port_info_t*     pNodePortInfo;
 
1225
 
 
1226
  pReqMad = (ib_smp_t*) &reqMadMsg.header;
 
1227
  pReqPortInfo = (ib_port_info_t*)(pReqMad->data);
 
1228
  pNodePortInfo = &(pSimNode->nodePortsInfo[portNum]);
 
1229
 
 
1230
  {
 
1231
    uint8_t     nMtuReq;
 
1232
    uint8_t     mtuCap;
 
1233
 
 
1234
    nMtuReq = ib_port_info_get_neighbor_mtu(pReqPortInfo);
 
1235
    mtuCap = ib_port_info_get_mtu_cap(pNodePortInfo);
 
1236
    if ((nMtuReq == 0) || (nMtuReq > 5) || (nMtuReq > mtuCap))
 
1237
    {
 
1238
      MSGREG(err4, 'E', "PortInfo N - MTU set for $ with MTU Cap $ !", "setPortInfoSwExtPort");
 
1239
      MSGSND(err4, nMtuReq, mtuCap);
 
1240
      status = IB_MAD_STATUS_INVALID_FIELD;
 
1241
 
 
1242
      MSG_EXIT_FUNC;
 
1243
      return status;
 
1244
    }
 
1245
    ib_port_info_set_neighbor_mtu(pNodePortInfo, nMtuReq);
 
1246
  }
 
1247
 
 
1248
  pNodePortInfo->vl_stall_life = pReqPortInfo->vl_stall_life;
 
1249
 
 
1250
  {
 
1251
    uint8_t     reqOpVl;
 
1252
    uint8_t     vlCap;
 
1253
 
 
1254
    reqOpVl = ib_port_info_get_op_vls(pReqPortInfo);
 
1255
    vlCap = ib_port_info_get_vl_cap(pNodePortInfo);
 
1256
 
 
1257
    if ((reqOpVl > vlCap) || (reqOpVl > 5))
 
1258
    {
 
1259
      MSGREG(err5, 'E', "PortInfo Operational VL set for $ with VL Cap $ !", "setPortInfoSwExtPort");
 
1260
      MSGSND(err5, reqOpVl, vlCap);
 
1261
      status = IB_MAD_STATUS_INVALID_FIELD;
 
1262
 
 
1263
      MSG_EXIT_FUNC;
 
1264
      return status;
 
1265
    }
 
1266
    if (reqOpVl) ib_port_info_set_op_vls(pNodePortInfo, reqOpVl);
 
1267
  }
 
1268
 
 
1269
  // TODO check if legal
 
1270
  pNodePortInfo->vl_enforce =
 
1271
         pNodePortInfo->vl_enforce & 0xf0 | pReqPortInfo->vl_enforce & 0xf;
 
1272
 
 
1273
  MSG_EXIT_FUNC;
 
1274
  return status;
 
1275
}
 
1276
 
 
1277
int IBMSSma::setPortInfoHca(ibms_mad_msg_t &respMadMsg,
 
1278
                            ibms_mad_msg_t &reqMadMsg,
 
1279
                            uint8_t        inPort,
 
1280
                            ib_port_info_t portInfoElm,
 
1281
                            int            portNum)
 
1282
{
 
1283
  MSG_ENTER_FUNC;
 
1284
  ib_net16_t          status = 0;
 
1285
  ib_smp_t*           pReqMad;
 
1286
  ib_port_info_t*     pReqPortInfo;
 
1287
  ib_port_info_t*     pNodePortInfo;
 
1288
 
 
1289
  pReqMad = (ib_smp_t*) &reqMadMsg.header;
 
1290
  pReqPortInfo = (ib_port_info_t*)(pReqMad->data);
 
1291
  pNodePortInfo = &(pSimNode->nodePortsInfo[portNum]);
 
1292
 
 
1293
  if ((pReqPortInfo->base_lid == 0) || (cl_ntoh16(pReqPortInfo->base_lid) >= 0xbfff))
 
1294
  {
 
1295
    MSGREG(err6, 'E', "PortInfo Invalid Lid set to $ on HCA!", "setPortInfoHca");
 
1296
    MSGSND(err6, pReqPortInfo->base_lid);
 
1297
    status = IB_MAD_STATUS_INVALID_FIELD;
 
1298
 
 
1299
    MSG_EXIT_FUNC;
 
1300
    return status;
 
1301
  }
 
1302
  else
 
1303
  {
 
1304
    if (pNodePortInfo->base_lid != pReqPortInfo->base_lid)
 
1305
    {
 
1306
      setIBPortBaseLid(pSimNode, portNum, cl_ntoh16(pReqPortInfo->base_lid));
 
1307
      pNodePortInfo->base_lid = pReqPortInfo->base_lid;
 
1308
    }
 
1309
    else
 
1310
    {
 
1311
      MSGREG(inf1, 'V', "Lid does not require change by the SubnSet !", "setPortInfoHca");
 
1312
        MSGSND(inf1);
 
1313
    }
 
1314
  }
 
1315
 
 
1316
  if ((pReqPortInfo->master_sm_base_lid == 0) || (cl_ntoh16(pReqPortInfo->master_sm_base_lid) >= 0xbfff))
 
1317
  {
 
1318
    MSGREG(err5, 'E', "PortInfo Invalid master SM Lid set for $ !", "setPortInfoHca");
 
1319
    MSGSND(err5, pReqPortInfo->master_sm_base_lid);
 
1320
    status = IB_MAD_STATUS_INVALID_FIELD;
 
1321
 
 
1322
    MSG_EXIT_FUNC;
 
1323
    return status;
 
1324
  }
 
1325
  else pNodePortInfo->master_sm_base_lid = pReqPortInfo->master_sm_base_lid;
 
1326
 
 
1327
  {
 
1328
    uint8_t  reqLmc;
 
1329
    uint8_t  mKeyProtectBits;
 
1330
 
 
1331
    reqLmc = ib_port_info_get_lmc(pReqPortInfo);
 
1332
    ib_port_info_set_lmc(pNodePortInfo, reqLmc);
 
1333
    mKeyProtectBits = ib_port_info_get_mpb(pReqPortInfo);
 
1334
    ib_port_info_set_mpb(pNodePortInfo, mKeyProtectBits);
 
1335
  }
 
1336
 
 
1337
  {
 
1338
    uint8_t     nMtuReq;
 
1339
    uint8_t     mtuCap;
 
1340
    uint8_t     masterSmSl;
 
1341
 
 
1342
    nMtuReq = ib_port_info_get_neighbor_mtu(pReqPortInfo);
 
1343
    mtuCap = ib_port_info_get_mtu_cap(pNodePortInfo);
 
1344
    if ((nMtuReq == 0) || (nMtuReq > 5) || (nMtuReq > mtuCap))
 
1345
    {
 
1346
      MSGREG(err4, 'E', "PortInfo N - MTU set for $ with MTU Cap $ !", "setPortInfoHca");
 
1347
      MSGSND(err4, nMtuReq, mtuCap);
 
1348
      status = IB_MAD_STATUS_INVALID_FIELD;
 
1349
 
 
1350
      MSG_EXIT_FUNC;
 
1351
      return status;
 
1352
    }
 
1353
    ib_port_info_set_neighbor_mtu(pNodePortInfo, nMtuReq);
 
1354
    masterSmSl = ib_port_info_get_smsl(pReqPortInfo);
 
1355
    ib_port_info_set_smsl(pNodePortInfo, masterSmSl);
 
1356
  }
 
1357
 
 
1358
  {
 
1359
    uint8_t     reqOpVl;
 
1360
    uint8_t     vlCap;
 
1361
 
 
1362
    reqOpVl = ib_port_info_get_op_vls(pReqPortInfo);
 
1363
    vlCap = ib_port_info_get_vl_cap(pNodePortInfo);
 
1364
 
 
1365
    if ((reqOpVl > vlCap) || (reqOpVl > 5))
 
1366
    {
 
1367
      MSGREG(err5, 'E', "PortInfo Operational VL set for $ with VL Cap $ !", "setPortInfoHca");
 
1368
      MSGSND(err5, reqOpVl, vlCap);
 
1369
      status = IB_MAD_STATUS_INVALID_FIELD;
 
1370
 
 
1371
      MSG_EXIT_FUNC;
 
1372
      return status;
 
1373
    }
 
1374
    if (reqOpVl) ib_port_info_set_op_vls(pNodePortInfo, reqOpVl);
 
1375
  }
 
1376
 
 
1377
  MSG_EXIT_FUNC;
 
1378
  return status;
 
1379
}
 
1380
 
 
1381
int IBMSSma::setPortInfo(ibms_mad_msg_t &respMadMsg,
 
1382
                         ibms_mad_msg_t &reqMadMsg,
 
1383
                         uint8_t        inPort,
 
1384
                         ib_port_info_t portInfoElm,
 
1385
                         int            portNum)
 
1386
{
 
1387
  MSG_ENTER_FUNC;
 
1388
  ib_net16_t          status = 0;
 
1389
 
 
1390
  status = setPortInfoGeneral(respMadMsg, reqMadMsg, inPort, portInfoElm, portNum);
 
1391
  if (status)
 
1392
  {
 
1393
    MSGREG(err0, 'E', "PortInfo failed in setPortInfoGeneral !", "setPortInfo");
 
1394
    MSGSND(err0);
 
1395
    MSG_EXIT_FUNC;
 
1396
    return status;
 
1397
  }
 
1398
 
 
1399
  if (pSimNode->nodeInfo.node_type == IB_NODE_TYPE_SWITCH)
 
1400
  {
 
1401
    //Handling a switch port
 
1402
    //TODO add different handling for: Enhanced Port0
 
1403
    //MSGREG(inf4, 'V', "PortInfo SubnSet of Switch Enhanced Port0 !", "setPortInfo");
 
1404
    //MSGSND(inf4);
 
1405
 
 
1406
    //  2) Base Port0
 
1407
    if (portNum == 0)
 
1408
    {
 
1409
      status = setPortInfoSwBasePort(respMadMsg, reqMadMsg, inPort, portInfoElm, portNum);
 
1410
    }
 
1411
    else
 
1412
    { //  3) External ports
 
1413
      status = setPortInfoSwExtPort(respMadMsg, reqMadMsg, inPort, portInfoElm, portNum);
 
1414
    }
 
1415
  }
 
1416
  else
 
1417
  {   //Handling an HCA port
 
1418
    status = setPortInfoHca(respMadMsg, reqMadMsg, inPort, portInfoElm, portNum);
 
1419
  }
 
1420
  if (status)
 
1421
  {
 
1422
    MSGREG(err1, 'E', "PortInfo failed in Node specific area !", "setPortInfo");
 
1423
    MSGSND(err1);
 
1424
    MSG_EXIT_FUNC;
 
1425
    return status;
 
1426
  }
 
1427
  {
 
1428
    ib_smp_t*           pRespMad;
 
1429
    ib_port_info_t*     pNodePortInfo;
 
1430
 
 
1431
    pRespMad = (ib_smp_t*) &respMadMsg.header;
 
1432
    pNodePortInfo = &(pSimNode->nodePortsInfo[portNum]);
 
1433
    memcpy (pRespMad->data, pNodePortInfo, sizeof(portInfoElm));
 
1434
  }
 
1435
 
 
1436
  MSG_EXIT_FUNC;
 
1437
  return status;
 
1438
}
 
1439
 
 
1440
int IBMSSma::portInfoMad(ibms_mad_msg_t &respMadMsg, ibms_mad_msg_t &reqMadMsg, uint8_t inPort)
 
1441
{
 
1442
  MSG_ENTER_FUNC;
 
1443
 
 
1444
  int                 portNum;
 
1445
  ib_net16_t          status = 0;
 
1446
  ib_port_info_t      portInfoElm;
 
1447
 
 
1448
  portNum = cl_ntoh32(reqMadMsg.header.attr_mod);
 
1449
  //non existing port of the device
 
1450
  if (portNum > pSimNode->nodeInfo.num_ports)
 
1451
  {
 
1452
    MSGREG(err0, 'E', "PortInfo request for non-existing port", "portInfoMad");
 
1453
    MSGSND(err0);
 
1454
    status = IB_MAD_STATUS_INVALID_FIELD;
 
1455
 
 
1456
    MSG_EXIT_FUNC;
 
1457
    return status;
 
1458
  }
 
1459
 
 
1460
  //for HCAs if AM is 0 then handling the port that received the mad
 
1461
  if ((pSimNode->nodeInfo.node_type == IB_NODE_TYPE_CA) && (portNum == 0))
 
1462
  {
 
1463
    portNum = inPort;
 
1464
  }
 
1465
 
 
1466
  portInfoElm = pSimNode->nodePortsInfo[portNum];
 
1467
  if (reqMadMsg.header.method == IB_MAD_METHOD_GET)
 
1468
  {
 
1469
    MSGREG(inf2, 'V', "PortInfo SubnGet !", "portInfoMad");
 
1470
    MSGSND(inf2);
 
1471
    {
 
1472
      ib_smp_t*           pRespMad;
 
1473
      pRespMad = (ib_smp_t*) &respMadMsg.header;
 
1474
 
 
1475
      portInfoElm.local_port_num = inPort;
 
1476
      memcpy (pRespMad->data, &(portInfoElm), sizeof(portInfoElm));
 
1477
    }
 
1478
  }
 
1479
  else
 
1480
  {
 
1481
    status = setPortInfo(respMadMsg, reqMadMsg, inPort, portInfoElm, portNum);
 
1482
  }
 
1483
 
 
1484
  MSG_EXIT_FUNC;
 
1485
  return status;
 
1486
}
 
1487
 
 
1488
int IBMSSma::pKeyMad(ibms_mad_msg_t &respMadMsg, ibms_mad_msg_t &reqMadMsg, uint8_t inPort)
 
1489
{
 
1490
  MSG_ENTER_FUNC;
 
1491
 
 
1492
  ib_smp_t*           pRespMad;
 
1493
  ib_smp_t*           pReqMad;
 
1494
  ib_net16_t          status = 0;
 
1495
  ib_pkey_table_t     PKeyBlockElem;
 
1496
  ib_pkey_table_t*    pPkeyBlockElem;
 
1497
  int                 portNum=0;
 
1498
  int                 PKeyBlockNum=0;
 
1499
 
 
1500
  if (pSimNode->nodeInfo.node_type == IB_NODE_TYPE_CA)
 
1501
  {
 
1502
    //HCA
 
1503
    portNum = inPort;
 
1504
    if (portNum == 0) portNum = 1;
 
1505
 
 
1506
  }
 
1507
  else if (pSimNode->nodeInfo.node_type == IB_NODE_TYPE_SWITCH)
 
1508
  {   //Switch
 
1509
    portNum = cl_ntoh32(reqMadMsg.header.attr_mod) >> 16;
 
1510
  }
 
1511
  PKeyBlockNum = cl_ntoh32(reqMadMsg.header.attr_mod) & 0xffff;
 
1512
  MSGREG(inf2, 'V', "Partition Key block number $ on port $ !", "pKeyMad");
 
1513
  MSGSND(inf2, PKeyBlockNum, portNum);
 
1514
 
 
1515
  if (PKeyBlockNum > (cl_ntoh16(pSimNode->nodeInfo.partition_cap) / 32))
 
1516
  {
 
1517
    MSGREG(err0, 'E', "Partition Key block number $ is un-supported limited to $ blocks !", "pKeyMad");
 
1518
    MSGSND(err0, PKeyBlockNum, (cl_ntoh16(pSimNode->nodeInfo.partition_cap) / 32));
 
1519
    status = IB_MAD_STATUS_INVALID_FIELD;
 
1520
 
 
1521
    MSG_EXIT_FUNC;
 
1522
    return status;
 
1523
  }
 
1524
  //TODO add P_Key size check for external ports of a switch (in SwitchInfo structure)
 
1525
 
 
1526
  pRespMad = (ib_smp_t*) &respMadMsg.header;
 
1527
  pReqMad = (ib_smp_t*) &reqMadMsg.header;
 
1528
  if (reqMadMsg.header.method == IB_MAD_METHOD_GET)
 
1529
  {
 
1530
    MSGREG(inf3, 'V', "Partition Key SubnGet !", "pKeyMad");
 
1531
    MSGSND(inf3);
 
1532
 
 
1533
    PKeyBlockElem = (pSimNode->nodePortPKeyTable[portNum])[PKeyBlockNum];
 
1534
    memcpy ((void*)(pRespMad->data), (void*)(&PKeyBlockElem), sizeof(ib_pkey_table_t));
 
1535
  }
 
1536
  else
 
1537
  {
 
1538
    MSGREG(inf4, 'V', "Partition Key SubnSet !", "pKeyMad");
 
1539
    MSGSND(inf4);
 
1540
 
 
1541
    pPkeyBlockElem = &(pSimNode->nodePortPKeyTable[portNum])[PKeyBlockNum];
 
1542
    memcpy ((void*)(pPkeyBlockElem), (void*)(pReqMad->data), sizeof(ib_pkey_table_t));
 
1543
    memcpy ((void*)(pRespMad->data), (void*)(pReqMad->data), sizeof(ib_pkey_table_t));
 
1544
  }
 
1545
 
 
1546
  MSG_EXIT_FUNC;
 
1547
  return status;
 
1548
}
 
1549
 
 
1550
int IBMSSma::madValidation(ibms_mad_msg_t &madMsg)
 
1551
{
 
1552
  MSG_ENTER_FUNC;
 
1553
 
 
1554
  ib_net16_t          status = 0;
 
1555
 
 
1556
  // we handle Get or Set or trap repress
 
1557
  if ((madMsg.header.method != IB_MAD_METHOD_GET) &&
 
1558
      (madMsg.header.method != IB_MAD_METHOD_SET) &&
 
1559
      (madMsg.header.method != IB_MAD_METHOD_TRAP_REPRESS))
 
1560
  {
 
1561
    MSGREG(wrn0, 'W', "We are not handling getResp Method.", "madValidation");
 
1562
    MSGSND(wrn0);
 
1563
    status = IB_MAD_STATUS_INVALID_FIELD;
 
1564
 
 
1565
    MSG_EXIT_FUNC;
 
1566
    return status;
 
1567
  }
 
1568
 
 
1569
  ibms_dump_mad( madMsg, RCV);
 
1570
 
 
1571
  MSG_EXIT_FUNC;
 
1572
  return status;
 
1573
}
 
1574
 
 
1575
int IBMSSma::processMad(uint8_t inPort, ibms_mad_msg_t &madMsg)
 
1576
{
 
1577
 
 
1578
  MSG_ENTER_FUNC;
 
1579
 
 
1580
  ibms_mad_msg_t      respMadMsg;
 
1581
  ib_net16_t          status = 0;
 
1582
  uint16_t            attributeId = 0;
 
1583
 
 
1584
  //1. Verify rcv MAD validity.
 
1585
  status = madValidation(madMsg);
 
1586
  if (status != 0)
 
1587
  {
 
1588
    //TODO need to do it more cleanly
 
1589
    MSG_EXIT_FUNC;
 
1590
    return status;
 
1591
  }
 
1592
 
 
1593
  if (madMsg.header.method == IB_MAD_METHOD_TRAP_REPRESS)
 
1594
  {
 
1595
    MSGREG(inf0, 'I', "--- Received Trap Repress ---", "processMad");
 
1596
    MSGSND(inf0);
 
1597
 
 
1598
    MSG_EXIT_FUNC;
 
1599
    return status;
 
1600
  }
 
1601
 
 
1602
  //2. Switch according to the attribute to the mad handle
 
1603
  //      and call appropriate function
 
1604
  MSGREG(inf1, 'I', "Process Mad got the following attribute: $ !", "processMad");
 
1605
  MSGSND(inf1, cl_ntoh16(madMsg.header.attr_id));
 
1606
  attributeId = madMsg.header.attr_id;
 
1607
 
 
1608
  // copy header from request to the response
 
1609
  {
 
1610
    ib_smp_t*   pRespSmp = (ib_smp_t*)(&respMadMsg.header);
 
1611
    ib_smp_t*   pReqSmp = (ib_smp_t*)(&madMsg.header);
 
1612
    memcpy(pRespSmp, pReqSmp, sizeof(ib_smp_t));
 
1613
  }
 
1614
 
 
1615
  // perform m_key check
 
1616
  unsigned mPort = inPort;
 
1617
  if (pSimNode->nodeInfo.node_type == IB_NODE_TYPE_SWITCH)
 
1618
    mPort = 0;
 
1619
 
 
1620
  ib_net64_t m_key1 = ((ib_smp_t*)(&madMsg.header))->m_key;
 
1621
 
 
1622
  pthread_mutex_lock(&vPT[mPort].mut);
 
1623
  ib_net64_t m_key2 = vPT[mPort].pInfo->m_key;
 
1624
 
 
1625
  MSGREG(inf21, 'I', "Mkeys current: $, received: $!", "processMad");
 
1626
  MSGSND(inf21, cl_ntoh64(m_key2), cl_ntoh64(m_key1));
 
1627
 
 
1628
  if (m_key2 && (m_key1 != m_key2) && madMsg.header.method == IB_MAD_METHOD_SET) {
 
1629
    MSGREG(inf22, 'I', "Mkeys mismatch!", "processMad");
 
1630
    MSGSND(inf22);
 
1631
 
 
1632
    // Timer already running
 
1633
    if (vPT[mPort].timerOn) {
 
1634
      MSGREG(inf2, 'I', "Timer already on, counter: $!", "processMad");
 
1635
      MSGSND(inf2,vPT[mPort].counter);
 
1636
 
 
1637
      MSG_EXIT_FUNC;
 
1638
      pthread_mutex_unlock(&vPT[mPort].mut);
 
1639
      return 0;
 
1640
    }
 
1641
    // Start the timer
 
1642
    else {
 
1643
      vPT[mPort].counter = cl_ntoh16(vPT[mPort].pInfo->m_key_lease_period);
 
1644
      vPT[mPort].timerOn = 1;
 
1645
      reg_t tmp;
 
1646
      tmp.f = cbMkey;
 
1647
      tmp.data = &vPT[mPort];
 
1648
 
 
1649
      MSGREG(inf2, 'I', "Starting timer with counter $!", "processMad");
 
1650
      MSGSND(inf2,vPT[mPort].counter);
 
1651
 
 
1652
      pthread_mutex_unlock(&vPT[mPort].mut);
 
1653
      mkeyTimer.reg(tmp);
 
1654
 
 
1655
 
 
1656
      MSG_EXIT_FUNC;
 
1657
 
 
1658
      return 0;
 
1659
    }
 
1660
  }
 
1661
 
 
1662
  if ((m_key1 == m_key2) && (vPT[mPort].timerOn)) {
 
1663
    MSGREG(inf2, 'I', "Stopping timer!", "processMad");
 
1664
    MSGSND(inf2);
 
1665
 
 
1666
    vPT[mPort].timerOn = 0;
 
1667
    pthread_mutex_unlock(&vPT[mPort].mut);
 
1668
    mkeyTimer.unreg(&vPT[mPort]);
 
1669
  }
 
1670
 
 
1671
  pthread_mutex_unlock(&vPT[mPort].mut);
 
1672
 
 
1673
  switch (attributeId) {
 
1674
  case IB_MAD_ATTR_NODE_DESC:
 
1675
    MSGREG(inf5, 'I', "Attribute being handled is $ !", "processMad");
 
1676
    MSGSND(inf5, CL_NTOH16(IB_MAD_ATTR_NODE_DESC));
 
1677
    if (madMsg.header.method != IB_MAD_METHOD_GET)
 
1678
    {
 
1679
      MSGREG(err6, 'E', "NodeDescription was sent with Method other then Get !", "sma");
 
1680
      MSGSND(err6);
 
1681
 
 
1682
      MSG_EXIT_FUNC;
 
1683
      return IB_MAD_STATUS_UNSUP_METHOD_ATTR;
 
1684
    }
 
1685
 
 
1686
    status = nodeDescMad(respMadMsg);
 
1687
    break;
 
1688
  case IB_MAD_ATTR_NODE_INFO:
 
1689
    MSGREG(inf4, 'I', "Attribute being handled is $ !", "processMad");
 
1690
    MSGSND(inf4, CL_NTOH16(IB_MAD_ATTR_NODE_INFO));
 
1691
    if (madMsg.header.method != IB_MAD_METHOD_GET)
 
1692
    {
 
1693
      MSGREG(err2, 'E', "NodeInfo was sent with Method other then Get !", "sma");
 
1694
      MSGSND(err2);
 
1695
 
 
1696
      MSG_EXIT_FUNC;
 
1697
      return IB_MAD_STATUS_UNSUP_METHOD_ATTR;
 
1698
    }
 
1699
 
 
1700
    status = nodeInfoMad(respMadMsg, inPort);
 
1701
    break;
 
1702
  case IB_MAD_ATTR_PORT_INFO:
 
1703
    MSGREG(inf6, 'I', "Attribute being handled is $ !", "processMad");
 
1704
    MSGSND(inf6, CL_NTOH16(IB_MAD_ATTR_PORT_INFO));
 
1705
 
 
1706
    status = portInfoMad(respMadMsg, madMsg, inPort);
 
1707
    break;
 
1708
  case IB_MAD_ATTR_P_KEY_TABLE:
 
1709
    MSGREG(inf7, 'I', "Attribute being handled is $ !", "processMad");
 
1710
    MSGSND(inf7, CL_NTOH16(IB_MAD_ATTR_P_KEY_TABLE));
 
1711
 
 
1712
    status = pKeyMad(respMadMsg, madMsg, inPort);
 
1713
    break;
 
1714
  case IB_MAD_ATTR_SWITCH_INFO:
 
1715
    MSGREG(inf8, 'I', "Attribute being handled is $ !", "processMad");
 
1716
    MSGSND(inf8, CL_NTOH16(IB_MAD_ATTR_SWITCH_INFO));
 
1717
 
 
1718
    status = switchInfoMad(respMadMsg, madMsg);
 
1719
    break;
 
1720
  case IB_MAD_ATTR_LIN_FWD_TBL:
 
1721
    MSGREG(inf9, 'I', "Attribute being handled is $ !", "processMad");
 
1722
    MSGSND(inf9, CL_NTOH16(IB_MAD_ATTR_LIN_FWD_TBL));
 
1723
 
 
1724
    status = lftMad(respMadMsg, madMsg);
 
1725
    break;
 
1726
  case IB_MAD_ATTR_MCAST_FWD_TBL:
 
1727
    MSGREG(inf10, 'I', "Attribute being handled is $ !", "processMad");
 
1728
    MSGSND(inf10, CL_NTOH16(IB_MAD_ATTR_MCAST_FWD_TBL));
 
1729
 
 
1730
    status = mftMad(respMadMsg, madMsg);
 
1731
    break;
 
1732
  case IB_MAD_ATTR_SLVL_TABLE:
 
1733
    MSGREG(inf11, 'I', "Attribute being handled is $ !", "processMad");
 
1734
    MSGSND(inf11, CL_NTOH16(IB_MAD_ATTR_SLVL_TABLE));
 
1735
 
 
1736
    status = sl2VlMad(respMadMsg, madMsg, inPort);
 
1737
    break;
 
1738
  case IB_MAD_ATTR_VL_ARBITRATION:
 
1739
    MSGREG(inf12, 'I', "Attribute being handled is $ !", "processMad");
 
1740
    MSGSND(inf12, CL_NTOH16(IB_MAD_ATTR_VL_ARBITRATION));
 
1741
 
 
1742
    status = vlArbMad(respMadMsg, madMsg, inPort);
 
1743
    break;
 
1744
  default:
 
1745
    MSGREG(err1, 'E', "No handler for requested attribute:$", "processMad");
 
1746
    MSGSND(err1, cl_ntoh16(attributeId));
 
1747
    status = IB_MAD_STATUS_UNSUP_METHOD_ATTR;
 
1748
 
 
1749
    //TODO need to do it more cleanly
 
1750
    MSG_EXIT_FUNC;
 
1751
    return status;
 
1752
    break;
 
1753
  }
 
1754
 
 
1755
  //ib_mad_init_response( respMadMsg, respMadMsg, status);
 
1756
  {
 
1757
    ib_smp_t*   pRespSmp = (ib_smp_t*)(&respMadMsg.header);
 
1758
    ib_smp_t*   pReqSmp = (ib_smp_t*)(&madMsg.header);
 
1759
 
 
1760
    respMadMsg.addr = madMsg.addr;
 
1761
    respMadMsg.addr.slid = madMsg.addr.dlid;
 
1762
    respMadMsg.addr.dlid = madMsg.addr.slid;
 
1763
    if (respMadMsg.header.method == IB_MAD_METHOD_SET)
 
1764
    {
 
1765
      respMadMsg.header.method = IB_MAD_METHOD_GET_RESP;
 
1766
    }
 
1767
    else respMadMsg.header.method |= IB_MAD_METHOD_RESP_MASK;
 
1768
    //only if direct then set D-bit
 
1769
    if (respMadMsg.header.mgmt_class == 0x81)
 
1770
    {
 
1771
      respMadMsg.header.status = status | IB_SMP_DIRECTION;
 
1772
    }
 
1773
    pRespSmp->dr_slid = pReqSmp->dr_dlid;
 
1774
    pRespSmp->dr_dlid = pReqSmp->dr_slid;
 
1775
  }
 
1776
 
 
1777
  //send response
 
1778
  ibms_dump_mad( respMadMsg, SND);
 
1779
  pSimNode->getSim()->getDispatcher()->dispatchMad(pSimNode, inPort,
 
1780
                                                   respMadMsg);
 
1781
 
 
1782
  MSG_EXIT_FUNC;
 
1783
  return status;
 
1784
}