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.
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:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
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.
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
38 * Implementation of osm_sa_mad_ctrl_t.
39 * This object is part of the SA object.
44 #endif /* HAVE_CONFIG_H */
47 #include <complib/cl_debug.h>
48 #include <iba/ib_types.h>
49 #include <vendor/osm_vendor_api.h>
50 #include <opensm/osm_sa_mad_ctrl.h>
51 #include <opensm/osm_msgdef.h>
52 #include <opensm/osm_helper.h>
53 #include <opensm/osm_sa.h>
55 /****f* opensm: SA/__osm_sa_mad_ctrl_disp_done_callback
57 * __osm_sa_mad_ctrl_disp_done_callback
60 * This function is the Dispatcher callback that indicates
61 * a received MAD has been processed by the recipient.
66 __osm_sa_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data)
68 osm_sa_mad_ctrl_t *const p_ctrl = (osm_sa_mad_ctrl_t *) context;
69 osm_madw_t *const p_madw = (osm_madw_t *) p_data;
71 OSM_LOG_ENTER(p_ctrl->p_log);
75 Return the MAD & wrapper to the pool.
77 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
78 OSM_LOG_EXIT(p_ctrl->p_log);
83 /****f* opensm: SA/__osm_sa_mad_ctrl_process
85 * __osm_sa_mad_ctrl_process
88 * This function handles known methods for received MADs.
93 __osm_sa_mad_ctrl_process(IN osm_sa_mad_ctrl_t * const p_ctrl,
94 IN osm_madw_t * p_madw)
96 ib_sa_mad_t *p_sa_mad;
98 cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;
99 uint64_t last_dispatched_msg_queue_time_msec;
100 uint32_t num_messages;
102 OSM_LOG_ENTER(p_ctrl->p_log);
105 If the dispatcher is showing us that it is overloaded
106 there is no point in placing the request in. We should instead provide
107 immediate response - IB_RESOURCE_BUSY
109 The dispatcher reports back the number of outstanding messages and the
110 time the last message stayed in the queue.
111 HACK: Actually, we cannot send a mad from within the receive callback;
112 thus - we will just drop it.
114 cl_disp_get_queue_status(p_ctrl->h_disp,
116 &last_dispatched_msg_queue_time_msec);
117 if ((num_messages > 1) &&
118 (p_ctrl->p_subn->opt.max_msg_fifo_timeout) &&
119 (last_dispatched_msg_queue_time_msec >
120 p_ctrl->p_subn->opt.max_msg_fifo_timeout)) {
121 OSM_LOG(p_ctrl->p_log, OSM_LOG_INFO,
122 /* "Responding BUSY status since the dispatcher is already" */
123 "Dropping MAD since the dispatcher is already"
124 " overloaded with %u messages and queue time of:"
125 "%" PRIu64 "[msec]\n",
126 num_messages, last_dispatched_msg_queue_time_msec);
128 /* send a busy response */
129 /* osm_sa_send_error(p_ctrl->p_resp, p_madw, IB_RESOURCE_BUSY); */
131 /* return the request to the pool */
132 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
137 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
140 Note that attr_id (like the rest of the MAD) is in
143 switch (p_sa_mad->attr_id) {
144 case IB_MAD_ATTR_CLASS_PORT_INFO:
145 msg_id = OSM_MSG_MAD_CLASS_PORT_INFO;
148 case IB_MAD_ATTR_NODE_RECORD:
149 msg_id = OSM_MSG_MAD_NODE_RECORD;
152 case IB_MAD_ATTR_PORTINFO_RECORD:
153 msg_id = OSM_MSG_MAD_PORTINFO_RECORD;
156 case IB_MAD_ATTR_LINK_RECORD:
157 msg_id = OSM_MSG_MAD_LINK_RECORD;
160 case IB_MAD_ATTR_SMINFO_RECORD:
161 msg_id = OSM_MSG_MAD_SMINFO_RECORD;
164 case IB_MAD_ATTR_SERVICE_RECORD:
165 msg_id = OSM_MSG_MAD_SERVICE_RECORD;
168 case IB_MAD_ATTR_PATH_RECORD:
169 msg_id = OSM_MSG_MAD_PATH_RECORD;
172 case IB_MAD_ATTR_MCMEMBER_RECORD:
173 msg_id = OSM_MSG_MAD_MCMEMBER_RECORD;
176 case IB_MAD_ATTR_INFORM_INFO:
177 msg_id = OSM_MSG_MAD_INFORM_INFO;
180 case IB_MAD_ATTR_VLARB_RECORD:
181 msg_id = OSM_MSG_MAD_VL_ARB_RECORD;
184 case IB_MAD_ATTR_SLVL_RECORD:
185 msg_id = OSM_MSG_MAD_SLVL_TBL_RECORD;
188 case IB_MAD_ATTR_PKEY_TBL_RECORD:
189 msg_id = OSM_MSG_MAD_PKEY_TBL_RECORD;
192 case IB_MAD_ATTR_LFT_RECORD:
193 msg_id = OSM_MSG_MAD_LFT_RECORD;
196 case IB_MAD_ATTR_GUIDINFO_RECORD:
197 msg_id = OSM_MSG_MAD_GUIDINFO_RECORD;
200 case IB_MAD_ATTR_INFORM_INFO_RECORD:
201 msg_id = OSM_MSG_MAD_INFORM_INFO_RECORD;
204 case IB_MAD_ATTR_SWITCH_INFO_RECORD:
205 msg_id = OSM_MSG_MAD_SWITCH_INFO_RECORD;
208 case IB_MAD_ATTR_MFT_RECORD:
209 msg_id = OSM_MSG_MAD_MFT_RECORD;
212 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
213 case IB_MAD_ATTR_MULTIPATH_RECORD:
214 msg_id = OSM_MSG_MAD_MULTIPATH_RECORD;
219 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A01: "
220 "Unsupported attribute = 0x%X\n",
221 cl_ntoh16(p_sa_mad->attr_id));
222 osm_dump_sa_mad(p_ctrl->p_log, p_sa_mad, OSM_LOG_ERROR);
225 if (msg_id != CL_DISP_MSGID_NONE) {
227 Post this MAD to the dispatcher for asynchronous
228 processing by the appropriate controller.
231 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
232 "Posting Dispatcher message %s\n",
233 osm_get_disp_msg_str(msg_id));
235 status = cl_disp_post(p_ctrl->h_disp,
238 __osm_sa_mad_ctrl_disp_done_callback,
241 if (status != CL_SUCCESS) {
242 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A02: "
243 "Dispatcher post message failed (%s) for attribute = 0x%X\n",
244 CL_STATUS_MSG(status),
245 cl_ntoh16(p_sa_mad->attr_id));
247 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
252 There is an unknown MAD attribute type for which there is
253 no recipient. Simply retire the MAD here.
255 cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown);
256 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
260 OSM_LOG_EXIT(p_ctrl->p_log);
273 /****f* opensm: SA/__osm_sa_mad_ctrl_rcv_callback
275 * __osm_sa_mad_ctrl_rcv_callback
278 * This is the callback from the transport layer for received MADs.
283 __osm_sa_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw,
284 IN void *bind_context,
285 IN osm_madw_t * p_req_madw)
287 osm_sa_mad_ctrl_t *p_ctrl = (osm_sa_mad_ctrl_t *) bind_context;
288 ib_sa_mad_t *p_sa_mad;
290 OSM_LOG_ENTER(p_ctrl->p_log);
295 A MAD was received from the wire, possibly in response to a request.
297 cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd);
299 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
300 "%u SA MADs received\n", p_ctrl->p_stats->sa_mads_rcvd);
303 * C15-0.1.3 requires not responding to any MAD if the SM is
304 * not in active state!
305 * We will not respond if the sm_state is not MASTER, or if the
306 * first_time_master_sweep flag (of the subnet) is TRUE - this
307 * flag indicates that the master still didn't finish its first
308 * sweep, so the subnet is not up and stable yet.
310 if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) {
311 cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored);
312 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
313 "Received SA MAD while SM not MASTER. MAD ignored\n");
314 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
317 if (p_ctrl->p_subn->first_time_master_sweep == TRUE) {
318 cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored);
319 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
320 "Received SA MAD while SM in first sweep. MAD ignored\n");
321 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
325 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
327 if (osm_log_is_active(p_ctrl->p_log, OSM_LOG_FRAMES))
328 osm_dump_sa_mad(p_ctrl->p_log, p_sa_mad, OSM_LOG_FRAMES);
331 * C15-0.1.5 - Table 185: SA Header - p884
332 * SM_key should be either 0 or match the current SM_Key
333 * otherwise discard the MAD.
335 if ((p_sa_mad->sm_key != 0) &&
336 (p_sa_mad->sm_key != p_ctrl->p_subn->opt.sa_key)) {
337 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A04: "
338 "Non-Zero SA MAD SM_Key: 0x%" PRIx64 " != SM_Key: 0x%"
339 PRIx64 "; MAD ignored\n", cl_ntoh64(p_sa_mad->sm_key),
340 cl_ntoh64(p_ctrl->p_subn->opt.sa_key)
342 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
346 switch (p_sa_mad->method) {
347 case IB_MAD_METHOD_REPORT_RESP:
348 /* we do not really do anything with report represses -
349 just retire the transaction */
350 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
351 "Received Report Repress. Retiring the transaction\n");
354 osm_mad_pool_put(p_ctrl->p_mad_pool, p_req_madw);
355 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
359 case IB_MAD_METHOD_GET:
360 case IB_MAD_METHOD_GETTABLE:
361 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
362 case IB_MAD_METHOD_GETMULTI:
364 case IB_MAD_METHOD_SET:
365 case IB_MAD_METHOD_DELETE:
366 __osm_sa_mad_ctrl_process(p_ctrl, p_madw);
370 cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown);
371 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A05: "
372 "Unsupported method = 0x%X\n", p_sa_mad->method);
373 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
378 OSM_LOG_EXIT(p_ctrl->p_log);
391 /****f* opensm: SA/__osm_sa_mad_ctrl_send_err_callback
393 * __osm_sa_mad_ctrl_send_err_callback
396 * This is the callback from the transport layer for send errors
397 * on MADs that were expecting a response.
402 __osm_sa_mad_ctrl_send_err_callback(IN void *bind_context,
403 IN osm_madw_t * p_madw)
405 osm_sa_mad_ctrl_t *p_ctrl = (osm_sa_mad_ctrl_t *) bind_context;
408 OSM_LOG_ENTER(p_ctrl->p_log);
410 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A06: "
411 "MAD transaction completed in error\n");
414 We should never be here since the SA never originates a request.
415 Unless we generated a Report(Notice)
421 An error occurred. No response was received to a request MAD.
422 Retire the original request MAD.
425 osm_dump_sa_mad(p_ctrl->p_log, osm_madw_get_sa_mad_ptr(p_madw),
428 /* __osm_sm_mad_ctrl_update_wire_stats( p_ctrl ); */
430 if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) {
431 OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
432 "Posting Dispatcher message %s\n",
433 osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw)));
435 status = cl_disp_post(p_ctrl->h_disp,
436 osm_madw_get_err_msg(p_madw),
438 __osm_sa_mad_ctrl_disp_done_callback,
440 if (status != CL_SUCCESS) {
441 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A07: "
442 "Dispatcher post message failed (%s)\n",
443 CL_STATUS_MSG(status));
447 No error message was provided, just retire the MAD.
449 osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
452 OSM_LOG_EXIT(p_ctrl->p_log);
465 /**********************************************************************
466 **********************************************************************/
467 void osm_sa_mad_ctrl_construct(IN osm_sa_mad_ctrl_t * const p_ctrl)
470 memset(p_ctrl, 0, sizeof(*p_ctrl));
471 p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
474 /**********************************************************************
475 **********************************************************************/
476 void osm_sa_mad_ctrl_destroy(IN osm_sa_mad_ctrl_t * const p_ctrl)
479 cl_disp_unregister(p_ctrl->h_disp);
482 /**********************************************************************
483 **********************************************************************/
485 osm_sa_mad_ctrl_init(IN osm_sa_mad_ctrl_t * const p_ctrl,
487 IN osm_mad_pool_t * const p_mad_pool,
488 IN osm_vendor_t * const p_vendor,
489 IN osm_subn_t * const p_subn,
490 IN osm_log_t * const p_log,
491 IN osm_stats_t * const p_stats,
492 IN cl_dispatcher_t * const p_disp)
494 ib_api_status_t status = IB_SUCCESS;
496 OSM_LOG_ENTER(p_log);
498 osm_sa_mad_ctrl_construct(p_ctrl);
501 p_ctrl->p_log = p_log;
502 p_ctrl->p_disp = p_disp;
503 p_ctrl->p_mad_pool = p_mad_pool;
504 p_ctrl->p_vendor = p_vendor;
505 p_ctrl->p_stats = p_stats;
506 p_ctrl->p_subn = p_subn;
508 p_ctrl->h_disp = cl_disp_register(p_disp,
509 CL_DISP_MSGID_NONE, NULL, p_ctrl);
511 if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) {
512 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1A08: "
513 "Dispatcher registration failed\n");
514 status = IB_INSUFFICIENT_RESOURCES;
523 /**********************************************************************
524 **********************************************************************/
526 osm_sa_mad_ctrl_bind(IN osm_sa_mad_ctrl_t * const p_ctrl,
527 IN const ib_net64_t port_guid)
529 osm_bind_info_t bind_info;
530 ib_api_status_t status = IB_SUCCESS;
532 OSM_LOG_ENTER(p_ctrl->p_log);
534 if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) {
535 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A09: "
536 "Multiple binds not allowed\n");
541 bind_info.class_version = 2;
542 bind_info.is_responder = TRUE;
543 bind_info.is_report_processor = FALSE;
544 bind_info.is_trap_processor = FALSE;
545 bind_info.mad_class = IB_MCLASS_SUBN_ADM;
546 bind_info.port_guid = port_guid;
547 bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
548 bind_info.send_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;
550 OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE,
551 "Binding to port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid));
553 p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor,
556 __osm_sa_mad_ctrl_rcv_callback,
557 __osm_sa_mad_ctrl_send_err_callback,
560 if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) {
562 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A10: "
563 "Vendor specific bind failed (%s)\n",
564 ib_get_err_str(status));
569 OSM_LOG_EXIT(p_ctrl->p_log);
573 /**********************************************************************
574 **********************************************************************/
575 ib_api_status_t osm_sa_mad_ctrl_unbind(IN osm_sa_mad_ctrl_t * const p_ctrl)
577 ib_api_status_t status = IB_SUCCESS;
579 OSM_LOG_ENTER(p_ctrl->p_log);
581 if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) {
582 OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A11: "
583 "No previous bind\n");
588 osm_vendor_unbind(p_ctrl->h_bind);
590 OSM_LOG_EXIT(p_ctrl->p_log);