f432df672cd62ce7113779374efa7e219c26dc07
[mirror/winof/.git] / ulp / opensm / user / libvendor / osm_vendor_mlx_sa.c
1 /*
2  * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  *
6  * This software is available to you under the OpenIB.org BSD license
7  * below:
8  *
9  *     Redistribution and use in source and binary forms, with or
10  *     without modification, are permitted provided that the following
11  *     conditions are met:
12  *
13  *      - Redistributions of source code must retain the above
14  *        copyright notice, this list of conditions and the following
15  *        disclaimer.
16  *
17  *      - Redistributions in binary form must reproduce the above
18  *        copyright notice, this list of conditions and the following
19  *        disclaimer in the documentation and/or other materials
20  *        provided with the distribution.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  * SOFTWARE.
30  *
31  * $Id$
32  */
33
34
35
36 #if HAVE_CONFIG_H
37 #  include <config.h>
38 #endif /* HAVE_CONFIG_H */
39
40 #include <complib/cl_debug.h>
41 #include <complib/cl_timer.h>
42 #include <vendor/osm_vendor_api.h>
43 #include <vendor/osm_vendor_sa_api.h>
44
45
46 /*****************************************************************************
47  *****************************************************************************/
48
49 /* this struct is the internal rep of the bind handle */
50 typedef struct _osmv_sa_bind_info {
51   osm_bind_handle_t  h_bind;
52   osm_log_t         *p_log;
53   osm_vendor_t      *p_vendor;
54   osm_mad_pool_t    *p_mad_pool;
55   uint64_t           port_guid;
56   cl_event_t         sync_event;
57   uint64_t           last_lids_update_sec;
58   uint16_t           lid;
59   uint16_t           sm_lid;
60 } osmv_sa_bind_info_t;
61
62 /*****************************************************************************
63  *****************************************************************************/
64
65 /*
66   Call back on new mad received:
67
68   We basically only need to set the context of the query.
69   Or report an error.
70
71   A pointer to the actual context of the request (a copy of the oriignal
72   request structure) is attached as the p_madw->context.ni_context.node_guid
73 */
74 void
75 __osmv_sa_mad_rcv_cb(
76   IN osm_madw_t *p_madw,
77   IN void* bind_context,
78   IN osm_madw_t *p_req_madw)
79 {
80   osmv_sa_bind_info_t   *p_bind = (osmv_sa_bind_info_t *)bind_context;
81   osmv_query_req_t      *p_query_req_copy = NULL;
82   osmv_query_res_t       query_res;
83   ib_sa_mad_t           *p_sa_mad;
84   ib_net16_t             mad_status;
85
86   OSM_LOG_ENTER( p_bind->p_log, __osmv_sa_mad_rcv_cb );
87
88   if (! p_req_madw)
89   {
90     osm_log( p_bind->p_log, OSM_LOG_DEBUG,
91              "__osmv_sa_mad_rcv_cb: "
92              "Ignoring a non-response mad\n");
93     osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
94     goto Exit;
95   }
96
97   /* obtain the sent context */
98   p_query_req_copy =
99         (osmv_query_req_t *)(p_req_madw->context.arb_context.context1);
100
101   /* provide the context of the original request in the result */
102   query_res.query_context = p_query_req_copy->query_context;
103
104   /* provide the resulting madw */
105   query_res.p_result_madw = p_madw;
106
107   /* update the req fields */
108   p_sa_mad = ( ib_sa_mad_t * ) p_madw->p_mad;
109
110   /* if we got a remote error track it in the status */
111   mad_status = ( ib_net16_t ) ( p_sa_mad->status & IB_SMP_STATUS_MASK );
112   if (mad_status != IB_SUCCESS)
113   {
114     osm_log( p_bind->p_log, OSM_LOG_ERROR,
115              "__osmv_sa_mad_rcv_cb: ERR 0501: "
116              "Remote error:0x%04X .\n",  mad_status
117              );
118     query_res.status = IB_REMOTE_ERROR;
119   }
120   else
121   {
122     query_res.status = IB_SUCCESS;
123   }
124
125   /* what if we have got back an empty mad ? */
126   if (! p_madw->mad_size)
127   {
128     osm_log( p_bind->p_log, OSM_LOG_ERROR,
129              "__osmv_sa_mad_rcv_cb: ERR 0502: "
130              "Got an empty mad.\n"
131              );
132     query_res.status = IB_ERROR;
133   }
134
135   if (IB_SUCCESS == mad_status)
136   {
137
138     /* if we are in not in a method response of an rmpp nature we must get only 1 */
139     /* HACK: in the future we might need to be smarter for other mathods... */
140     if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP)
141     {
142       query_res.result_cnt = 1;
143     }
144     else
145     {
146 #ifndef VENDOR_RMPP_SUPPORT
147       if (mad_status != IB_SUCCESS)
148         query_res.result_cnt = 0;
149       else
150         query_res.result_cnt = 1;
151 #else
152       /* we used the offset value to calculate the number of
153          records in here */
154       query_res.result_cnt =
155         (uintn_t)
156         ( ( p_madw->mad_size - IB_SA_MAD_HDR_SIZE ) /
157           ib_get_attr_size( p_sa_mad->attr_offset ) );
158       osm_log( p_bind->p_log, OSM_LOG_DEBUG,
159                "__osmv_sa_mad_rcv_cb: Count = %u = %u / %u (%u)\n",
160                query_res.result_cnt, p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
161                ib_get_attr_size( p_sa_mad->attr_offset ),
162                ( p_madw->mad_size - IB_SA_MAD_HDR_SIZE ) %
163                ib_get_attr_size( p_sa_mad->attr_offset )
164                );
165 #endif
166     }
167   }
168
169   query_res.query_type = p_query_req_copy->query_type;
170
171   p_query_req_copy->pfn_query_cb( &query_res );
172
173   if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
174     cl_event_signal( &p_bind->sync_event );
175
176  Exit:
177
178   /* free the copied query request if found */
179   if (p_query_req_copy) cl_free(p_query_req_copy);
180
181   /* put back the request madw */
182   if (p_req_madw)
183     osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);
184
185   OSM_LOG_EXIT( p_bind->p_log );
186 }
187
188 /*****************************************************************************
189  ****************************************************************************/
190 /*
191   Send Error Callback:
192
193   Only report the error and get rid of the mad wrapper
194 */
195 void
196 __osmv_sa_mad_err_cb(
197   IN void* bind_context,
198   IN osm_madw_t *p_madw)
199 {
200   osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)bind_context;
201   osmv_query_req_t   *p_query_req_copy = NULL;
202   osmv_query_res_t    query_res;
203
204   OSM_LOG_ENTER( p_bind->p_log, __osmv_sa_mad_err_cb );
205
206   /* Obtain the sent context etc */
207   p_query_req_copy =
208         (osmv_query_req_t *)(p_madw->context.arb_context.context1);
209
210   /* provide the context of the original request in the result */
211   query_res.query_context = p_query_req_copy->query_context;
212
213   query_res.p_result_madw = p_madw;
214
215   query_res.status = IB_TIMEOUT;
216   query_res.result_cnt = 0;
217
218   query_res.query_type = p_query_req_copy->query_type;
219
220   p_query_req_copy->pfn_query_cb( &query_res );
221
222   if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
223     cl_event_signal( &p_bind->sync_event );
224
225   if (p_query_req_copy) cl_free(p_query_req_copy);
226   OSM_LOG_EXIT( p_bind->p_log );
227 }
228
229 /*****************************************************************************
230  This routine needs to be invoked on every send - since the SM LID and Local 
231  lid might change. To do that without any major perfoermance impact we cache 
232  the results and time they were obtained. Refresh only twice a minute. 
233  To avoid the need to use statics and risk a race - we require the refresh time
234  to be stored in the context of the results. Also this coveres cases were 
235  we query for multiple guids.
236  *****************************************************************************/
237 ib_api_status_t
238 __osmv_get_lid_and_sm_lid_by_port_guid(
239   IN osm_vendor_t*   const p_vend,
240   IN ib_net64_t            port_guid,
241   IN OUT uint64_t*         p_lids_update_time_sec,
242   OUT uint16_t*            lid,
243   OUT uint16_t*            sm_lid)
244 {
245
246   ib_api_status_t    status;
247   ib_port_attr_t    *p_attr_array;
248   uint32_t           num_ports;
249   uint32_t           port_num;
250
251   OSM_LOG_ENTER( p_vend->p_log, __osmv_get_lid_and_sm_lid_by_port_guid );
252
253   /* use prevous values if current time is close enough to previous query */
254   if (cl_get_time_stamp_sec() <= *p_lids_update_time_sec + 30)
255   {
256     osm_log( p_vend->p_log, OSM_LOG_DEBUG,
257              "__osmv_get_lid_and_sm_lid_by_port_guid: "
258              "Using previously stored lid:0x%04x sm_lid:0x%04x\n",
259              *lid, *sm_lid
260              );
261     status = IB_SUCCESS;
262     goto Exit;
263   }
264
265   /* obtain the number of available ports */
266   num_ports = 0;
267   status = osm_vendor_get_all_port_attr(p_vend, NULL, &num_ports);
268   if (status != IB_INSUFFICIENT_MEMORY)
269   {
270     osm_log( p_vend->p_log, OSM_LOG_ERROR,
271              "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0503: "
272              "expected to get the IB_INSUFFICIENT_MEMORY but got: %s\n",
273              ib_get_err_str(status)
274              );
275     status = IB_ERROR;
276     goto Exit;
277   }
278
279   osm_log( p_vend->p_log, OSM_LOG_DEBUG,
280            "__osmv_get_lid_and_sm_lid_by_port_guid: "
281            "Found total of %u ports. Looking for guid:0x%016" PRIx64 "\n",
282            num_ports, cl_ntoh64(port_guid)
283            );
284
285   /* allocate the attributes */
286   p_attr_array =
287     (ib_port_attr_t *)cl_malloc(sizeof(ib_port_attr_t)*num_ports);
288
289   /* obtain the attributes */
290   status = osm_vendor_get_all_port_attr(p_vend, p_attr_array, &num_ports);
291   if (status != IB_SUCCESS)
292   {
293     osm_log( p_vend->p_log, OSM_LOG_ERROR,
294              "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0504: "
295              "Fail to get port attributes (error: %s)\n",
296              ib_get_err_str(status)
297              );
298     cl_free(p_attr_array);
299     goto Exit;
300   }
301
302   status = IB_ERROR;
303   /* find the port requested in the list */
304   for (port_num = 0; (port_num<num_ports) && (status == IB_ERROR); port_num++)
305   {
306     if (p_attr_array[port_num].port_guid == port_guid)
307     {
308       *lid = p_attr_array[port_num].lid;
309       *sm_lid = p_attr_array[port_num].sm_lid;
310       *p_lids_update_time_sec = cl_get_time_stamp_sec();
311       status = IB_SUCCESS;
312       osm_log( p_vend->p_log, OSM_LOG_DEBUG,
313                "__osmv_get_lid_and_sm_lid_by_port_guid: "
314                "Found guid:0x%016" PRIx64 " with idx:%d\n",
315                cl_ntoh64(port_guid), port_num);
316     }
317   }
318
319   cl_free(p_attr_array);
320
321  Exit:
322   OSM_LOG_EXIT( p_vend->p_log );
323   return ( status );
324 }
325
326 /*****************************************************************************
327  *****************************************************************************/
328 osm_bind_handle_t
329 osmv_bind_sa(
330   IN osm_vendor_t*   const p_vend,
331   IN osm_mad_pool_t* const p_mad_pool,
332   IN ib_net64_t            port_guid
333   )
334 {
335   osm_bind_info_t bind_info;
336   osm_log_t *p_log = p_vend->p_log;
337   ib_api_status_t status = IB_SUCCESS;
338   osmv_sa_bind_info_t *p_sa_bind_info;
339   cl_status_t cl_status;
340
341   OSM_LOG_ENTER( p_log, osmv_bind_sa );
342
343   osm_log( p_log, OSM_LOG_DEBUG,
344            "osmv_bind_sa: "
345            "Binding to port 0x%" PRIx64 ".\n",
346            cl_ntoh64( port_guid ) );
347
348   bind_info.port_guid = port_guid;
349   bind_info.mad_class = IB_MCLASS_SUBN_ADM;
350   bind_info.class_version = 2;
351   bind_info.is_responder = TRUE;
352   bind_info.is_trap_processor = FALSE;
353   bind_info.is_report_processor = TRUE;
354   bind_info.send_q_size = 256;
355   bind_info.recv_q_size = 256;
356
357   /* allocate the new sa bind info */
358   p_sa_bind_info =
359     (osmv_sa_bind_info_t *)cl_malloc(sizeof(osmv_sa_bind_info_t));
360   if (! p_sa_bind_info)
361   {
362     osm_log( p_log, OSM_LOG_ERROR,
363              "osmv_bind_sa: ERR 0505: "
364              "Fail to allocate new bidn structure\n" );
365     p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
366     goto Exit;
367   }
368
369   /* store some important context */
370   p_sa_bind_info->p_log = p_log;
371   p_sa_bind_info->port_guid = port_guid;
372   p_sa_bind_info->p_mad_pool = p_mad_pool;
373   p_sa_bind_info->p_vendor = p_vend;
374   p_sa_bind_info->last_lids_update_sec = 0;
375
376   /* Bind to the lower level */
377   p_sa_bind_info->h_bind =
378     osm_vendor_bind( p_vend,
379                      &bind_info,
380                      p_mad_pool,
381                      __osmv_sa_mad_rcv_cb,
382                      __osmv_sa_mad_err_cb,
383                      p_sa_bind_info); /* context provided to CBs */
384
385   if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE)
386   {
387     cl_free(p_sa_bind_info);
388     p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
389     osm_log( p_log, OSM_LOG_ERROR,
390              "osmv_bind_sa: ERR 0506: "
391              "Fail to bind to vendor SMI.\n" );
392     goto Exit;
393   }
394
395   /* obtain the sm_lid from the vendor */
396   status =
397     __osmv_get_lid_and_sm_lid_by_port_guid(
398       p_vend, port_guid,
399       &p_sa_bind_info->last_lids_update_sec,
400       &p_sa_bind_info->lid,
401       &p_sa_bind_info->sm_lid);
402   if (status != IB_SUCCESS)
403   {
404     cl_free(p_sa_bind_info);
405     p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
406     osm_log( p_log, OSM_LOG_ERROR,
407              "osmv_bind_sa: ERR 0507: "
408              "Fail to obtain the sm lid.\n" );
409     goto Exit;
410   }
411
412   /* initialize the sync_event */
413   cl_event_construct( &p_sa_bind_info->sync_event );
414   cl_status = cl_event_init( &p_sa_bind_info->sync_event, TRUE );
415   if( cl_status != CL_SUCCESS )
416   {
417     osm_log( p_log, OSM_LOG_ERROR,
418              "osmv_bind_sa: ERR 0508: "
419              "cl_init_event failed: %s\n",
420              ib_get_err_str(cl_status)
421              );
422     cl_free(p_sa_bind_info);
423     p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
424   }
425
426  Exit:
427   OSM_LOG_EXIT( p_log );
428   return ( p_sa_bind_info );
429 }
430
431 /*****************************************************************************
432  *****************************************************************************/
433
434 /****t* OSM Vendor SA Client/osmv_sa_mad_data
435  * NAME
436  *    osmv_sa_mad_data
437  *
438  * DESCRIPTION
439  * Extra fields required to perform a mad query
440  *  This struct is passed to the actual send method
441  *
442  * SYNOPSIS
443  */
444 typedef struct _osmv_sa_mad_data
445 {
446   /* MAD data. */
447   uint8_t method;
448   ib_net16_t attr_id;
449   ib_net16_t attr_offset;
450   ib_net64_t comp_mask;
451   void *p_attr;
452 } osmv_sa_mad_data_t;
453 /*
454  * method
455  *    The method of the mad to be sent
456  *
457  *  attr_id
458  *     Attribute ID
459  *
460  *  attr_offset
461  *     Offset as defiend by RMPP
462  *
463  *  comp_mask
464  *     The component mask of the query
465  *
466  *  p_attr
467  *     A pointer to the record of the attribute to be sent.
468  *
469  *****/
470
471 /*****************************************************************************
472  *****************************************************************************/
473 /* Send a MAD out on the GSI interface */
474 ib_api_status_t
475 __osmv_send_sa_req(
476   IN osmv_sa_bind_info_t*             p_bind,
477   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
478   IN const osmv_query_req_t     * const p_query_req )
479 {
480   ib_api_status_t   status;
481   ib_mad_t         *p_mad_hdr;
482   ib_sa_mad_t      *p_sa_mad;
483   osm_madw_t       *p_madw;
484   osm_log_t        *p_log = p_bind->p_log;
485   static atomic32_t trans_id;
486   boolean_t         sync;
487   osmv_query_req_t   *p_query_req_copy;
488
489   OSM_LOG_ENTER( p_log, __osmv_send_sa_req );
490
491   /*
492     since the sm_lid might change we obtain it every send
493     (actually it is cached in the bind object and refreshed 
494     every 30sec by this proc )
495   */
496   status =
497     __osmv_get_lid_and_sm_lid_by_port_guid(
498       p_bind->p_vendor, p_bind->port_guid,
499       &p_bind->last_lids_update_sec,
500       &p_bind->lid,
501       &p_bind->sm_lid);
502   if (status != IB_SUCCESS)
503   {
504     osm_log( p_log, OSM_LOG_ERROR,
505              "__osmv_send_sa_req: ERR 0509: "
506              "Fail to obtain the sm lid.\n" );
507     goto Exit;
508   }
509
510   /* Get a MAD wrapper for the send */
511   p_madw = osm_mad_pool_get(
512     p_bind->p_mad_pool,
513     p_bind->h_bind,
514     MAD_BLOCK_SIZE,
515     NULL );
516
517   if( p_madw == NULL )
518   {
519     osm_log( p_log, OSM_LOG_ERROR,
520              "__osmv_send_sa_req: ERR 0510: " 
521              "Unable to acquire MAD.\n" );
522     status = IB_INSUFFICIENT_RESOURCES;
523     goto Exit;
524   }
525
526   /* Initialize the Sent MAD: */
527
528   /* Initialize the MAD buffer for the send operation. */
529   p_mad_hdr = osm_madw_get_mad_ptr( p_madw );
530   p_sa_mad =  osm_madw_get_sa_mad_ptr( p_madw );
531
532   /* Get a new transaction Id */
533   cl_atomic_inc( &trans_id );
534
535   /* Cleanup the MAD from any residue */
536   cl_memclr(p_sa_mad, MAD_BLOCK_SIZE);
537
538   /* Initialize the standard MAD header. */
539   ib_mad_init_new(
540     p_mad_hdr,                         /* mad pointer */
541     IB_MCLASS_SUBN_ADM,                /* class */
542     ( uint8_t ) 2,                     /* version */
543     p_sa_mad_data->method,             /* method */
544     cl_hton64( ( uint64_t ) trans_id ),/* tid */
545     p_sa_mad_data->attr_id,            /* attr id */
546     0                                  /* attr mod */
547     );
548
549   /* Set the query information. */
550   p_sa_mad->sm_key = p_query_req->sm_key;
551   p_sa_mad->attr_offset = 0;
552   p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
553   if( p_sa_mad->comp_mask )
554   {
555     cl_memcpy( p_sa_mad->data, p_sa_mad_data->p_attr,
556                ib_get_attr_size(p_sa_mad_data->attr_offset));
557   }
558
559   /*
560     Provide the address to send to
561   */
562   /* Patch to handle IBAL - host order , where it should take destination lid in network order */
563 #ifdef OSM_VENDOR_INTF_AL
564   p_madw->mad_addr.dest_lid = p_bind->sm_lid;
565 #else
566   p_madw->mad_addr.dest_lid = cl_hton16(p_bind->sm_lid);
567 #endif
568   p_madw->mad_addr.addr_type.smi.source_lid =
569     cl_hton16(p_bind->lid);
570   p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
571   p_madw->mad_addr.addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
572   p_madw->mad_addr.addr_type.gsi.pkey = IB_DEFAULT_PKEY;
573   p_madw->resp_expected = TRUE;
574   p_madw->fail_msg = CL_DISP_MSGID_NONE;
575
576   /*
577     Provide MAD context such that the call back will know what to do.
578     We have to keep the entire request structure so we know the CB.
579     Since we can not rely on the client to keep it arroud until
580     the response - we duplicate it and will later dispose it (in CB).
581     To store on the MADW we cast it into what opensm has:
582     p_madw->context.arb_context.context1
583   */
584   p_query_req_copy = cl_malloc(sizeof(*p_query_req_copy));
585   *p_query_req_copy = *p_query_req;
586   p_madw->context.arb_context.context1 = p_query_req_copy;
587
588   /* we can support async as well as sync calls */
589   sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);
590
591   /* send the mad asynchronously */
592   status = osm_vendor_send(
593     osm_madw_get_bind_handle( p_madw ),
594     p_madw,
595     p_madw->resp_expected );
596
597   /* if synchronous - wait on the event */
598   if (sync)
599   {
600     osm_log( p_log, OSM_LOG_DEBUG,
601              "__osmv_send_sa_req: "
602              "Waiting for async event.\n" );
603     cl_event_wait_on( &p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE );
604     cl_event_reset(&p_bind->sync_event);
605   }
606
607  Exit:
608   OSM_LOG_EXIT( p_log );
609   return status;
610 }
611
612 /*****************************************************************************
613  *****************************************************************************/
614 /*
615  * Query the SA based on the user's request.
616  */
617 ib_api_status_t
618 osmv_query_sa(
619   IN osm_bind_handle_t         h_bind,
620   IN const osmv_query_req_t * const p_query_req
621   )
622 {
623   osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)h_bind;
624   osmv_sa_mad_data_t sa_mad_data;
625   osmv_user_query_t *p_user_query;
626   ib_service_record_t svc_rec;
627   ib_node_record_t node_rec;
628   ib_portinfo_record_t port_info;
629   ib_path_rec_t path_rec;
630   ib_class_port_info_t class_port_info;
631   osm_log_t *p_log = p_bind->p_log;
632   ib_api_status_t status;
633
634   OSM_LOG_ENTER( p_log, osmv_query_sa );
635
636   /* Set the request information. */
637   sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
638
639   /* Set the MAD attributes and component mask correctly. */
640   switch ( p_query_req->query_type )
641   {
642
643   case OSMV_QUERY_USER_DEFINED:
644     osm_log( p_log, OSM_LOG_DEBUG,
645              "osmv_query_sa DBG:001 %s", "USER_DEFINED\n" );
646     p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
647     if (p_user_query->method) sa_mad_data.method = p_user_query->method;
648     sa_mad_data.attr_offset = p_user_query->attr_offset;
649     sa_mad_data.attr_id = p_user_query->attr_id;
650     sa_mad_data.comp_mask = p_user_query->comp_mask;
651     sa_mad_data.p_attr = p_user_query->p_attr;
652     break;
653
654   case OSMV_QUERY_ALL_SVC_RECS:
655     osm_log( p_log, OSM_LOG_DEBUG,
656              "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n" );
657     sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
658     sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
659     sa_mad_data.attr_offset =
660       ib_get_attr_offset( sizeof( ib_service_record_t ) );
661     sa_mad_data.comp_mask = 0;
662     sa_mad_data.p_attr = &svc_rec;
663     break;
664
665   case OSMV_QUERY_SVC_REC_BY_NAME:
666     osm_log( p_log, OSM_LOG_DEBUG,
667              "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n" );
668     sa_mad_data.method = IB_MAD_METHOD_GET;
669     sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
670     sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME;
671     sa_mad_data.attr_offset =
672       ib_get_attr_offset( sizeof( ib_service_record_t ) );
673     sa_mad_data.p_attr = &svc_rec;
674     cl_memcpy( svc_rec.service_name, p_query_req->p_query_input,
675                sizeof( ib_svc_name_t ) );
676     break;
677
678   case OSMV_QUERY_SVC_REC_BY_ID:
679     osm_log( p_log, OSM_LOG_DEBUG,
680              "osmv_query_sa DBG:001 %s", "SVC_REC_BY_ID\n" );
681     sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
682     sa_mad_data.comp_mask = IB_SR_COMPMASK_SID;
683     sa_mad_data.attr_offset =
684       ib_get_attr_offset( sizeof( ib_service_record_t ) );
685     sa_mad_data.p_attr = &svc_rec;
686     svc_rec.service_id = *( ib_net64_t * ) ( p_query_req->p_query_input );
687     break;
688
689   case OSMV_QUERY_CLASS_PORT_INFO:
690     osm_log( p_log, OSM_LOG_DEBUG,
691              "osmv_query_sa DBG:001 %s","CLASS_PORT_INFO\n" );
692     sa_mad_data.method = IB_MAD_METHOD_GET;
693     sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO;
694     sa_mad_data.attr_offset =
695       ib_get_attr_offset( sizeof( ib_class_port_info_t ) );
696     sa_mad_data.comp_mask = 0;
697     sa_mad_data.p_attr = &class_port_info;
698
699     break;
700
701   case OSMV_QUERY_NODE_REC_BY_NODE_GUID:
702     osm_log( p_log, OSM_LOG_DEBUG,
703              "osmv_query_sa DBG:001 %s","NODE_REC_BY_NODE_GUID\n" );
704     sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
705     sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD;
706     sa_mad_data.attr_offset =
707       ib_get_attr_offset( sizeof( ib_node_record_t ) );
708     sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID;
709     sa_mad_data.p_attr = &node_rec;
710     node_rec.node_info.node_guid =
711       *( ib_net64_t * ) ( p_query_req->p_query_input );
712
713     break;
714
715   case OSMV_QUERY_PORT_REC_BY_LID:
716     osm_log( p_log, OSM_LOG_DEBUG,
717              "osmv_query_sa DBG:001 %s","PORT_REC_BY_LID\n" );
718     sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
719     sa_mad_data.attr_offset =
720       ib_get_attr_offset( sizeof( ib_portinfo_record_t ) );
721     sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID;
722     sa_mad_data.p_attr = &port_info;
723     port_info.lid = *( ib_net16_t * ) ( p_query_req->p_query_input );
724     break;
725
726   case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM:
727     sa_mad_data.method = IB_MAD_METHOD_GET;
728     p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
729     osm_log( p_log, OSM_LOG_DEBUG,
730              "osmv_query_sa DBG:001 %s","PORT_REC_BY_LID_AND_NUM\n" );
731     sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
732     sa_mad_data.attr_offset =
733       ib_get_attr_offset( sizeof( ib_portinfo_record_t ) );
734     sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM;
735     sa_mad_data.p_attr = p_user_query->p_attr;
736     break;
737
738   case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK:
739     sa_mad_data.method = IB_MAD_METHOD_GET;
740     p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
741     osm_log( p_log, OSM_LOG_DEBUG,
742              "osmv_query_sa DBG:001 %s","OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n" );
743     sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD;
744     sa_mad_data.attr_offset =
745       ib_get_attr_offset( sizeof( ib_vl_arb_table_record_t ) );
746     sa_mad_data.comp_mask = IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT | IB_VLA_COMPMASK_BLOCK;
747     sa_mad_data.p_attr = p_user_query->p_attr;
748     break;
749
750   case OSMV_QUERY_SLVL_BY_LID_AND_PORTS:
751     sa_mad_data.method = IB_MAD_METHOD_GET;
752     p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
753     osm_log( p_log, OSM_LOG_DEBUG,
754              "osmv_query_sa DBG:001 %s","OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n" );
755     sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD;
756     sa_mad_data.attr_offset =
757       ib_get_attr_offset( sizeof( ib_slvl_table_record_t ) );
758     sa_mad_data.comp_mask = IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT | IB_SLVL_COMPMASK_IN_PORT;
759     sa_mad_data.p_attr = p_user_query->p_attr;
760     break;
761
762   case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS:
763     osm_log( p_log, OSM_LOG_DEBUG,
764              "osmv_query_sa DBG:001 %s","PATH_REC_BY_PORT_GUIDS\n" );
765     cl_memclr(&path_rec, sizeof(ib_path_rec_t ));
766     sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
767     sa_mad_data.attr_offset =
768       ib_get_attr_offset( sizeof( ib_path_rec_t ) );
769     sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID );
770     sa_mad_data.p_attr = &path_rec;
771     ib_gid_set_default( &path_rec.dgid,
772                         ( ( osmv_guid_pair_t * ) ( p_query_req->
773                                                    p_query_input ) )->
774                         dest_guid );
775     ib_gid_set_default( &path_rec.sgid,
776                         ( ( osmv_guid_pair_t * ) ( p_query_req->
777                                                    p_query_input ) )->
778                         src_guid );
779     break;
780
781   case OSMV_QUERY_PATH_REC_BY_GIDS:
782     osm_log( p_log, OSM_LOG_DEBUG,
783              "osmv_query_sa DBG:001 %s","PATH_REC_BY_GIDS\n" );
784     cl_memclr(&path_rec, sizeof(ib_path_rec_t ));
785     sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
786     sa_mad_data.attr_offset =
787       ib_get_attr_offset( sizeof( ib_path_rec_t ) );
788     sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID );
789     sa_mad_data.p_attr = &path_rec;
790     cl_memcpy( &path_rec.dgid,
791                &( ( osmv_gid_pair_t * ) ( p_query_req->p_query_input ) )->
792                dest_gid, sizeof( ib_gid_t ) );
793     cl_memcpy( &path_rec.sgid,
794                &( ( osmv_gid_pair_t * ) ( p_query_req->p_query_input ) )->
795                src_gid, sizeof( ib_gid_t ) );
796     break;
797
798   case OSMV_QUERY_PATH_REC_BY_LIDS:
799     osm_log( p_log, OSM_LOG_DEBUG,
800              "osmv_query_sa DBG:001 %s","PATH_REC_BY_LIDS\n" );
801     cl_memclr(&path_rec, sizeof(ib_path_rec_t ));
802     sa_mad_data.method = IB_MAD_METHOD_GET;
803     sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
804     sa_mad_data.attr_offset =
805       ib_get_attr_offset( sizeof( ib_path_rec_t ) );
806     sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID );
807     sa_mad_data.p_attr = &path_rec;
808     path_rec.dlid =
809       ( ( osmv_lid_pair_t * ) ( p_query_req->p_query_input ) )->dest_lid;
810     path_rec.slid =
811       ( ( osmv_lid_pair_t * ) ( p_query_req->p_query_input ) )->src_lid;
812     break;
813
814   case OSMV_QUERY_UD_MULTICAST_SET:
815     sa_mad_data.method = IB_MAD_METHOD_SET;
816     p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
817     osm_log( p_log, OSM_LOG_DEBUG,
818              "osmv_query_sa DBG:001 %s","OSMV_QUERY_UD_MULTICAST_SET\n" );
819     sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
820     sa_mad_data.attr_offset =
821       ib_get_attr_offset( sizeof( ib_member_rec_t ) );
822     sa_mad_data.comp_mask = p_user_query->comp_mask;
823     sa_mad_data.p_attr = p_user_query->p_attr;
824     break;
825
826   case OSMV_QUERY_UD_MULTICAST_DELETE:
827     sa_mad_data.method = IB_MAD_METHOD_DELETE;
828     p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input;
829     osm_log( p_log, OSM_LOG_DEBUG,
830              "osmv_query_sa DBG:001 %s","OSMV_QUERY_UD_MULTICAST_DELETE\n" );
831     sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
832     sa_mad_data.attr_offset =
833       ib_get_attr_offset( sizeof( ib_member_rec_t ) );
834     sa_mad_data.comp_mask = p_user_query->comp_mask;
835     sa_mad_data.p_attr = p_user_query->p_attr;
836     break;
837
838   default:
839     osm_log( p_log, OSM_LOG_ERROR,
840              "osmv_query_sa DBG:001 %s","UNKNOWN\n" );
841     CL_ASSERT( 0 );
842     return IB_ERROR;
843   }
844
845   status = __osmv_send_sa_req( h_bind, &sa_mad_data, p_query_req );
846
847   OSM_LOG_EXIT( p_log );
848   return status;
849 }
850
851
852 /*****************************************************************************
853  *****************************************************************************/
854
855