DABC (Data Acquisition Backbone Core)  2.9.9
OpenSM.cxx
Go to the documentation of this file.
1 /************************************************************
2  * The Data Acquisition Backbone Core (DABC) *
3  ************************************************************
4  * Copyright (C) 2009 - *
5  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
6  * Planckstr. 1, 64291 Darmstadt, Germany *
7  * Contact: http://dabc.gsi.de *
8  ************************************************************
9  * This software can be used under the GPL license *
10  * agreements as stated in LICENSE.txt file *
11  * which is part of the distribution. *
12  ************************************************************/
13 
14 #include "verbs/OpenSM.h"
15 
16 #include <infiniband/opensm/osm_helper.h>
17 
18 #include "dabc/logging.h"
19 #include "verbs/QueuePair.h"
20 
21 
22 ib_gid_t TOsm_good_mgid = {
23  {
24  0xFF, 0x12, 0xA0, 0x1C,
25  0xFE, 0x80, 0x00, 0x00,
26  0x00, 0x00, 0x00, 0x00,
27  0x88, 0x99, 0xaa, 0xbb
28  }
29  };
30 
31 /*
32 
33 int ibv_sa_init_ah_from_mcmember(
34  struct ibv_context *device,
35  uint8_t port_num,
36  struct ibv_sa_net_mcmember_rec *mc_rec,
37  struct ibv_ah_attr *ah_attr)
38 {
39  struct ibv_sa_mcmember_rec rec;
40  int ret;
41 
42  ibv_sa_unpack_mcmember_rec(&rec, mc_rec);
43 
44  ret = get_gid_index(device, port_num, &rec.port_gid);
45  if (ret < 0)
46  return ret;
47 
48  memset(ah_attr, 0, sizeof *ah_attr);
49  ah_attr->dlid = ntohs(rec.mlid);
50  ah_attr->sl = rec.sl;
51  ah_attr->port_num = port_num;
52  ah_attr->static_rate = rec.rate;
53 
54  ah_attr->is_global = 1;
55  ah_attr->grh.dgid = rec.mgid;
56 
57  ah_attr->grh.sgid_index = (uint8_t) ret;
58  ah_attr->grh.flow_label = ntohl(rec.flow_label);
59  ah_attr->grh.hop_limit = rec.hop_limit;
60  ah_attr->grh.traffic_class = rec.traffic_class;
61  return 0;
62 }
63 
64 */
65 
66 
67 void TOsm_query_callback(osmv_query_res_t * p_rec )
68 {
69  verbs::OpenSM* ctxt = (verbs::OpenSM*) p_rec->query_context;
70 
71  ctxt->SetResult(p_rec);
72 
73  if( p_rec->status != IB_SUCCESS )
74  if ( p_rec->status != IB_INVALID_PARAMETER )
75  EOUT("TOsm_query_result: Error on query (%s)", ib_get_err_str( p_rec->status));
76 }
77 
78 
79 
80 // **************************************************
81 
83  f_vendor(0),
84  f_log(0)
85 {
86  memset(&f_local_port, 0, sizeof(f_local_port));
87  memset(&f_bind_handle, 0, sizeof(f_bind_handle));
88  memset(&f_mad_pool, 0, sizeof(f_mad_pool));
89 }
90 
92 {
93 }
94 
96 {
97  ib_api_status_t status;
98 
99  f_log = (osm_log_t*) malloc (sizeof(osm_log_t));
100  if (!f_log) {
101  EOUT("Problem with memory allocation");
102  return false;
103  }
104 
105  memset(f_log, 0, sizeof(osm_log_t));
106  osm_log_construct(f_log);
107 
108  status = osm_log_init_v2(f_log, TRUE, 0x0001, NULL, 0, TRUE );
109 // status = osm_log_init(f_log, TRUE, 0x0001, NULL, TRUE );
110  if( status != IB_SUCCESS ) {
111  EOUT("Problem with osm_log_init_v2");
112  return false;
113  }
114 
115  /* but we do not want any extra stuff here */
116  osm_log_set_level(f_log, OSM_LOG_ERROR/* | OSM_LOG_INFO */);
117 
118  //osm_log(f_log, OSM_LOG_INFO, "doing init");
119 
120  f_vendor = osm_vendor_new(f_log, 10);
121 
122  if (f_vendor==0) {
123  //osm_log(f_log, OSM_LOG_ERROR, "Cannot create vendor\n" );
124  EOUT("Cannot create vendor");
125  return false;
126  }
127 
128 
129 // the only change from OFED 1.2 to 1.4
130 // status = osm_mad_pool_init( &f_mad_pool, f_log );
131 
132  osm_mad_pool_construct( &f_mad_pool);
133  status = osm_mad_pool_init( &f_mad_pool);
134  if( status != IB_SUCCESS ) {
135  osm_log(f_log, OSM_LOG_ERROR, "problem with mad_pool\n" );
136  return false;
137  }
138 
139  return BindPort();
140 }
141 
143 {
144  uint32_t port_index = 0; // we always use first port
145  ib_api_status_t status;
146  uint32_t num_ports = OSM_GUID_ARRAY_SIZE;
147  ib_port_attr_t attr_array[OSM_GUID_ARRAY_SIZE];
148 
149  /*
150  * Call the transport layer for a list of local port
151  * GUID values.
152  */
153  status = osm_vendor_get_all_port_attr( f_vendor, attr_array, &num_ports );
154  if( status != IB_SUCCESS ) {
155  EOUT("osm_vendor_get_all_port_attr fails");
156  return false;
157  }
158 
159 /*
160  DOUT1("Total number of ports = %u", num_ports);
161  for (uint32_t n=0;n<num_ports;n++)
162  DOUT1(" Port %u: %016lx ", n, cl_ntoh64(attr_array[n].port_guid);
163 */
164 
166  memcpy( &f_local_port, &(attr_array[port_index]), sizeof( f_local_port ) );
167 
168 // DOUT1("Try to bind to %016lx", cl_ntoh64(f_local_port.port_guid);
169 
170  f_bind_handle = osmv_bind_sa(f_vendor, &f_mad_pool, f_local_port.port_guid);
171 
172  if(f_bind_handle == OSM_BIND_INVALID_HANDLE ) {
173  EOUT("Unable to bind to SA");
174  return false;
175  }
176 
177  return true;
178 }
179 
180 
182 {
183  DOUT4( "osm_vendor_delete commented");
184 // osm_vendor_delete(&f_vendor);
185  DOUT4( "osm_mad_pool_destroy");
186  osm_mad_pool_destroy(&f_mad_pool);
187  DOUT4( "osm_log_destroy");
188  osm_log_destroy(f_log);
189  return true;
190 }
191 
192 
193 bool verbs::OpenSM::Query_SA(osmv_query_type_t query_type,
194  uint64_t comp_mask,
195  ib_member_rec_t *mc_req,
196  ib_sa_mad_t *res)
197 {
198  ib_api_status_t status = IB_SUCCESS;
199 
200  osmv_user_query_t user;
201  osmv_query_req_t req;
202 
203  /*
204  * Do a blocking query for this record in the subnet.
205  *
206  * The query structures are locals.
207  */
208  memset( &req, 0, sizeof( req ) );
209  memset( &user, 0, sizeof( user ) );
210  memset( res, 0, sizeof(ib_sa_mad_t ) );
211 
212  user.p_attr = mc_req;
213  user.comp_mask = comp_mask;
214 
215  req.query_type = query_type;
216  req.timeout_ms = 1000; //p_osmt->opt.transaction_timeout;
217  req.retry_cnt = 3; // p_osmt->opt.retry_count;
218  req.flags = OSM_SA_FLAGS_SYNC;
219  req.query_context = this;
220  req.pfn_query_cb = TOsm_query_callback;
221  req.p_query_input = &user;
222  req.sm_key = 0;
223 
224  status = osmv_query_sa( f_bind_handle, &req );
225 
226  if ( status != IB_SUCCESS ) {
227  EOUT("osmv_query_sa error -(%s)", ib_get_err_str(status));
228  goto Exit;
229  }
230 
231  /* ok it worked */
232  memcpy(res, osm_madw_get_mad_ptr(fLastResult.p_result_madw), sizeof(ib_sa_mad_t));
233 
234  status = fLastResult.status;
235 
236  if((status != IB_SUCCESS ) && (status == IB_REMOTE_ERROR))
237  EOUT( "osmv_query_sa remote error");
238 // ib_get_mad_status_str( osm_madw_get_mad_ptr( context.result.p_result_madw ) ) );
239 
240  Exit:
241  /*
242  * Return the IB query MAD to the pool as necessary.
243  */
244  if(fLastResult.p_result_madw != NULL )
245  {
246  osm_mad_pool_put( &f_mad_pool, fLastResult.p_result_madw );
247  fLastResult.p_result_madw = NULL;
248  }
249 
250  return (status==IB_SUCCESS);
251 }
252 
254  uint8_t* mgid_raw,
255  uint16_t* mlid)
256 {
257  if ((mgid_raw==0) || (mlid==0)) return false;
258 
259  ib_member_rec_t mc_req_rec;
260  uint64_t comp_mask=0;
261  ib_sa_mad_t res_sa_mad;
262  ib_member_rec_t *p_mc_res;
263 
264  memset(&mc_req_rec, 0, sizeof(ib_member_rec_t));
265 
266  // set multicast group id
267 // memcpy(&mc_req_rec.mgid, mgid, sizeof(ib_gid_t));
268  memcpy(&mc_req_rec.mgid.raw, mgid_raw, sizeof(mc_req_rec.mgid.raw));
269 
270  DOUT4(" %s multicast port %016lx", (isadd ? "Add to" : "Remove from"), cl_ntoh64(f_local_port.port_guid));
271 
272  // set port id, which will be add/removed from multicast group
273  memcpy(&mc_req_rec.port_gid.unicast.interface_id,
274  &f_local_port.port_guid,
275  sizeof(f_local_port.port_guid));
276 
277  // lets use our own prefix ????
278  mc_req_rec.port_gid.unicast.prefix = CL_HTON64(0xFE80000000000000ULL);
279 
280  // set q key, for now I see only 0 in osmt_multicast ???
281  mc_req_rec.qkey = cl_hton32(VERBS_DEFAULT_QKEY);
282 
283  // as I see, mlid (multicast lid) is 0 and will be returned after request
284  mc_req_rec.mlid = 0;
285 
286  // we try exactly 2048, probably one should use less restrictive construction
287  // check when group is executed
288  mc_req_rec.mtu = IB_MTU_LEN_2048 | IB_PATH_SELECTOR_EXACTLY << 6;
289 // mc_req_rec.mtu = IB_MTU_LEN_256 | IB_PATH_SELECTOR_GREATER_THAN << 6;
290 
291  // everywhere 0 as I can see
292  mc_req_rec.tclass = 0;
293 
294  mc_req_rec.pkey = cl_hton16(0xffff);
295 // mc_req_rec.pkey = cl_hton16(2); //cl_hton16(0xffff);
296 
297  // this is our actual physical link datarate
298  mc_req_rec.rate = IB_LINK_WIDTH_ACTIVE_4X;
299 
300  // try to set packet life time grater than 0
301  // there is also comment, that just 0 should work
302  mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_GREATER_THAN << 6;
303 
304  // did not used here
305  mc_req_rec.sl_flow_hop = 0;
306 
307  // if I understood correctly scope = 0x02 is local scope (that ever it means),
308  // no other values are observed in osmt_multicast
309  // For state some other flags are possible: IB_MC_REC_STATE_NON_MEMBER or IB_MC_REC_STATE_SEND_ONLY_MEMBER
310  // Try as it is mostly used in examples.
311  mc_req_rec.scope_state = ib_member_set_scope_state(0x02, IB_MC_REC_STATE_FULL_MEMBER);
312 
313  // never appears in example
314  mc_req_rec.proxy_join = 0;
315 
316  comp_mask =
317  IB_MCR_COMPMASK_MGID | // there is also IB_MCR_COMPMASK_GID==IB_MCR_COMPMASK_MGID
318  IB_MCR_COMPMASK_PORT_GID |
319  IB_MCR_COMPMASK_QKEY |
320  IB_MCR_COMPMASK_PKEY |
321  IB_MCR_COMPMASK_SL |
322  IB_MCR_COMPMASK_FLOW |
323  IB_MCR_COMPMASK_JOIN_STATE |
324  IB_MCR_COMPMASK_TCLASS | /* all above are required */
325  IB_MCR_COMPMASK_MTU_SEL |
326  IB_MCR_COMPMASK_MTU |
327  IB_MCR_COMPMASK_SCOPE | // used only once, probably should not be specified
328  IB_MCR_COMPMASK_LIFE |
329  IB_MCR_COMPMASK_LIFE_SEL;
330 
331  bool res = Query_SA(isadd ? OSMV_QUERY_UD_MULTICAST_SET :
332  OSMV_QUERY_UD_MULTICAST_DELETE,
333  comp_mask,
334  &mc_req_rec,
335  &res_sa_mad);
336 
337  if (!res) return false;
338 
339  p_mc_res = (ib_member_rec_t*) ib_sa_mad_get_payload_ptr(&res_sa_mad);
340 
341  *mlid = cl_ntoh16(p_mc_res->mlid);
342 
343  return true;
344 }
345 
346 
348 {
349  ib_api_status_t status = IB_SUCCESS;
350  osmv_user_query_t user;
351  osmv_query_req_t req;
352  ib_member_rec_t *p_rec;
353  uint32_t i,num_recs = 0;
354 
355  memset( &req, 0, sizeof( req ) );
356  memset( &user, 0, sizeof( user ) );
357 
358  user.method = 0; //IB_MAD_METHOD_GET;
359  user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
360  user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
361  user.comp_mask = 0;
362 
363  req.query_type = OSMV_QUERY_USER_DEFINED;
364  req.timeout_ms = 1000;
365  req.retry_cnt = 3;
366  req.flags = OSM_SA_FLAGS_SYNC;
367  req.query_context = this;
368  req.pfn_query_cb = TOsm_query_callback;
369  req.p_query_input = &user;
370  req.sm_key = 0;
371 
372  status = osmv_query_sa(f_bind_handle, &req );
373 
374  if( status != IB_SUCCESS ) {
375  EOUT("PrintAllMulticasts error"
376  "osmv_query_sa failed (%s)\n", ib_get_err_str( status ));
377  goto Exit;
378  }
379 
380  status = fLastResult.status;
381 
382  if(status != IB_SUCCESS) {
383  EOUT("ib_query failed (%s)", ib_get_err_str( status ) ));
384  if(status==IB_REMOTE_ERROR) EOUT("Remote error");
385  goto Exit;
386  }
387 
388  num_recs = fLastResult.result_cnt;
389  DOUT0("Number of Multicast records: %u", num_recs);
390 
391  for( i = 0; i < num_recs; i++ ) {
392  p_rec = (ib_member_rec_t*) osmv_get_query_result( fLastResult.p_result_madw, i );
393 
394 /* DOUT0( " Rec %2d: "
395  "mgid: %02x%02x%02x%02x%02x%02x%02x%02x : %02x%02x%02x%02x%02x%02x%02x%02x"
396  " mlid: %4x mtu: %x rate: %x", i,
397  p_rec->mgid.raw[0], p_rec->mgid.raw[1], p_rec->mgid.raw[2], p_rec->mgid.raw[3],
398  p_rec->mgid.raw[4], p_rec->mgid.raw[5], p_rec->mgid.raw[6], p_rec->mgid.raw[7],
399  p_rec->mgid.raw[8], p_rec->mgid.raw[9], p_rec->mgid.raw[10], p_rec->mgid.raw[11],
400  p_rec->mgid.raw[12], p_rec->mgid.raw[13], p_rec->mgid.raw[14], p_rec->mgid.raw[15],
401  p_rec->mlid, p_rec->mtu, p_rec->rate));
402 */
403 
404  DOUT0( " Rec %2d: "
405  "mgid: %016lx : %016lx mlid: %04x mtu: %x pkey: %x rate: %x", i,
406  cl_ntoh64(p_rec->mgid.unicast.prefix),
407  cl_ntoh64(p_rec->mgid.unicast.interface_id),
408  cl_ntoh16(p_rec->mlid), p_rec->mtu, cl_ntoh16(p_rec->pkey), p_rec->rate));
409 
410  if (i==num_recs-1)
411  osm_dump_mc_record( f_log, p_rec, OSM_LOG_ERROR);
412  }
413 
414  Exit:
415  if( fLastResult.p_result_madw != NULL )
416  {
417  osm_mad_pool_put( &f_mad_pool, fLastResult.p_result_madw );
418  fLastResult.p_result_madw = NULL;
419  }
420 
421  return ( status==IB_SUCCESS );
422 }
423 
424 
425 bool verbs::OpenSM::QueryMyltucastGroup(uint8_t* mgid, uint16_t& mlid)
426 {
427  bool res = false;
428 
429  ib_api_status_t status = IB_SUCCESS;
430  osmv_user_query_t user;
431  osmv_query_req_t req;
432  ib_member_rec_t *p_rec;
433  uint32_t i,num_recs = 0;
434 
435  memset( &req, 0, sizeof( req ) );
436  memset( &user, 0, sizeof( user ) );
437 
438  user.method = 0; //IB_MAD_METHOD_GET;
439  user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
440  user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
441  user.comp_mask = 0;
442 
443  req.query_type = OSMV_QUERY_USER_DEFINED;
444  req.timeout_ms = 1000;
445  req.retry_cnt = 3;
446  req.flags = OSM_SA_FLAGS_SYNC;
447  req.query_context = this;
448  req.pfn_query_cb = TOsm_query_callback;
449  req.p_query_input = &user;
450  req.sm_key = 0;
451 
452  status = osmv_query_sa(f_bind_handle, &req );
453 
454  if( status != IB_SUCCESS ) {
455  EOUT("osmv_query_sa failed (%s)", ib_get_err_str(status));
456  goto Exit;
457  }
458 
459  status = fLastResult.status;
460 
461  if(status != IB_SUCCESS) {
462  EOUT("PrintAllMulticasts error"
463  "ib_query failed (%s)\n", ib_get_err_str( status ) ));
464  if(status==IB_REMOTE_ERROR) EOUT("PrintAllMulticasts Remote error");
465  goto Exit;
466  }
467 
468  num_recs = fLastResult.result_cnt;
469 
470  for( i = 0; i < num_recs; i++ ) {
471  p_rec = (ib_member_rec_t*) osmv_get_query_result( fLastResult.p_result_madw, i );
472 
473  if (memcmp(p_rec->mgid.raw, mgid, sizeof(uint8_t)*16)!=0) continue;
474 
475  mlid = cl_ntoh16(p_rec->mlid);
476  res = true;
477  break;
478  }
479 
480  Exit:
481  if( fLastResult.p_result_madw != NULL )
482  {
483  osm_mad_pool_put( &f_mad_pool, fLastResult.p_result_madw );
484  fLastResult.p_result_madw = NULL;
485  }
486 
487  return res;
488 }
ib_gid_t TOsm_good_mgid
Definition: OpenSM.cxx:22
void TOsm_query_callback(osmv_query_res_t *p_rec)
Definition: OpenSM.cxx:67
#define OSM_GUID_ARRAY_SIZE
Definition: OpenSM.h:17
#define VERBS_DEFAULT_QKEY
Definition: QueuePair.h:18
Interface class to opensm.
Definition: OpenSM.h:28
void SetResult(osmv_query_res_t *res)
Definition: OpenSM.h:36
bool QueryMyltucastGroup(uint8_t *mgid, uint16_t &mlid)
Definition: OpenSM.cxx:425
bool Init()
Definition: OpenSM.cxx:95
virtual ~OpenSM()
Definition: OpenSM.cxx:91
osm_bind_handle_t f_bind_handle
Definition: OpenSM.h:59
osm_mad_pool_t f_mad_pool
Definition: OpenSM.h:60
bool Query_SA(osmv_query_type_t query_type, uint64_t comp_mask, ib_member_rec_t *mc_req, ib_sa_mad_t *res)
Definition: OpenSM.cxx:193
bool PrintAllMulticasts()
Definition: OpenSM.cxx:347
bool BindPort()
Definition: OpenSM.cxx:142
bool ManageMultiCastGroup(bool isadd, uint8_t *mgid, uint16_t *mlid)
Definition: OpenSM.cxx:253
bool Close()
Definition: OpenSM.cxx:181
ib_port_attr_t f_local_port
Definition: OpenSM.h:58
#define DOUT0(args ...)
Definition: logging.h:156
#define EOUT(args ...)
Definition: logging.h:150
#define DOUT4(args ...)
Definition: logging.h:182
Definition: Factory.h:20