]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/management/opensm/opensm/osm_sa_informinfo.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / management / opensm / opensm / osm_sa_informinfo.c
1 /*
2  * Copyright (c) 2004-2008 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 a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * OpenIB.org BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  *
34  */
35
36 /*
37  * Abstract:
38  *    Implementation of osm_infr_rcv_t.
39  * This object represents the InformInfo Receiver object.
40  * This object is part of the opensm family of objects.
41  */
42
43 #if HAVE_CONFIG_H
44 #  include <config.h>
45 #endif                          /* HAVE_CONFIG_H */
46
47 #include <string.h>
48 #include <iba/ib_types.h>
49 #include <arpa/inet.h>
50 #include <complib/cl_qmap.h>
51 #include <complib/cl_passivelock.h>
52 #include <complib/cl_debug.h>
53 #include <complib/cl_qlist.h>
54 #include <vendor/osm_vendor_api.h>
55 #include <opensm/osm_port.h>
56 #include <opensm/osm_node.h>
57 #include <opensm/osm_switch.h>
58 #include <opensm/osm_helper.h>
59 #include <opensm/osm_sa.h>
60 #include <opensm/osm_inform.h>
61 #include <opensm/osm_pkey.h>
62
63 #include <sys/socket.h>
64
65 typedef struct osm_iir_item {
66         cl_list_item_t list_item;
67         ib_inform_info_record_t rec;
68 } osm_iir_item_t;
69
70 typedef struct osm_iir_search_ctxt {
71         const ib_inform_info_record_t *p_rcvd_rec;
72         ib_net64_t comp_mask;
73         cl_qlist_t *p_list;
74         ib_gid_t subscriber_gid;
75         ib_net16_t subscriber_enum;
76         osm_sa_t *sa;
77         osm_physp_t *p_req_physp;
78 } osm_iir_search_ctxt_t;
79
80 /**********************************************************************
81 o13-14.1.1: Except for Set(InformInfo) requests with Inform-
82 Info:LIDRangeBegin=0xFFFF, managers that support event forwarding
83 shall, upon receiving a Set(InformInfo), verify that the requester
84 originating the Set(InformInfo) and a Trap() source identified by Inform-
85 can access each other - can use path record to verify that.
86 **********************************************************************/
87 static boolean_t
88 __validate_ports_access_rights(IN osm_sa_t * sa,
89                                IN osm_infr_t * p_infr_rec)
90 {
91         boolean_t valid = TRUE;
92         osm_physp_t *p_requester_physp;
93         osm_port_t *p_port;
94         osm_physp_t *p_physp;
95         ib_net64_t portguid;
96         ib_net16_t lid_range_begin;
97         ib_net16_t lid_range_end;
98         ib_net16_t lid;
99         const cl_ptr_vector_t *p_tbl;
100         ib_gid_t zero_gid;
101
102         OSM_LOG_ENTER(sa->p_log);
103
104         /* get the requester physp from the request address */
105         p_requester_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
106                                                       &p_infr_rec->report_addr);
107
108         memset(&zero_gid, 0, sizeof(zero_gid));
109         if (memcmp(&(p_infr_rec->inform_record.inform_info.gid),
110                    &zero_gid, sizeof(ib_gid_t))) {
111                 /* a gid is defined */
112                 portguid =
113                     p_infr_rec->inform_record.inform_info.gid.unicast.
114                     interface_id;
115
116                 p_port = osm_get_port_by_guid(sa->p_subn, portguid);
117
118                 if (p_port == NULL) {
119                         OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4301: "
120                                 "Invalid port guid: 0x%016" PRIx64 "\n",
121                                 cl_ntoh64(portguid));
122                         valid = FALSE;
123                         goto Exit;
124                 }
125
126                 /* get the destination InformInfo physical port */
127                 p_physp = p_port->p_physp;
128
129                 /* make sure that the requester and destination port can access each other
130                    according to the current partitioning. */
131                 if (!osm_physp_share_pkey
132                     (sa->p_log, p_physp, p_requester_physp)) {
133                         OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
134                                 "port and requester don't share pkey\n");
135                         valid = FALSE;
136                         goto Exit;
137                 }
138         } else {
139                 /* gid is zero - check if LID range is defined */
140                 lid_range_begin =
141                     cl_ntoh16(p_infr_rec->inform_record.inform_info.
142                               lid_range_begin);
143                 /* if lid is 0xFFFF - meaning all endports managed by the manager */
144                 if (lid_range_begin == 0xFFFF)
145                         goto Exit;
146
147                 lid_range_end =
148                     cl_ntoh16(p_infr_rec->inform_record.inform_info.
149                               lid_range_end);
150
151                 /* lid_range_end is set to zero if no range desired. In this case -
152                    just make it equal to the lid_range_begin. */
153                 if (lid_range_end == 0)
154                         lid_range_end = lid_range_begin;
155
156                 /* go over all defined lids within the range and make sure that the
157                    requester port can access them according to current partitioning. */
158                 for (lid = lid_range_begin; lid <= lid_range_end; lid++) {
159                         p_tbl = &sa->p_subn->port_lid_tbl;
160                         if (cl_ptr_vector_get_size(p_tbl) > lid)
161                                 p_port = cl_ptr_vector_get(p_tbl, lid);
162                         else {
163                                 /* lid requested is out of range */
164                                 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4302: "
165                                         "Given LID (%u) is out of range:%u\n",
166                                         lid, cl_ptr_vector_get_size(p_tbl));
167                                 valid = FALSE;
168                                 goto Exit;
169                         }
170                         if (p_port == NULL)
171                                 continue;
172
173                         p_physp = p_port->p_physp;
174                         /* make sure that the requester and destination port can access
175                            each other according to the current partitioning. */
176                         if (!osm_physp_share_pkey
177                             (sa->p_log, p_physp, p_requester_physp)) {
178                                 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
179                                         "port and requester don't share pkey\n");
180                                 valid = FALSE;
181                                 goto Exit;
182                         }
183                 }
184         }
185
186 Exit:
187         OSM_LOG_EXIT(sa->p_log);
188         return valid;
189 }
190
191 /**********************************************************************
192  **********************************************************************/
193 static boolean_t
194 __validate_infr(IN osm_sa_t * sa, IN osm_infr_t * p_infr_rec)
195 {
196         boolean_t valid = TRUE;
197
198         OSM_LOG_ENTER(sa->p_log);
199
200         valid = __validate_ports_access_rights(sa, p_infr_rec);
201         if (!valid) {
202                 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
203                         "Invalid Access for InformInfo\n");
204                 valid = FALSE;
205         }
206
207         OSM_LOG_EXIT(sa->p_log);
208         return valid;
209 }
210
211 /**********************************************************************
212 o13-12.1.1: Confirm a valid request for event subscription by responding
213 with an InformInfo attribute that is a copy of the data in the
214 Set(InformInfo) request.
215 **********************************************************************/
216 static void
217 __osm_infr_rcv_respond(IN osm_sa_t * sa,
218                        IN osm_madw_t * const p_madw)
219 {
220         cl_qlist_t rec_list;
221         osm_iir_item_t *item;
222
223         OSM_LOG_ENTER(sa->p_log);
224
225         OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
226                 "Generating successful InformInfo response\n");
227
228         item = malloc(sizeof(*item));
229         if (!item) {
230                 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4303: "
231                         "rec_item alloc failed\n");
232                 goto Exit;
233         }
234
235         memcpy(&item->rec,
236                ib_sa_mad_get_payload_ptr(osm_madw_get_sa_mad_ptr(p_madw)),
237                sizeof(item->rec));
238
239         cl_qlist_init(&rec_list);
240         cl_qlist_insert_tail(&rec_list, &item->list_item);
241
242         osm_sa_respond(sa, p_madw, sizeof(ib_inform_info_t), &rec_list);
243
244 Exit:
245         OSM_LOG_EXIT(sa->p_log);
246 }
247
248 /**********************************************************************
249  **********************************************************************/
250 static void
251 __osm_sa_inform_info_rec_by_comp_mask(IN osm_sa_t * sa,
252                                       IN const osm_infr_t * const p_infr,
253                                       osm_iir_search_ctxt_t * const p_ctxt)
254 {
255         const ib_inform_info_record_t *p_rcvd_rec = NULL;
256         ib_net64_t comp_mask;
257         ib_net64_t portguid;
258         osm_port_t *p_subscriber_port;
259         osm_physp_t *p_subscriber_physp;
260         const osm_physp_t *p_req_physp;
261         osm_iir_item_t *p_rec_item;
262
263         OSM_LOG_ENTER(sa->p_log);
264
265         p_rcvd_rec = p_ctxt->p_rcvd_rec;
266         comp_mask = p_ctxt->comp_mask;
267         p_req_physp = p_ctxt->p_req_physp;
268
269         if (comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID &&
270             memcmp(&p_infr->inform_record.subscriber_gid,
271                    &p_ctxt->subscriber_gid,
272                    sizeof(p_infr->inform_record.subscriber_gid)))
273                 goto Exit;
274
275         if (comp_mask & IB_IIR_COMPMASK_ENUM &&
276             p_infr->inform_record.subscriber_enum != p_ctxt->subscriber_enum)
277                 goto Exit;
278
279         /* Implement any other needed search cases */
280
281         /* Ensure pkey is shared before returning any records */
282         portguid = p_infr->inform_record.subscriber_gid.unicast.interface_id;
283         p_subscriber_port = osm_get_port_by_guid(sa->p_subn, portguid);
284         if (p_subscriber_port == NULL) {
285                 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430D: "
286                         "Invalid subscriber port guid: 0x%016" PRIx64 "\n",
287                         cl_ntoh64(portguid));
288                 goto Exit;
289         }
290
291         /* get the subscriber InformInfo physical port */
292         p_subscriber_physp = p_subscriber_port->p_physp;
293         /* make sure that the requester and subscriber port can access each other
294            according to the current partitioning. */
295         if (!osm_physp_share_pkey
296             (sa->p_log, p_req_physp, p_subscriber_physp)) {
297                 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
298                         "requester and subscriber ports don't share pkey\n");
299                 goto Exit;
300         }
301
302         p_rec_item = malloc(sizeof(*p_rec_item));
303         if (p_rec_item == NULL) {
304                 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430E: "
305                         "rec_item alloc failed\n");
306                 goto Exit;
307         }
308
309         memcpy((void *)&p_rec_item->rec, (void *)&p_infr->inform_record,
310                sizeof(ib_inform_info_record_t));
311         cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item);
312
313 Exit:
314         OSM_LOG_EXIT(sa->p_log);
315 }
316
317 /**********************************************************************
318  **********************************************************************/
319 static void
320 __osm_sa_inform_info_rec_by_comp_mask_cb(IN cl_list_item_t * const p_list_item,
321                                          IN void *context)
322 {
323         const osm_infr_t *const p_infr = (osm_infr_t *) p_list_item;
324         osm_iir_search_ctxt_t *const p_ctxt = (osm_iir_search_ctxt_t *) context;
325
326         __osm_sa_inform_info_rec_by_comp_mask(p_ctxt->sa, p_infr, p_ctxt);
327 }
328
329 /**********************************************************************
330 Received a Get(InformInfoRecord) or GetTable(InformInfoRecord) MAD
331 **********************************************************************/
332 static void
333 osm_infr_rcv_process_get_method(IN osm_sa_t * sa,
334                                 IN osm_madw_t * const p_madw)
335 {
336         char gid_str[INET6_ADDRSTRLEN];
337         ib_sa_mad_t *p_rcvd_mad;
338         const ib_inform_info_record_t *p_rcvd_rec;
339         cl_qlist_t rec_list;
340         osm_iir_search_ctxt_t context;
341         osm_physp_t *p_req_physp;
342         osm_iir_item_t *item;
343
344         OSM_LOG_ENTER(sa->p_log);
345
346         CL_ASSERT(p_madw);
347         p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw);
348         p_rcvd_rec =
349             (ib_inform_info_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad);
350
351         /* update the requester physical port. */
352         p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
353                                                 osm_madw_get_mad_addr_ptr
354                                                 (p_madw));
355         if (p_req_physp == NULL) {
356                 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4309: "
357                         "Cannot find requester physical port\n");
358                 goto Exit;
359         }
360
361         if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
362                 osm_dump_inform_info_record(sa->p_log, p_rcvd_rec,
363                                             OSM_LOG_DEBUG);
364
365         cl_qlist_init(&rec_list);
366
367         context.p_rcvd_rec = p_rcvd_rec;
368         context.p_list = &rec_list;
369         context.comp_mask = p_rcvd_mad->comp_mask;
370         context.subscriber_gid = p_rcvd_rec->subscriber_gid;
371         context.subscriber_enum = p_rcvd_rec->subscriber_enum;
372         context.sa = sa;
373         context.p_req_physp = p_req_physp;
374
375         OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
376                 "Query Subscriber GID:%s(%02X) Enum:0x%X(%02X)\n",
377                 inet_ntop(AF_INET6, p_rcvd_rec->subscriber_gid.raw,
378                         gid_str, sizeof gid_str),
379                 (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID) != 0,
380                 cl_ntoh16(p_rcvd_rec->subscriber_enum),
381                 (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_ENUM) != 0);
382
383         cl_plock_acquire(sa->p_lock);
384
385         cl_qlist_apply_func(&sa->p_subn->sa_infr_list,
386                             __osm_sa_inform_info_rec_by_comp_mask_cb, &context);
387
388         cl_plock_release(sa->p_lock);
389
390         /* clear reserved and pad fields in InformInfoRecord */
391         for (item = (osm_iir_item_t *) cl_qlist_head(&rec_list);
392              item != (osm_iir_item_t *) cl_qlist_end(&rec_list);
393              item = (osm_iir_item_t *)cl_qlist_next(&item->list_item)) {
394                 memset(item->rec.reserved, 0, sizeof(item->rec.reserved));
395                 memset(item->rec.pad, 0, sizeof(item->rec.pad));
396         }
397
398         osm_sa_respond(sa, p_madw, sizeof(ib_inform_info_record_t), &rec_list);
399
400 Exit:
401         OSM_LOG_EXIT(sa->p_log);
402 }
403
404 /*********************************************************************
405 Received a Set(InformInfo) MAD
406 **********************************************************************/
407 static void
408 osm_infr_rcv_process_set_method(IN osm_sa_t * sa,
409                                 IN osm_madw_t * const p_madw)
410 {
411         ib_sa_mad_t *p_sa_mad;
412         ib_inform_info_t *p_recvd_inform_info;
413         osm_infr_t inform_info_rec;     /* actual inform record to be stored for reports */
414         osm_infr_t *p_infr;
415         ib_net32_t qpn;
416         uint8_t resp_time_val;
417         ib_api_status_t res;
418
419         OSM_LOG_ENTER(sa->p_log);
420
421         CL_ASSERT(p_madw);
422
423         p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
424         p_recvd_inform_info =
425             (ib_inform_info_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
426
427 #if 0
428         if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
429                 osm_dump_inform_info(sa->p_log, p_recvd_inform_info,
430                                      OSM_LOG_DEBUG);
431 #endif
432
433         /* Grab the lock */
434         cl_plock_excl_acquire(sa->p_lock);
435
436         /* define the inform record */
437         inform_info_rec.inform_record.inform_info = *p_recvd_inform_info;
438
439         /* following C13-32.1.2 Tbl 120: we only copy the source address vector */
440         inform_info_rec.report_addr = p_madw->mad_addr;
441
442         /* we will need to know the mad srvc to send back through */
443         inform_info_rec.h_bind = p_madw->h_bind;
444         inform_info_rec.sa = sa;
445
446         /* update the subscriber GID according to mad address */
447         res = osm_get_gid_by_mad_addr(sa->p_log, sa->p_subn, &p_madw->mad_addr,
448                                       &inform_info_rec.inform_record.
449                                       subscriber_gid);
450         if (res != IB_SUCCESS) {
451                 cl_plock_release(sa->p_lock);
452
453                 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 "
454                         "Subscribe Request from unknown LID: %u\n",
455                         cl_ntoh16(p_madw->mad_addr.dest_lid));
456                 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
457                 goto Exit;
458         }
459
460         /* HACK: enum is always 0 (currently) */
461         inform_info_rec.inform_record.subscriber_enum = 0;
462
463         /* Subscribe values above 1 are undefined */
464         if (p_recvd_inform_info->subscribe > 1) {
465                 cl_plock_release(sa->p_lock);
466
467                 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 "
468                         "Invalid subscribe: %d\n",
469                         p_recvd_inform_info->subscribe);
470                 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
471                 goto Exit;
472         }
473
474         /*
475          * MODIFICATIONS DONE ON INCOMING REQUEST:
476          *
477          * QPN:
478          * Internally we keep the QPN field of the InformInfo updated
479          * so we can simply compare it in the record - when finding such.
480          */
481         if (p_recvd_inform_info->subscribe) {
482                 ib_inform_info_set_qpn(&inform_info_rec.inform_record.
483                                        inform_info,
484                                        inform_info_rec.report_addr.addr_type.
485                                        gsi.remote_qp);
486
487                 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
488                         "Subscribe Request with QPN: 0x%06X\n",
489                         cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi.
490                                   remote_qp));
491         } else {
492                 ib_inform_info_get_qpn_resp_time(p_recvd_inform_info->g_or_v.
493                                                  generic.qpn_resp_time_val,
494                                                  &qpn, &resp_time_val);
495
496                 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
497                         "UnSubscribe Request with QPN: 0x%06X\n",
498                         cl_ntoh32(qpn));
499         }
500
501         /* If record exists with matching InformInfo */
502         p_infr =
503             osm_infr_get_by_rec(sa->p_subn, sa->p_log, &inform_info_rec);
504
505         /* check to see if the request was for subscribe */
506         if (p_recvd_inform_info->subscribe) {
507                 /* validate the request for a new or update InformInfo */
508                 if (__validate_infr(sa, &inform_info_rec) != TRUE) {
509                         cl_plock_release(sa->p_lock);
510
511                         OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4305: "
512                                 "Failed to validate a new inform object\n");
513
514                         /* o13-13.1.1: we need to set the subscribe bit to 0 */
515                         p_recvd_inform_info->subscribe = 0;
516                         osm_sa_send_error(sa, p_madw,
517                                           IB_SA_MAD_STATUS_REQ_INVALID);
518                         goto Exit;
519                 }
520
521                 /* ok - we can try and create a new entry */
522                 if (p_infr == NULL) {
523                         /* Create the instance of the osm_infr_t object */
524                         p_infr = osm_infr_new(&inform_info_rec);
525                         if (p_infr == NULL) {
526                                 cl_plock_release(sa->p_lock);
527
528                                 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4306: "
529                                         "Failed to create a new inform object\n");
530
531                                 /* o13-13.1.1: we need to set the subscribe bit to 0 */
532                                 p_recvd_inform_info->subscribe = 0;
533                                 osm_sa_send_error(sa, p_madw,
534                                                   IB_SA_MAD_STATUS_NO_RESOURCES);
535                                 goto Exit;
536                         }
537
538                         /* Add this new osm_infr_t object to subnet object */
539                         osm_infr_insert_to_db(sa->p_subn, sa->p_log, p_infr);
540                 } else
541                         /* Update the old instance of the osm_infr_t object */
542                         p_infr->inform_record = inform_info_rec.inform_record;
543         /* We got an UnSubscribe request */
544         } else if (p_infr == NULL) {
545                 cl_plock_release(sa->p_lock);
546
547                 /* No Such Item - So Error */
548                 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4307: "
549                         "Failed to UnSubscribe to non existing inform object\n");
550
551                 /* o13-13.1.1: we need to set the subscribe bit to 0 */
552                 p_recvd_inform_info->subscribe = 0;
553                 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
554                 goto Exit;
555         } else
556                 /* Delete this object from the subnet list of informs */
557                 osm_infr_remove_from_db(sa->p_subn, sa->p_log, p_infr);
558
559         cl_plock_release(sa->p_lock);
560
561         /* send the success response */
562         __osm_infr_rcv_respond(sa, p_madw);
563
564 Exit:
565         OSM_LOG_EXIT(sa->p_log);
566 }
567
568 /*********************************************************************
569 **********************************************************************/
570 void osm_infr_rcv_process(IN void *context, IN void *data)
571 {
572         osm_sa_t *sa = context;
573         osm_madw_t *p_madw = data;
574         ib_sa_mad_t *p_sa_mad;
575
576         OSM_LOG_ENTER(sa->p_log);
577
578         CL_ASSERT(p_madw);
579
580         p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
581
582         CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO);
583
584         if (p_sa_mad->method != IB_MAD_METHOD_SET) {
585                 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
586                         "Unsupported Method (%s)\n",
587                         ib_get_sa_method_str(p_sa_mad->method));
588                 osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
589                 goto Exit;
590         }
591
592         osm_infr_rcv_process_set_method(sa, p_madw);
593
594 Exit:
595         OSM_LOG_EXIT(sa->p_log);
596 }
597
598 /*********************************************************************
599 **********************************************************************/
600 void osm_infir_rcv_process(IN void *context, IN void *data)
601 {
602         osm_sa_t *sa = context;
603         osm_madw_t *p_madw = data;
604         ib_sa_mad_t *p_sa_mad;
605
606         OSM_LOG_ENTER(sa->p_log);
607
608         CL_ASSERT(p_madw);
609
610         p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
611
612         CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD);
613
614         if (p_sa_mad->method != IB_MAD_METHOD_GET &&
615             p_sa_mad->method != IB_MAD_METHOD_GETTABLE) {
616                 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Unsupported Method (%s)\n",
617                         ib_get_sa_method_str(p_sa_mad->method));
618                 osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
619                 goto Exit;
620         }
621
622         osm_infr_rcv_process_get_method(sa, p_madw);
623
624 Exit:
625         OSM_LOG_EXIT(sa->p_log);
626 }