1 /*
2 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5 * Copyright (c) 2009 HNR Consulting. All rights reserved.
6 * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
7 *
8 * This software is available to you under a choice of one of two
9 * licenses. You may choose to be licensed under the terms of the GNU
10 * General Public License (GPL) Version 2, available from the file
11 * COPYING in the main directory of this source tree, or the
12 * OpenIB.org BSD license below:
13 *
14 * Redistribution and use in source and binary forms, with or
15 * without modification, are permitted provided that the following
16 * conditions are met:
17 *
18 * - Redistributions of source code must retain the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer.
21 *
22 * - Redistributions in binary form must reproduce the above
23 * copyright notice, this list of conditions and the following
24 * disclaimer in the documentation and/or other materials
25 * provided with the distribution.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
31 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 * SOFTWARE.
35 *
36 */
37
38 /*
39 * Abstract:
40 * Implementation of osm_sm_mad_ctrl_t.
41 * This object represents the SM MAD request controller object.
42 * This object is part of the opensm family of objects.
43 */
44
45 #if HAVE_CONFIG_H
46 # include <config.h>
47 #endif /* HAVE_CONFIG_H */
48
49 #include <string.h>
50 #include <complib/cl_debug.h>
51 #include <iba/ib_types.h>
52 #include <opensm/osm_file_ids.h>
53 #define FILE_ID OSM_FILE_SM_MAD_CTRL_C
54 #include <opensm/osm_sm_mad_ctrl.h>
55 #include <vendor/osm_vendor_api.h>
56 #include <opensm/osm_madw.h>
57 #include <opensm/osm_msgdef.h>
58 #include <opensm/osm_helper.h>
59 #include <opensm/osm_opensm.h>
60
61 /****f* opensm: SM/sm_mad_ctrl_retire_trans_mad
62 * NAME
63 * sm_mad_ctrl_retire_trans_mad
64 *
65 * DESCRIPTION
66 * This function handles clean-up of MADs associated with the SM's
67 * outstanding transactions on the wire.
68 *
69 * SYNOPSIS
70 */
71
sm_mad_ctrl_retire_trans_mad(IN osm_sm_mad_ctrl_t * p_ctrl,IN osm_madw_t * p_madw)72 static void sm_mad_ctrl_retire_trans_mad(IN osm_sm_mad_ctrl_t * p_ctrl,
73 IN osm_madw_t * p_madw)
74 {
75 uint32_t outstanding;
76
77 OSM_LOG_ENTER(p_ctrl->p_log);
78
79 CL_ASSERT(p_madw);
80 /*
81 Return the MAD & wrapper to the pool.
82 */
83 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
84 "Retiring MAD with TID 0x%" PRIx64 "\n",
85 cl_ntoh64(osm_madw_get_smp_ptr(p_madw)->trans_id));
86
87 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
88
89 outstanding = osm_stats_dec_qp0_outstanding(p_ctrl->p_stats);
90
91 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs outstanding%s\n",
92 p_ctrl->p_stats->qp0_mads_outstanding,
93 outstanding ? "" : ": wire is clean.");
94
95 OSM_LOG_EXIT(p_ctrl->p_log);
96 }
97
98 /************/
99
100 /****f* opensm: SM/sm_mad_ctrl_disp_done_callback
101 * NAME
102 * sm_mad_ctrl_disp_done_callback
103 *
104 * DESCRIPTION
105 * This function is the Dispatcher callback that indicates
106 * a received MAD has been processed by the recipient.
107 *
108 * SYNOPSIS
109 */
sm_mad_ctrl_disp_done_callback(IN void * context,IN void * p_data)110 static void sm_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data)
111 {
112 osm_sm_mad_ctrl_t *p_ctrl = context;
113 osm_madw_t *p_madw = p_data;
114 ib_smp_t *p_smp;
115
116 OSM_LOG_ENTER(p_ctrl->p_log);
117
118 /*
119 If the MAD that just finished processing was a response,
120 then retire the transaction, since we must have generated
121 the request.
122
123 Otherwise, retire the transaction if a response was expected,
124 as in the case of a send failure. If a response was not expected,
125 just put the MAD back in the pool, because the MAD was a query
126 from some outside agent, e.g. Get(SMInfo) from another SM.
127 */
128 p_smp = osm_madw_get_smp_ptr(p_madw);
129 if (ib_smp_is_response(p_smp)) {
130 CL_ASSERT(p_madw->resp_expected == FALSE);
131 sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
132 } else if (p_madw->resp_expected == TRUE)
133 sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
134 else
135 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
136
137 OSM_LOG_EXIT(p_ctrl->p_log);
138 }
139
140 /************/
141
142 /****f* opensm: SM/sm_mad_ctrl_update_wire_stats
143 * NAME
144 * sm_mad_ctrl_update_wire_stats
145 *
146 * DESCRIPTION
147 * Updates wire stats for outstanding MADs and calls the VL15 poller.
148 *
149 * SYNOPSIS
150 */
sm_mad_ctrl_update_wire_stats(IN osm_sm_mad_ctrl_t * p_ctrl)151 static void sm_mad_ctrl_update_wire_stats(IN osm_sm_mad_ctrl_t * p_ctrl)
152 {
153 uint32_t mads_on_wire;
154
155 OSM_LOG_ENTER(p_ctrl->p_log);
156
157 mads_on_wire =
158 cl_atomic_dec(&p_ctrl->p_stats->qp0_mads_outstanding_on_wire);
159
160 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
161 "%u SMPs on the wire, %u outstanding\n", mads_on_wire,
162 p_ctrl->p_stats->qp0_mads_outstanding);
163
164 /*
165 We can signal the VL15 controller to send another MAD
166 if any are waiting for transmission.
167 */
168 osm_vl15_poll(p_ctrl->p_vl15);
169 OSM_LOG_EXIT(p_ctrl->p_log);
170 }
171
172 /****f* opensm: SM/sm_mad_ctrl_process_get_resp
173 * NAME
174 * sm_mad_ctrl_process_get_resp
175 *
176 * DESCRIPTION
177 * This function handles method GetResp() for received MADs.
178 * This is the most common path for QP0 MADs.
179 *
180 * SYNOPSIS
181 */
sm_mad_ctrl_process_get_resp(IN osm_sm_mad_ctrl_t * p_ctrl,IN osm_madw_t * p_madw,IN void * transaction_context)182 static void sm_mad_ctrl_process_get_resp(IN osm_sm_mad_ctrl_t * p_ctrl,
183 IN osm_madw_t * p_madw,
184 IN void *transaction_context)
185 {
186 ib_smp_t *p_smp;
187 cl_status_t status;
188 osm_madw_t *p_old_madw;
189 cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
190
191 OSM_LOG_ENTER(p_ctrl->p_log);
192
193 CL_ASSERT(p_madw);
194 CL_ASSERT(transaction_context);
195
196 p_smp = osm_madw_get_smp_ptr(p_madw);
197
198 if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR && !ib_smp_is_d(p_smp)) {
199 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3102: "
200 "'D' bit not set in returned SMP\n");
201 osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
202 }
203
204 p_old_madw = transaction_context;
205
206 sm_mad_ctrl_update_wire_stats(p_ctrl);
207
208 /*
209 Copy the MAD Wrapper context from the requesting MAD
210 to the new MAD. This mechanism allows the recipient
211 controller to recover its own context regarding this
212 MAD transaction. Once we've copied the context, we
213 can return the original MAD to the pool.
214 */
215 osm_madw_copy_context(p_madw, p_old_madw);
216 osm_mad_pool_put(p_ctrl->p_mad_pool, p_old_madw);
217
218 /*
219 Note that attr_id (like the rest of the MAD) is in
220 network byte order.
221 */
222 switch (p_smp->attr_id) {
223 case IB_MAD_ATTR_NODE_DESC:
224 msg_id = OSM_MSG_MAD_NODE_DESC;
225 break;
226 case IB_MAD_ATTR_NODE_INFO:
227 msg_id = OSM_MSG_MAD_NODE_INFO;
228 break;
229 case IB_MAD_ATTR_GUID_INFO:
230 msg_id = OSM_MSG_MAD_GUID_INFO;
231 break;
232 case IB_MAD_ATTR_SWITCH_INFO:
233 msg_id = OSM_MSG_MAD_SWITCH_INFO;
234 break;
235 case IB_MAD_ATTR_PORT_INFO:
236 msg_id = OSM_MSG_MAD_PORT_INFO;
237 break;
238 case IB_MAD_ATTR_LIN_FWD_TBL:
239 msg_id = OSM_MSG_MAD_LFT;
240 break;
241 case IB_MAD_ATTR_MCAST_FWD_TBL:
242 msg_id = OSM_MSG_MAD_MFT;
243 break;
244 case IB_MAD_ATTR_SM_INFO:
245 msg_id = OSM_MSG_MAD_SM_INFO;
246 break;
247 case IB_MAD_ATTR_SLVL_TABLE:
248 msg_id = OSM_MSG_MAD_SLVL;
249 break;
250 case IB_MAD_ATTR_VL_ARBITRATION:
251 msg_id = OSM_MSG_MAD_VL_ARB;
252 break;
253 case IB_MAD_ATTR_P_KEY_TABLE:
254 msg_id = OSM_MSG_MAD_PKEY;
255 break;
256 case IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO:
257 msg_id = OSM_MSG_MAD_MLNX_EXT_PORT_INFO;
258 break;
259 case IB_MAD_ATTR_CLASS_PORT_INFO:
260 case IB_MAD_ATTR_NOTICE:
261 case IB_MAD_ATTR_INFORM_INFO:
262 default:
263 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
264 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3103: "
265 "Unsupported attribute 0x%X (%s)\n",
266 cl_ntoh16(p_smp->attr_id),
267 ib_get_sm_attr_str(p_smp->attr_id));
268 osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
269 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
270 goto Exit;
271 }
272
273 /*
274 Post this MAD to the dispatcher for asynchronous
275 processing by the appropriate controller.
276 */
277
278 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
279 osm_get_disp_msg_str(msg_id));
280
281 status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
282 sm_mad_ctrl_disp_done_callback, p_ctrl);
283
284 if (status != CL_SUCCESS) {
285 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3104: "
286 "Dispatcher post message failed (%s) for attribute 0x%X (%s)\n",
287 CL_STATUS_MSG(status), cl_ntoh16(p_smp->attr_id),
288 ib_get_sm_attr_str(p_smp->attr_id));
289 goto Exit;
290 }
291
292 Exit:
293 OSM_LOG_EXIT(p_ctrl->p_log);
294 }
295
296 /****f* opensm: SM/sm_mad_ctrl_process_get
297 * NAME
298 * sm_mad_ctrl_process_get
299 *
300 * DESCRIPTION
301 * This function handles method Get() for received MADs.
302 *
303 * SYNOPSIS
304 */
sm_mad_ctrl_process_get(IN osm_sm_mad_ctrl_t * p_ctrl,IN osm_madw_t * p_madw)305 static void sm_mad_ctrl_process_get(IN osm_sm_mad_ctrl_t * p_ctrl,
306 IN osm_madw_t * p_madw)
307 {
308 ib_smp_t *p_smp;
309 cl_status_t status;
310 cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
311
312 OSM_LOG_ENTER(p_ctrl->p_log);
313
314 p_smp = osm_madw_get_smp_ptr(p_madw);
315
316 /*
317 Note that attr_id (like the rest of the MAD) is in
318 network byte order.
319 */
320 switch (p_smp->attr_id) {
321 case IB_MAD_ATTR_SM_INFO:
322 msg_id = OSM_MSG_MAD_SM_INFO;
323 break;
324 default:
325 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
326 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
327 "Ignoring SubnGet MAD - unsupported attribute 0x%X\n",
328 cl_ntoh16(p_smp->attr_id));
329 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
330 goto Exit;
331 }
332
333 /*
334 Post this MAD to the dispatcher for asynchronous
335 processing by the appropriate controller.
336 */
337
338 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
339 osm_get_disp_msg_str(msg_id));
340
341 status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
342 sm_mad_ctrl_disp_done_callback, p_ctrl);
343
344 if (status != CL_SUCCESS) {
345 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3106: "
346 "Dispatcher post message failed (%s)\n",
347 CL_STATUS_MSG(status));
348 goto Exit;
349 }
350
351 Exit:
352 OSM_LOG_EXIT(p_ctrl->p_log);
353 }
354
355 /*
356 * PARAMETERS
357 *
358 * RETURN VALUES
359 *
360 * NOTES
361 *
362 * SEE ALSO
363 *********/
364
365 /****f* opensm: SM/sm_mad_ctrl_process_set
366 * NAME
367 * sm_mad_ctrl_process_set
368 *
369 * DESCRIPTION
370 * This function handles method Set() for received MADs.
371 *
372 * SYNOPSIS
373 */
sm_mad_ctrl_process_set(IN osm_sm_mad_ctrl_t * p_ctrl,IN osm_madw_t * p_madw)374 static void sm_mad_ctrl_process_set(IN osm_sm_mad_ctrl_t * p_ctrl,
375 IN osm_madw_t * p_madw)
376 {
377 ib_smp_t *p_smp;
378 cl_status_t status;
379 cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
380
381 OSM_LOG_ENTER(p_ctrl->p_log);
382
383 p_smp = osm_madw_get_smp_ptr(p_madw);
384
385 /*
386 Note that attr_id (like the rest of the MAD) is in
387 network byte order.
388 */
389 switch (p_smp->attr_id) {
390 case IB_MAD_ATTR_SM_INFO:
391 msg_id = OSM_MSG_MAD_SM_INFO;
392 break;
393 default:
394 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
395 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3107: "
396 "Unsupported attribute 0x%X (%s)\n",
397 cl_ntoh16(p_smp->attr_id),
398 ib_get_sm_attr_str(p_smp->attr_id));
399 osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
400 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
401 goto Exit;
402 }
403
404 /*
405 Post this MAD to the dispatcher for asynchronous
406 processing by the appropriate controller.
407 */
408
409 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
410 osm_get_disp_msg_str(msg_id));
411
412 status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
413 sm_mad_ctrl_disp_done_callback, p_ctrl);
414
415 if (status != CL_SUCCESS) {
416 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3108: "
417 "Dispatcher post message failed (%s)\n",
418 CL_STATUS_MSG(status));
419 goto Exit;
420 }
421
422 Exit:
423 OSM_LOG_EXIT(p_ctrl->p_log);
424 }
425
426 /*
427 * PARAMETERS
428 *
429 * RETURN VALUES
430 *
431 * NOTES
432 *
433 * SEE ALSO
434 *********/
435
436 /****f* opensm: SM/sm_mad_ctrl_process_trap
437 * NAME
438 * sm_mad_ctrl_process_trap
439 *
440 * DESCRIPTION
441 * This function handles method Trap() for received MADs.
442 *
443 * SYNOPSIS
444 */
sm_mad_ctrl_process_trap(IN osm_sm_mad_ctrl_t * p_ctrl,IN osm_madw_t * p_madw)445 static void sm_mad_ctrl_process_trap(IN osm_sm_mad_ctrl_t * p_ctrl,
446 IN osm_madw_t * p_madw)
447 {
448 ib_smp_t *p_smp;
449 cl_status_t status;
450 cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
451
452 OSM_LOG_ENTER(p_ctrl->p_log);
453
454 p_smp = osm_madw_get_smp_ptr(p_madw);
455
456 /* Make sure OpenSM is master. If not - then we should not process the trap */
457 if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) {
458 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
459 "Received trap but OpenSM is not in MASTER state. "
460 "Dropping mad\n");
461 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
462 goto Exit;
463 }
464
465 /*
466 Note that attr_id (like the rest of the MAD) is in
467 network byte order.
468 */
469 switch (p_smp->attr_id) {
470 case IB_MAD_ATTR_NOTICE:
471 msg_id = OSM_MSG_MAD_NOTICE;
472 break;
473 default:
474 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
475 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3109: "
476 "Unsupported attribute 0x%X (%s)\n",
477 cl_ntoh16(p_smp->attr_id),
478 ib_get_sm_attr_str(p_smp->attr_id));
479 osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
480 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
481 goto Exit;
482 }
483
484 /*
485 Post this MAD to the dispatcher for asynchronous
486 processing by the appropriate controller.
487 */
488
489 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
490 osm_get_disp_msg_str(msg_id));
491
492 status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
493 sm_mad_ctrl_disp_done_callback, p_ctrl);
494
495 if (status != CL_SUCCESS) {
496 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3110: "
497 "Dispatcher post message failed (%s)\n",
498 CL_STATUS_MSG(status));
499 goto Exit;
500 }
501
502 Exit:
503 OSM_LOG_EXIT(p_ctrl->p_log);
504 }
505
506 /*
507 * PARAMETERS
508 *
509 * RETURN VALUES
510 *
511 * NOTES
512 *
513 * SEE ALSO
514 *********/
515
516 /****f* opensm: SM/sm_mad_ctrl_process_trap_repress
517 * NAME
518 * sm_mad_ctrl_process_trap_repress
519 *
520 * DESCRIPTION
521 * This function handles method TrapRepress() for received MADs.
522 *
523 * SYNOPSIS
524 */
sm_mad_ctrl_process_trap_repress(IN osm_sm_mad_ctrl_t * p_ctrl,IN osm_madw_t * p_madw)525 static void sm_mad_ctrl_process_trap_repress(IN osm_sm_mad_ctrl_t * p_ctrl,
526 IN osm_madw_t * p_madw)
527 {
528 ib_smp_t *p_smp;
529
530 OSM_LOG_ENTER(p_ctrl->p_log);
531
532 p_smp = osm_madw_get_smp_ptr(p_madw);
533
534 /*
535 Note that attr_id (like the rest of the MAD) is in
536 network byte order.
537 */
538 switch (p_smp->attr_id) {
539 case IB_MAD_ATTR_NOTICE:
540 sm_mad_ctrl_update_wire_stats(p_ctrl);
541 sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
542 break;
543 default:
544 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
545 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3105: "
546 "Unsupported attribute 0x%X (%s)\n",
547 cl_ntoh16(p_smp->attr_id),
548 ib_get_sm_attr_str(p_smp->attr_id));
549 osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
550 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
551 break;
552 }
553
554 OSM_LOG_EXIT(p_ctrl->p_log);
555 }
556
log_rcv_cb_error(osm_log_t * p_log,ib_smp_t * p_smp,ib_net16_t status)557 static void log_rcv_cb_error(osm_log_t *p_log, ib_smp_t *p_smp, ib_net16_t status)
558 {
559 char buf[BUF_SIZE];
560 uint32_t i;
561
562 if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) {
563 char ipath[BUF_SIZE], rpath[BUF_SIZE];
564 int ni = sprintf(ipath, "%d", p_smp->initial_path[0]);
565 int nr = sprintf(rpath, "%d", p_smp->return_path[0]);
566 for (i = 1; i <= p_smp->hop_count; i++) {
567 ni += sprintf(ipath + ni, ",%d", p_smp->initial_path[i]);
568 nr += sprintf(rpath + nr, ",%d", p_smp->return_path[i]);
569 }
570 snprintf(buf, sizeof(buf),
571 "\n\t\t\tInitial path: %s Return path: %s",
572 ipath, rpath);
573 }
574
575 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 3111: "
576 "Received MAD with error status = 0x%X\n"
577 "\t\t\t%s(%s), attr_mod 0x%x, TID 0x%" PRIx64 "%s\n",
578 cl_ntoh16(status), ib_get_sm_method_str(p_smp->method),
579 ib_get_sm_attr_str(p_smp->attr_id), cl_ntoh32(p_smp->attr_mod),
580 cl_ntoh64(p_smp->trans_id),
581 p_smp->mgmt_class == IB_MCLASS_SUBN_DIR ? buf : "");
582
583 osm_dump_dr_smp_v2(p_log, p_smp, FILE_ID, OSM_LOG_VERBOSE);
584 }
585
586 /*
587 * PARAMETERS
588 *
589 * RETURN VALUES
590 *
591 * NOTES
592 *
593 * SEE ALSO
594 *********/
595
596 /****f* opensm: SM/sm_mad_ctrl_rcv_callback
597 * NAME
598 * sm_mad_ctrl_rcv_callback
599 *
600 * DESCRIPTION
601 * This is the callback from the transport layer for received MADs.
602 *
603 * SYNOPSIS
604 */
sm_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw,IN void * bind_context,IN osm_madw_t * p_req_madw)605 static void sm_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw,
606 IN void *bind_context,
607 IN osm_madw_t * p_req_madw)
608 {
609 osm_sm_mad_ctrl_t *p_ctrl = bind_context;
610 ib_smp_t *p_smp;
611 ib_net16_t status;
612
613 OSM_LOG_ENTER(p_ctrl->p_log);
614
615 CL_ASSERT(p_madw);
616
617 /*
618 A MAD was received from the wire, possibly in response to a request.
619 */
620 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd);
621
622 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs received\n",
623 p_ctrl->p_stats->qp0_mads_rcvd);
624
625 p_smp = osm_madw_get_smp_ptr(p_madw);
626
627 /* if we are closing down simply do nothing */
628 if (osm_exit_flag) {
629 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR,
630 "Ignoring received mad - since we are exiting\n");
631
632 osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_DEBUG);
633
634 /* retire the mad or put it back */
635 if (ib_smp_is_response(p_smp)) {
636 CL_ASSERT(p_madw->resp_expected == FALSE);
637 sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
638 } else if (p_madw->resp_expected == TRUE)
639 sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
640 else
641 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
642
643 goto Exit;
644 }
645
646 if (OSM_LOG_IS_ACTIVE_V2(p_ctrl->p_log, OSM_LOG_FRAMES))
647 osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_FRAMES);
648
649 if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)
650 status = ib_smp_get_status(p_smp);
651 else
652 status = p_smp->status;
653
654 if (status != 0)
655 log_rcv_cb_error(p_ctrl->p_log, p_smp, status);
656
657 switch (p_smp->method) {
658 case IB_MAD_METHOD_GET_RESP:
659 CL_ASSERT(p_req_madw != NULL);
660 sm_mad_ctrl_process_get_resp(p_ctrl, p_madw, p_req_madw);
661 break;
662 case IB_MAD_METHOD_GET:
663 CL_ASSERT(p_req_madw == NULL);
664 sm_mad_ctrl_process_get(p_ctrl, p_madw);
665 break;
666 case IB_MAD_METHOD_TRAP:
667 CL_ASSERT(p_req_madw == NULL);
668 sm_mad_ctrl_process_trap(p_ctrl, p_madw);
669 break;
670 case IB_MAD_METHOD_SET:
671 CL_ASSERT(p_req_madw == NULL);
672 sm_mad_ctrl_process_set(p_ctrl, p_madw);
673 break;
674 case IB_MAD_METHOD_TRAP_REPRESS:
675 CL_ASSERT(p_req_madw != NULL);
676 sm_mad_ctrl_process_trap_repress(p_ctrl, p_madw);
677 break;
678 case IB_MAD_METHOD_SEND:
679 case IB_MAD_METHOD_REPORT:
680 case IB_MAD_METHOD_REPORT_RESP:
681 default:
682 cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
683 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3112: "
684 "Unsupported method = 0x%X\n", p_smp->method);
685 osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR);
686 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
687 goto Exit;
688 }
689
690 Exit:
691 OSM_LOG_EXIT(p_ctrl->p_log);
692 }
693
694 /*
695 * PARAMETERS
696 *
697 * RETURN VALUES
698 *
699 * NOTES
700 *
701 * SEE ALSO
702 *********/
703
704 /****f* opensm: SM/sm_mad_ctrl_send_err_cb
705 * NAME
706 * sm_mad_ctrl_send_err_cb
707 *
708 * DESCRIPTION
709 * This is the callback from the transport layer for send errors
710 * on MADs that were expecting a response.
711 *
712 * SYNOPSIS
713 */
sm_mad_ctrl_send_err_cb(IN void * context,IN osm_madw_t * p_madw)714 static void sm_mad_ctrl_send_err_cb(IN void *context, IN osm_madw_t * p_madw)
715 {
716 osm_sm_mad_ctrl_t *p_ctrl = context;
717 ib_api_status_t status;
718 ib_smp_t *p_smp;
719
720 OSM_LOG_ENTER(p_ctrl->p_log);
721
722 CL_ASSERT(p_madw);
723
724 p_smp = osm_madw_get_smp_ptr(p_madw);
725 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3113: "
726 "MAD completed in error (%s): "
727 "%s(%s), attr_mod 0x%x, TID 0x%" PRIx64 "\n",
728 ib_get_err_str(p_madw->status),
729 ib_get_sm_method_str(p_smp->method),
730 ib_get_sm_attr_str(p_smp->attr_id), cl_ntoh32(p_smp->attr_mod),
731 cl_ntoh64(p_smp->trans_id));
732
733 /*
734 If this was a SubnSet MAD, then this error might indicate a problem
735 in configuring the subnet. In this case - need to mark that there was
736 such a problem. The subnet will not be up, and the next sweep should
737 be a heavy sweep as well.
738 */
739 if (p_smp->method == IB_MAD_METHOD_SET &&
740 (p_smp->attr_id == IB_MAD_ATTR_PORT_INFO ||
741 p_smp->attr_id == IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO ||
742 p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL ||
743 p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO ||
744 p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL ||
745 p_smp->attr_id == IB_MAD_ATTR_P_KEY_TABLE)) {
746 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3119: "
747 "Set method failed for attribute 0x%X (%s)\n",
748 cl_ntoh16(p_smp->attr_id),
749 ib_get_sm_attr_str(p_smp->attr_id));
750 p_ctrl->p_subn->subnet_initialization_error = TRUE;
751 } else if (p_madw->status == IB_TIMEOUT &&
752 p_smp->method == IB_MAD_METHOD_GET) {
753 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3120: "
754 "Timeout while getting attribute 0x%X (%s); "
755 "Possible mis-set mkey?\n",
756 cl_ntoh16(p_smp->attr_id),
757 ib_get_sm_attr_str(p_smp->attr_id));
758 }
759
760 osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_VERBOSE);
761
762 /*
763 Since we did not get any response we suspect the DR path
764 used for the target port.
765 Find it and replace it with an alternate path.
766 This is true only if the destination lid is not 0xFFFF, since
767 then we are aiming for a specific path and not specific destination
768 lid.
769 */
770 /* For now - do not add the alternate dr path to the release */
771 #if 0
772 if (p_madw->mad_addr.dest_lid != 0xFFFF) {
773 osm_physp_t *p_physp = osm_get_physp_by_mad_addr(p_ctrl->p_log,
774 p_ctrl->p_subn,
775 &(p_madw->
776 mad_addr));
777 if (!p_physp) {
778 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3114: "
779 "Failed to find the corresponding phys port\n");
780 } else {
781 osm_physp_replace_dr_path_with_alternate_dr_path
782 (p_ctrl->p_log, p_ctrl->p_subn, p_physp,
783 p_madw->h_bind);
784 }
785 }
786 #endif
787
788 /*
789 An error occurred. No response was received to a request MAD.
790 Retire the original request MAD.
791 */
792 sm_mad_ctrl_update_wire_stats(p_ctrl);
793
794 if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) {
795 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
796 "Posting Dispatcher message %s\n",
797 osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw)));
798
799 status = cl_disp_post(p_ctrl->h_disp,
800 osm_madw_get_err_msg(p_madw), p_madw,
801 sm_mad_ctrl_disp_done_callback, p_ctrl);
802 if (status != CL_SUCCESS)
803 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3115: "
804 "Dispatcher post message failed (%s)\n",
805 CL_STATUS_MSG(status));
806 } else
807 /*
808 No error message was provided, just retire the MAD.
809 */
810 sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
811
812 OSM_LOG_EXIT(p_ctrl->p_log);
813 }
814
815 /*
816 * PARAMETERS
817 *
818 * RETURN VALUES
819 *
820 * NOTES
821 *
822 * SEE ALSO
823 *********/
824
osm_sm_mad_ctrl_construct(IN osm_sm_mad_ctrl_t * p_ctrl)825 void osm_sm_mad_ctrl_construct(IN osm_sm_mad_ctrl_t * p_ctrl)
826 {
827 CL_ASSERT(p_ctrl);
828 memset(p_ctrl, 0, sizeof(*p_ctrl));
829 p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
830 }
831
osm_sm_mad_ctrl_destroy(IN osm_sm_mad_ctrl_t * p_ctrl)832 void osm_sm_mad_ctrl_destroy(IN osm_sm_mad_ctrl_t * p_ctrl)
833 {
834 CL_ASSERT(p_ctrl);
835
836 if (p_ctrl->h_bind != CL_DISP_INVALID_HANDLE)
837 osm_vendor_unbind(p_ctrl->h_bind);
838 cl_disp_unregister(p_ctrl->h_disp);
839 }
840
osm_sm_mad_ctrl_init(IN osm_sm_mad_ctrl_t * p_ctrl,IN osm_subn_t * p_subn,IN osm_mad_pool_t * p_mad_pool,IN osm_vl15_t * p_vl15,IN osm_vendor_t * p_vendor,IN osm_log_t * p_log,IN osm_stats_t * p_stats,IN cl_plock_t * p_lock,IN cl_dispatcher_t * p_disp)841 ib_api_status_t osm_sm_mad_ctrl_init(IN osm_sm_mad_ctrl_t * p_ctrl,
842 IN osm_subn_t * p_subn,
843 IN osm_mad_pool_t * p_mad_pool,
844 IN osm_vl15_t * p_vl15,
845 IN osm_vendor_t * p_vendor,
846 IN osm_log_t * p_log,
847 IN osm_stats_t * p_stats,
848 IN cl_plock_t * p_lock,
849 IN cl_dispatcher_t * p_disp)
850 {
851 ib_api_status_t status = IB_SUCCESS;
852
853 OSM_LOG_ENTER(p_log);
854
855 osm_sm_mad_ctrl_construct(p_ctrl);
856
857 p_ctrl->p_subn = p_subn;
858 p_ctrl->p_log = p_log;
859 p_ctrl->p_disp = p_disp;
860 p_ctrl->p_mad_pool = p_mad_pool;
861 p_ctrl->p_vendor = p_vendor;
862 p_ctrl->p_stats = p_stats;
863 p_ctrl->p_lock = p_lock;
864 p_ctrl->p_vl15 = p_vl15;
865
866 p_ctrl->h_disp = cl_disp_register(p_disp, CL_DISP_MSGID_NONE, NULL,
867 NULL);
868
869 if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) {
870 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 3116: "
871 "Dispatcher registration failed\n");
872 status = IB_INSUFFICIENT_RESOURCES;
873 goto Exit;
874 }
875
876 Exit:
877 OSM_LOG_EXIT(p_log);
878 return status;
879 }
880
osm_sm_mad_ctrl_bind(IN osm_sm_mad_ctrl_t * p_ctrl,IN ib_net64_t port_guid)881 ib_api_status_t osm_sm_mad_ctrl_bind(IN osm_sm_mad_ctrl_t * p_ctrl,
882 IN ib_net64_t port_guid)
883 {
884 osm_bind_info_t bind_info;
885 ib_api_status_t status = IB_SUCCESS;
886
887 OSM_LOG_ENTER(p_ctrl->p_log);
888
889 if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) {
890 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3117: "
891 "Multiple binds not allowed\n");
892 status = IB_ERROR;
893 goto Exit;
894 }
895
896 bind_info.class_version = 1;
897 bind_info.is_report_processor = FALSE;
898 bind_info.is_responder = TRUE;
899 bind_info.is_trap_processor = TRUE;
900 bind_info.mad_class = IB_MCLASS_SUBN_DIR;
901 bind_info.port_guid = port_guid;
902 bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE;
903 bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE;
904 bind_info.timeout = p_ctrl->p_subn->opt.transaction_timeout;
905 bind_info.retries = p_ctrl->p_subn->opt.transaction_retries;
906
907 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
908 "Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
909
910 p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor, &bind_info,
911 p_ctrl->p_mad_pool,
912 sm_mad_ctrl_rcv_callback,
913 sm_mad_ctrl_send_err_cb, p_ctrl);
914
915 if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) {
916 status = IB_ERROR;
917 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3118: "
918 "Vendor specific bind failed\n");
919 goto Exit;
920 }
921
922 Exit:
923 OSM_LOG_EXIT(p_ctrl->p_log);
924 return status;
925 }
926