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 * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved.
7 * This software is available to you under a choice of one of two
8 * licenses. You may choose to be licensed under the terms of the GNU
9 * General Public License (GPL) Version 2, available from the file
10 * COPYING in the main directory of this source tree, or the
11 * OpenIB.org BSD license below:
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
17 * - Redistributions of source code must retain the above
18 * copyright notice, this list of conditions and the following
21 * - Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials
24 * provided with the distribution.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39 * Implementation of osm_sa_t.
40 * This object represents the Subnet Administration object.
41 * This object is part of the opensm family of objects.
46 #endif /* HAVE_CONFIG_H */
52 #include <sys/types.h>
54 #include <complib/cl_qmap.h>
55 #include <complib/cl_passivelock.h>
56 #include <complib/cl_debug.h>
57 #include <iba/ib_types.h>
58 #include <opensm/osm_sa.h>
59 #include <opensm/osm_madw.h>
60 #include <opensm/osm_log.h>
61 #include <opensm/osm_subnet.h>
62 #include <opensm/osm_mad_pool.h>
63 #include <opensm/osm_msgdef.h>
64 #include <opensm/osm_opensm.h>
65 #include <opensm/osm_multicast.h>
66 #include <opensm/osm_inform.h>
67 #include <opensm/osm_service.h>
68 #include <opensm/osm_helper.h>
69 #include <vendor/osm_vendor_api.h>
71 #define OSM_SA_INITIAL_TID_VALUE 0xabc
73 extern void osm_cpi_rcv_process(IN void *context, IN void *data);
74 extern void osm_gir_rcv_process(IN void *context, IN void *data);
75 extern void osm_infr_rcv_process(IN void *context, IN void *data);
76 extern void osm_infir_rcv_process(IN void *context, IN void *data);
77 extern void osm_lftr_rcv_process(IN void *context, IN void *data);
78 extern void osm_lr_rcv_process(IN void *context, IN void *data);
79 extern void osm_mcmr_rcv_process(IN void *context, IN void *data);
80 extern void osm_mftr_rcv_process(IN void *context, IN void *data);
81 extern void osm_mpr_rcv_process(IN void *context, IN void *data);
82 extern void osm_nr_rcv_process(IN void *context, IN void *data);
83 extern void osm_pr_rcv_process(IN void *context, IN void *data);
84 extern void osm_pkey_rec_rcv_process(IN void *context, IN void *data);
85 extern void osm_pir_rcv_process(IN void *context, IN void *data);
86 extern void osm_sr_rcv_process(IN void *context, IN void *data);
87 extern void osm_slvl_rec_rcv_process(IN void *context, IN void *data);
88 extern void osm_smir_rcv_process(IN void *context, IN void *data);
89 extern void osm_sir_rcv_process(IN void *context, IN void *data);
90 extern void osm_vlarb_rec_rcv_process(IN void *context, IN void *data);
91 extern void osm_sr_rcv_lease_cb(IN void *context);
93 /**********************************************************************
94 **********************************************************************/
95 void osm_sa_construct(IN osm_sa_t * const p_sa)
97 memset(p_sa, 0, sizeof(*p_sa));
98 p_sa->state = OSM_SA_STATE_INIT;
99 p_sa->sa_trans_id = OSM_SA_INITIAL_TID_VALUE;
101 cl_timer_construct(&p_sa->sr_timer);
104 /**********************************************************************
105 **********************************************************************/
106 void osm_sa_shutdown(IN osm_sa_t * const p_sa)
108 ib_api_status_t status;
109 OSM_LOG_ENTER(p_sa->p_log);
111 cl_timer_stop(&p_sa->sr_timer);
113 /* unbind from the mad service */
114 status = osm_sa_mad_ctrl_unbind(&p_sa->mad_ctrl);
116 /* remove any registered dispatcher message */
117 cl_disp_unregister(p_sa->nr_disp_h);
118 cl_disp_unregister(p_sa->pir_disp_h);
119 cl_disp_unregister(p_sa->gir_disp_h);
120 cl_disp_unregister(p_sa->lr_disp_h);
121 cl_disp_unregister(p_sa->pr_disp_h);
122 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
123 cl_disp_unregister(p_sa->mpr_disp_h);
125 cl_disp_unregister(p_sa->smir_disp_h);
126 cl_disp_unregister(p_sa->mcmr_disp_h);
127 cl_disp_unregister(p_sa->sr_disp_h);
128 cl_disp_unregister(p_sa->infr_disp_h);
129 cl_disp_unregister(p_sa->infir_disp_h);
130 cl_disp_unregister(p_sa->vlarb_disp_h);
131 cl_disp_unregister(p_sa->slvl_disp_h);
132 cl_disp_unregister(p_sa->pkey_disp_h);
133 cl_disp_unregister(p_sa->lft_disp_h);
134 cl_disp_unregister(p_sa->sir_disp_h);
135 cl_disp_unregister(p_sa->mft_disp_h);
136 osm_sa_mad_ctrl_destroy(&p_sa->mad_ctrl);
138 OSM_LOG_EXIT(p_sa->p_log);
141 /**********************************************************************
142 **********************************************************************/
143 void osm_sa_destroy(IN osm_sa_t * const p_sa)
145 OSM_LOG_ENTER(p_sa->p_log);
147 p_sa->state = OSM_SA_STATE_INIT;
149 cl_timer_destroy(&p_sa->sr_timer);
151 OSM_LOG_EXIT(p_sa->p_log);
154 /**********************************************************************
155 **********************************************************************/
157 osm_sa_init(IN osm_sm_t * const p_sm,
158 IN osm_sa_t * const p_sa,
159 IN osm_subn_t * const p_subn,
160 IN osm_vendor_t * const p_vendor,
161 IN osm_mad_pool_t * const p_mad_pool,
162 IN osm_log_t * const p_log,
163 IN osm_stats_t * const p_stats,
164 IN cl_dispatcher_t * const p_disp, IN cl_plock_t * const p_lock)
166 ib_api_status_t status = IB_SUCCESS;
168 OSM_LOG_ENTER(p_log);
171 p_sa->p_subn = p_subn;
172 p_sa->p_vendor = p_vendor;
173 p_sa->p_mad_pool = p_mad_pool;
175 p_sa->p_disp = p_disp;
176 p_sa->p_lock = p_lock;
178 p_sa->state = OSM_SA_STATE_READY;
180 status = osm_sa_mad_ctrl_init(&p_sa->mad_ctrl,
184 p_subn, p_log, p_stats, p_disp);
185 if (status != IB_SUCCESS)
188 status = cl_timer_init(&p_sa->sr_timer, osm_sr_rcv_lease_cb, p_sa);
189 if (status != IB_SUCCESS)
192 p_sa->cpi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_CLASS_PORT_INFO,
193 osm_cpi_rcv_process, p_sa);
194 if (p_sa->cpi_disp_h == CL_DISP_INVALID_HANDLE)
197 p_sa->nr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_RECORD,
198 osm_nr_rcv_process, p_sa);
199 if (p_sa->nr_disp_h == CL_DISP_INVALID_HANDLE)
202 p_sa->pir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORTINFO_RECORD,
203 osm_pir_rcv_process, p_sa);
204 if (p_sa->pir_disp_h == CL_DISP_INVALID_HANDLE)
207 p_sa->gir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_GUIDINFO_RECORD,
208 osm_gir_rcv_process, p_sa);
209 if (p_sa->gir_disp_h == CL_DISP_INVALID_HANDLE)
212 p_sa->lr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LINK_RECORD,
213 osm_lr_rcv_process, p_sa);
214 if (p_sa->lr_disp_h == CL_DISP_INVALID_HANDLE)
217 p_sa->pr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PATH_RECORD,
218 osm_pr_rcv_process, p_sa);
219 if (p_sa->pr_disp_h == CL_DISP_INVALID_HANDLE)
222 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
224 cl_disp_register(p_disp, OSM_MSG_MAD_MULTIPATH_RECORD,
225 osm_mpr_rcv_process, p_sa);
226 if (p_sa->mpr_disp_h == CL_DISP_INVALID_HANDLE)
230 p_sa->smir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SMINFO_RECORD,
231 osm_smir_rcv_process, p_sa);
232 if (p_sa->smir_disp_h == CL_DISP_INVALID_HANDLE)
236 cl_disp_register(p_disp, OSM_MSG_MAD_MCMEMBER_RECORD,
237 osm_mcmr_rcv_process, p_sa);
238 if (p_sa->mcmr_disp_h == CL_DISP_INVALID_HANDLE)
241 p_sa->sr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SERVICE_RECORD,
242 osm_sr_rcv_process, p_sa);
243 if (p_sa->sr_disp_h == CL_DISP_INVALID_HANDLE)
246 p_sa->infr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO,
247 osm_infr_rcv_process, p_sa);
248 if (p_sa->infr_disp_h == CL_DISP_INVALID_HANDLE)
252 cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO_RECORD,
253 osm_infir_rcv_process, p_sa);
254 if (p_sa->infir_disp_h == CL_DISP_INVALID_HANDLE)
257 p_sa->vlarb_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB_RECORD,
258 osm_vlarb_rec_rcv_process, p_sa);
259 if (p_sa->vlarb_disp_h == CL_DISP_INVALID_HANDLE)
263 cl_disp_register(p_disp, OSM_MSG_MAD_SLVL_TBL_RECORD,
264 osm_slvl_rec_rcv_process, p_sa);
265 if (p_sa->slvl_disp_h == CL_DISP_INVALID_HANDLE)
269 cl_disp_register(p_disp, OSM_MSG_MAD_PKEY_TBL_RECORD,
270 osm_pkey_rec_rcv_process, p_sa);
271 if (p_sa->pkey_disp_h == CL_DISP_INVALID_HANDLE)
274 p_sa->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT_RECORD,
275 osm_lftr_rcv_process, p_sa);
276 if (p_sa->lft_disp_h == CL_DISP_INVALID_HANDLE)
280 cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO_RECORD,
281 osm_sir_rcv_process, p_sa);
282 if (p_sa->sir_disp_h == CL_DISP_INVALID_HANDLE)
285 p_sa->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT_RECORD,
286 osm_mftr_rcv_process, p_sa);
287 if (p_sa->mft_disp_h == CL_DISP_INVALID_HANDLE)
295 /**********************************************************************
296 **********************************************************************/
298 osm_sa_bind(IN osm_sa_t * const p_sa, IN const ib_net64_t port_guid)
300 ib_api_status_t status;
302 OSM_LOG_ENTER(p_sa->p_log);
304 status = osm_sa_mad_ctrl_bind(&p_sa->mad_ctrl, port_guid);
306 if (status != IB_SUCCESS) {
307 OSM_LOG(p_sa->p_log, OSM_LOG_ERROR, "ERR 4C03: "
308 "SA MAD Controller bind failed (%s)\n",
309 ib_get_err_str(status));
314 OSM_LOG_EXIT(p_sa->p_log);
318 ib_api_status_t osm_sa_send(osm_sa_t *sa,
319 IN osm_madw_t * const p_madw,
320 IN boolean_t const resp_expected)
322 ib_api_status_t status;
324 cl_atomic_inc(&sa->p_subn->p_osm->stats.sa_mads_sent);
325 status = osm_vendor_send(p_madw->h_bind, p_madw, resp_expected);
326 if (status != IB_SUCCESS) {
327 cl_atomic_dec(&sa->p_subn->p_osm->stats.sa_mads_sent);
328 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C04: "
329 "osm_vendor_send failed, status = %s\n",
330 ib_get_err_str(status));
336 osm_sa_send_error(IN osm_sa_t * sa,
337 IN const osm_madw_t * const p_madw,
338 IN const ib_net16_t sa_status)
340 osm_madw_t *p_resp_madw;
341 ib_sa_mad_t *p_resp_sa_mad;
342 ib_sa_mad_t *p_sa_mad;
344 OSM_LOG_ENTER(sa->p_log);
346 /* avoid races - if we are exiting - exit */
348 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
349 "Ignoring requested send after exit\n");
353 p_resp_madw = osm_mad_pool_get(sa->p_mad_pool,
354 p_madw->h_bind, MAD_BLOCK_SIZE,
357 if (p_resp_madw == NULL) {
358 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C07: "
359 "Unable to acquire response MAD\n");
363 p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw);
364 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
366 /* Copy the MAD header back into the response mad */
367 *p_resp_sa_mad = *p_sa_mad;
368 p_resp_sa_mad->status = sa_status;
370 if (p_resp_sa_mad->method == IB_MAD_METHOD_SET)
371 p_resp_sa_mad->method = IB_MAD_METHOD_GET;
372 else if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE)
373 p_resp_sa_mad->attr_offset = 0;
375 p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
378 * C15-0.1.5 - always return SM_Key = 0 (table 185 p 884)
380 p_resp_sa_mad->sm_key = 0;
383 * o15-0.2.7 - The PathRecord Attribute ID shall be used in
384 * the response (to a SubnAdmGetMulti(MultiPathRecord)
386 if (p_resp_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD)
387 p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD;
389 if (osm_log_is_active(sa->p_log, OSM_LOG_FRAMES))
390 osm_dump_sa_mad(sa->p_log, p_resp_sa_mad, OSM_LOG_FRAMES);
392 osm_sa_send(sa, p_resp_madw, FALSE);
395 OSM_LOG_EXIT(sa->p_log);
398 void osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size,
405 cl_list_item_t *item;
406 osm_madw_t *resp_madw;
407 ib_sa_mad_t *sa_mad, *resp_sa_mad;
409 #ifndef VENDOR_RMPP_SUPPORT
410 unsigned trim_num_rec;
414 sa_mad = osm_madw_get_sa_mad_ptr(madw);
415 num_rec = cl_qlist_count(list);
419 * If we do a SubnAdmGet and got more than one record it is an error!
421 if (sa_mad->method == IB_MAD_METHOD_GET && num_rec > 1) {
422 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C05: "
423 "Got more than one record for SubnAdmGet (%u)\n",
425 osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
429 #ifndef VENDOR_RMPP_SUPPORT
430 trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / attr_size;
431 if (trim_num_rec < num_rec) {
432 OSM_LOG(sa->p_log, OSM_LOG_VERBOSE,
433 "Number of records:%u trimmed to:%u to fit in one MAD\n",
434 num_rec, trim_num_rec);
435 num_rec = trim_num_rec;
439 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Returning %u records\n", num_rec);
441 if (sa_mad->method == IB_MAD_METHOD_GET && num_rec == 0) {
442 osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RECORDS);
447 * Get a MAD to reply. Address of Mad is in the received mad_wrapper
449 resp_madw = osm_mad_pool_get(sa->p_mad_pool, madw->h_bind,
450 num_rec * attr_size + IB_SA_MAD_HDR_SIZE,
453 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C06: "
454 "osm_mad_pool_get failed\n");
455 osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RESOURCES);
459 resp_sa_mad = osm_madw_get_sa_mad_ptr(resp_madw);
462 Copy the MAD header back into the response mad.
463 Set the 'R' bit and the payload length,
464 Then copy all records from the list into the response payload.
467 memcpy(resp_sa_mad, sa_mad, IB_SA_MAD_HDR_SIZE);
468 if (resp_sa_mad->method == IB_MAD_METHOD_SET)
469 resp_sa_mad->method = IB_MAD_METHOD_GET;
470 resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
471 /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
472 resp_sa_mad->sm_key = 0;
474 /* Fill in the offset (paylen will be done by the rmpp SAR) */
475 resp_sa_mad->attr_offset = num_rec ? ib_get_attr_offset(attr_size) : 0;
477 p = ib_sa_mad_get_payload_ptr(resp_sa_mad);
479 #ifndef VENDOR_RMPP_SUPPORT
480 /* we support only one packet RMPP - so we will set the first and
481 last flags for gettable */
482 if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) {
483 resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
484 resp_sa_mad->rmpp_flags =
485 IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST |
489 /* forcefully define the packet as RMPP one */
490 if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
491 resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
494 for (i = 0; i < num_rec; i++) {
495 item = cl_qlist_remove_head(list);
496 memcpy(p, ((struct item_data *)item)->data, attr_size);
501 osm_sa_send(sa, resp_madw, FALSE);
503 osm_dump_sa_mad(sa->p_log, resp_sa_mad, OSM_LOG_FRAMES);
505 /* need to set the mem free ... */
506 item = cl_qlist_remove_head(list);
507 while (item != cl_qlist_end(list)) {
509 item = cl_qlist_remove_head(list);
513 /**********************************************************************
514 **********************************************************************/
520 struct opensm_dump_context {
526 opensm_dump_to_file(osm_opensm_t * p_osm, const char *file_name,
527 void (*dump_func) (osm_opensm_t * p_osm, FILE * file))
532 snprintf(path, sizeof(path), "%s/%s",
533 p_osm->subn.opt.dump_files_dir, file_name);
535 file = fopen(path, "w");
537 OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C01: "
538 "cannot open file \'%s\': %s\n",
539 file_name, strerror(errno));
543 chmod(path, S_IRUSR | S_IWUSR);
545 dump_func(p_osm, file);
551 static void mcast_mgr_dump_one_port(cl_map_item_t * p_map_item, void *cxt)
553 FILE *file = ((struct opensm_dump_context *)cxt)->file;
554 osm_mcm_port_t *p_mcm_port = (osm_mcm_port_t *) p_map_item;
556 fprintf(file, "mcm_port: "
557 "port_gid=0x%016" PRIx64 ":0x%016" PRIx64 " "
558 "scope_state=0x%02x proxy_join=0x%x" "\n\n",
559 cl_ntoh64(p_mcm_port->port_gid.unicast.prefix),
560 cl_ntoh64(p_mcm_port->port_gid.unicast.interface_id),
561 p_mcm_port->scope_state, p_mcm_port->proxy_join);
564 static void sa_dump_one_mgrp(osm_mgrp_t *p_mgrp, void *cxt)
566 struct opensm_dump_context dump_context;
567 osm_opensm_t *p_osm = ((struct opensm_dump_context *)cxt)->p_osm;
568 FILE *file = ((struct opensm_dump_context *)cxt)->file;
570 fprintf(file, "MC Group 0x%04x %s:"
571 " mgid=0x%016" PRIx64 ":0x%016" PRIx64
572 " port_gid=0x%016" PRIx64 ":0x%016" PRIx64
573 " qkey=0x%08x mlid=0x%04x mtu=0x%02x tclass=0x%02x"
574 " pkey=0x%04x rate=0x%02x pkt_life=0x%02x sl_flow_hop=0x%08x"
575 " scope_state=0x%02x proxy_join=0x%x" "\n\n",
576 cl_ntoh16(p_mgrp->mlid),
577 p_mgrp->well_known ? " (well known)" : "",
578 cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
579 cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
580 cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.prefix),
581 cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.interface_id),
582 cl_ntoh32(p_mgrp->mcmember_rec.qkey),
583 cl_ntoh16(p_mgrp->mcmember_rec.mlid),
584 p_mgrp->mcmember_rec.mtu,
585 p_mgrp->mcmember_rec.tclass,
586 cl_ntoh16(p_mgrp->mcmember_rec.pkey),
587 p_mgrp->mcmember_rec.rate,
588 p_mgrp->mcmember_rec.pkt_life,
589 cl_ntoh32(p_mgrp->mcmember_rec.sl_flow_hop),
590 p_mgrp->mcmember_rec.scope_state,
591 p_mgrp->mcmember_rec.proxy_join);
593 dump_context.p_osm = p_osm;
594 dump_context.file = file;
596 cl_qmap_apply_func(&p_mgrp->mcm_port_tbl,
597 mcast_mgr_dump_one_port, &dump_context);
600 static void sa_dump_one_inform(cl_list_item_t * p_list_item, void *cxt)
602 FILE *file = ((struct opensm_dump_context *)cxt)->file;
603 osm_infr_t *p_infr = (osm_infr_t *) p_list_item;
604 ib_inform_info_record_t *p_iir = &p_infr->inform_record;
606 fprintf(file, "InformInfo Record:"
607 " subscriber_gid=0x%016" PRIx64 ":0x%016" PRIx64
608 " subscriber_enum=0x%x"
610 " gid=0x%016" PRIx64 ":0x%016" PRIx64
611 " lid_range_begin=0x%x"
612 " lid_range_end=0x%x"
617 " qpn_resp_time_val=0x%x"
619 " rep_addr: lid=0x%04x path_bits=0x%02x static_rate=0x%02x"
620 " remote_qp=0x%08x remote_qkey=0x%08x pkey_ix=0x%04x sl=0x%02x"
622 cl_ntoh64(p_iir->subscriber_gid.unicast.prefix),
623 cl_ntoh64(p_iir->subscriber_gid.unicast.interface_id),
624 cl_ntoh16(p_iir->subscriber_enum),
625 cl_ntoh64(p_iir->inform_info.gid.unicast.prefix),
626 cl_ntoh64(p_iir->inform_info.gid.unicast.interface_id),
627 cl_ntoh16(p_iir->inform_info.lid_range_begin),
628 cl_ntoh16(p_iir->inform_info.lid_range_end),
629 p_iir->inform_info.is_generic,
630 p_iir->inform_info.subscribe,
631 cl_ntoh16(p_iir->inform_info.trap_type),
632 cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num),
633 cl_ntoh32(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val),
634 cl_ntoh32(ib_inform_info_get_prod_type(&p_iir->inform_info)),
635 cl_ntoh16(p_infr->report_addr.dest_lid),
636 p_infr->report_addr.path_bits,
637 p_infr->report_addr.static_rate,
638 cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qp),
639 cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qkey),
640 p_infr->report_addr.addr_type.gsi.pkey_ix,
641 p_infr->report_addr.addr_type.gsi.service_level);
644 static void sa_dump_one_service(cl_list_item_t * p_list_item, void *cxt)
646 FILE *file = ((struct opensm_dump_context *)cxt)->file;
647 osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item;
648 ib_service_record_t *p_sr = &p_svcr->service_record;
650 fprintf(file, "Service Record: id=0x%016" PRIx64
651 " gid=0x%016" PRIx64 ":0x%016" PRIx64
654 " key=0x%02x%02x%02x%02x%02x%02x%02x%02x"
655 ":0x%02x%02x%02x%02x%02x%02x%02x%02x"
657 " data8=0x%02x%02x%02x%02x%02x%02x%02x%02x"
658 ":0x%02x%02x%02x%02x%02x%02x%02x%02x"
659 " data16=0x%04x%04x%04x%04x:0x%04x%04x%04x%04x"
660 " data32=0x%08x%08x:0x%08x%08x"
661 " data64=0x%016" PRIx64 ":0x%016" PRIx64
662 " modified_time=0x%x lease_period=0x%x\n\n",
663 cl_ntoh64(p_sr->service_id),
664 cl_ntoh64(p_sr->service_gid.unicast.prefix),
665 cl_ntoh64(p_sr->service_gid.unicast.interface_id),
666 cl_ntoh16(p_sr->service_pkey),
667 cl_ntoh32(p_sr->service_lease),
668 p_sr->service_key[0], p_sr->service_key[1],
669 p_sr->service_key[2], p_sr->service_key[3],
670 p_sr->service_key[4], p_sr->service_key[5],
671 p_sr->service_key[6], p_sr->service_key[7],
672 p_sr->service_key[8], p_sr->service_key[9],
673 p_sr->service_key[10], p_sr->service_key[11],
674 p_sr->service_key[12], p_sr->service_key[13],
675 p_sr->service_key[14], p_sr->service_key[15],
677 p_sr->service_data8[0], p_sr->service_data8[1],
678 p_sr->service_data8[2], p_sr->service_data8[3],
679 p_sr->service_data8[4], p_sr->service_data8[5],
680 p_sr->service_data8[6], p_sr->service_data8[7],
681 p_sr->service_data8[8], p_sr->service_data8[9],
682 p_sr->service_data8[10], p_sr->service_data8[11],
683 p_sr->service_data8[12], p_sr->service_data8[13],
684 p_sr->service_data8[14], p_sr->service_data8[15],
685 cl_ntoh16(p_sr->service_data16[0]),
686 cl_ntoh16(p_sr->service_data16[1]),
687 cl_ntoh16(p_sr->service_data16[2]),
688 cl_ntoh16(p_sr->service_data16[3]),
689 cl_ntoh16(p_sr->service_data16[4]),
690 cl_ntoh16(p_sr->service_data16[5]),
691 cl_ntoh16(p_sr->service_data16[6]),
692 cl_ntoh16(p_sr->service_data16[7]),
693 cl_ntoh32(p_sr->service_data32[0]),
694 cl_ntoh32(p_sr->service_data32[1]),
695 cl_ntoh32(p_sr->service_data32[2]),
696 cl_ntoh32(p_sr->service_data32[3]),
697 cl_ntoh64(p_sr->service_data64[0]),
698 cl_ntoh64(p_sr->service_data64[1]),
699 p_svcr->modified_time, p_svcr->lease_period);
702 static void sa_dump_all_sa(osm_opensm_t * p_osm, FILE * file)
704 struct opensm_dump_context dump_context;
708 dump_context.p_osm = p_osm;
709 dump_context.file = file;
710 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump multicast:\n");
711 cl_plock_acquire(&p_osm->lock);
712 for (i = 0; i <= p_osm->subn.max_mcast_lid_ho - IB_LID_MCAST_START_HO;
714 p_mgrp = p_osm->subn.mgroups[i];
716 sa_dump_one_mgrp(p_mgrp, &dump_context);
718 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump inform:\n");
719 cl_qlist_apply_func(&p_osm->subn.sa_infr_list,
720 sa_dump_one_inform, &dump_context);
721 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump services:\n");
722 cl_qlist_apply_func(&p_osm->subn.sa_sr_list,
723 sa_dump_one_service, &dump_context);
724 cl_plock_release(&p_osm->lock);
727 int osm_sa_db_file_dump(osm_opensm_t * p_osm)
729 return opensm_dump_to_file(p_osm, "opensm-sa.dump", sa_dump_all_sa);
735 static osm_mgrp_t *load_mcgroup(osm_opensm_t * p_osm, ib_net16_t mlid,
736 ib_member_rec_t * p_mcm_rec,
739 ib_net64_t comp_mask;
742 cl_plock_excl_acquire(&p_osm->lock);
744 p_mgrp = osm_get_mgrp_by_mlid(&p_osm->subn, mlid);
746 if (!memcmp(&p_mgrp->mcmember_rec.mgid, &p_mcm_rec->mgid,
748 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
749 "mgrp %04x is already here.", cl_ntoh16(mlid));
752 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
753 "mlid %04x is already used by another MC group. Will "
754 "request clients reregistration.\n", cl_ntoh16(mlid));
759 comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL
760 | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL;
761 if (osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa,
762 comp_mask, p_mcm_rec,
763 &p_mgrp) != IB_SUCCESS ||
764 !p_mgrp || p_mgrp->mlid != mlid) {
765 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
766 "cannot create MC group with mlid 0x%04x and mgid "
767 "0x%016" PRIx64 ":0x%016" PRIx64 "\n", cl_ntoh16(mlid),
768 cl_ntoh64(p_mcm_rec->mgid.unicast.prefix),
769 cl_ntoh64(p_mcm_rec->mgid.unicast.interface_id));
771 } else if (well_known)
772 p_mgrp->well_known = TRUE;
775 cl_plock_release(&p_osm->lock);
780 static int load_svcr(osm_opensm_t * p_osm, ib_service_record_t * sr,
781 uint32_t modified_time, uint32_t lease_period)
786 cl_plock_excl_acquire(&p_osm->lock);
788 if (osm_svcr_get_by_rid(&p_osm->subn, &p_osm->log, sr)) {
789 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
790 "ServiceRecord already exists\n");
794 if (!(p_svcr = osm_svcr_new(sr))) {
795 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
796 "cannot allocate new service struct\n");
801 p_svcr->modified_time = modified_time;
802 p_svcr->lease_period = lease_period;
804 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding ServiceRecord...\n");
806 osm_svcr_insert_to_db(&p_osm->subn, &p_osm->log, p_svcr);
808 if (lease_period != 0xffffffff)
809 cl_timer_trim(&p_osm->sa.sr_timer, 1000);
812 cl_plock_release(&p_osm->lock);
817 static int load_infr(osm_opensm_t * p_osm, ib_inform_info_record_t * iir,
818 osm_mad_addr_t * addr)
820 osm_infr_t infr, *p_infr;
823 infr.h_bind = p_osm->sa.mad_ctrl.h_bind;
824 infr.sa = &p_osm->sa;
825 /* other possible way to restore mad_addr partially is
826 to extract qpn from InformInfo and to find lid by gid */
827 infr.report_addr = *addr;
828 infr.inform_record = *iir;
830 cl_plock_excl_acquire(&p_osm->lock);
831 if (osm_infr_get_by_rec(&p_osm->subn, &p_osm->log, &infr)) {
832 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
833 "InformInfo Record already exists\n");
837 if (!(p_infr = osm_infr_new(&infr))) {
838 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
839 "cannot allocate new infr struct\n");
844 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding InformInfo Record...\n");
846 osm_infr_insert_to_db(&p_osm->subn, &p_osm->log, p_infr);
849 cl_plock_release(&p_osm->lock);
854 #define UNPACK_FUNC(name,x) \
855 static int unpack_##name##x(char *p, uint##x##_t *val_ptr) \
858 unsigned long long num; \
859 num = strtoull(p, &q, 16); \
860 if (num > ~((uint##x##_t)0x0) \
861 || q == p || (!isspace(*q) && *q != ':')) { \
865 *val_ptr = cl_hton##x((uint##x##_t)num); \
866 return (int)(q - p); \
869 #define cl_hton8(x) (x)
872 UNPACK_FUNC(net, 16);
873 UNPACK_FUNC(net, 32);
874 UNPACK_FUNC(net, 64);
876 static int unpack_string(char *p, uint8_t * buf, unsigned len)
881 if (*q == '\'' || *q == '\"')
883 while (--len && *q && *q != delim)
886 if (*q == delim && delim != ' ')
891 static int unpack_string64(char *p, uint8_t * buf)
893 return unpack_string(p, buf, 64);
896 #define PARSE_AHEAD(p, x, name, val_ptr) { int _ret; \
897 p = strstr(p, name); \
899 OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \
900 "PARSE ERROR: %s:%u: cannot find \"%s\" string\n", \
901 file_name, lineno, (name)); \
906 _ret = unpack_##x(p, (val_ptr)); \
908 OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \
909 "PARSE ERROR: %s:%u: cannot parse "#x" value " \
910 "after \"%s\"\n", file_name, lineno, (name)); \
917 int osm_sa_db_file_load(osm_opensm_t * p_osm)
923 osm_mgrp_t *p_mgrp = NULL;
924 unsigned rereg_clients = 0;
927 file_name = p_osm->subn.opt.sa_db_file;
929 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
930 "sa db file name is not specifed. Skip restore\n");
934 file = fopen(file_name, "r");
936 OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 4C02: "
937 "cannot open sa db file \'%s\'. Skip restoring\n",
944 while (fgets(line, sizeof(line) - 1, file) != NULL) {
957 if (!strncmp(p, "MC Group", 8)) {
958 ib_member_rec_t mcm_rec;
960 unsigned well_known = 0;
963 memset(&mcm_rec, 0, sizeof(mcm_rec));
965 PARSE_AHEAD(p, net16, " 0x", &mlid);
966 if (strstr(p, "well known"))
968 PARSE_AHEAD(p, net64, " mgid=0x",
969 &mcm_rec.mgid.unicast.prefix);
970 PARSE_AHEAD(p, net64, ":0x",
971 &mcm_rec.mgid.unicast.interface_id);
972 PARSE_AHEAD(p, net64, " port_gid=0x",
973 &mcm_rec.port_gid.unicast.prefix);
974 PARSE_AHEAD(p, net64, ":0x",
975 &mcm_rec.port_gid.unicast.interface_id);
976 PARSE_AHEAD(p, net32, " qkey=0x", &mcm_rec.qkey);
977 PARSE_AHEAD(p, net16, " mlid=0x", &mcm_rec.mlid);
978 PARSE_AHEAD(p, net8, " mtu=0x", &mcm_rec.mtu);
979 PARSE_AHEAD(p, net8, " tclass=0x", &mcm_rec.tclass);
980 PARSE_AHEAD(p, net16, " pkey=0x", &mcm_rec.pkey);
981 PARSE_AHEAD(p, net8, " rate=0x", &mcm_rec.rate);
982 PARSE_AHEAD(p, net8, " pkt_life=0x", &mcm_rec.pkt_life);
983 PARSE_AHEAD(p, net32, " sl_flow_hop=0x",
984 &mcm_rec.sl_flow_hop);
985 PARSE_AHEAD(p, net8, " scope_state=0x",
986 &mcm_rec.scope_state);
987 PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
988 mcm_rec.proxy_join = val;
990 p_mgrp = load_mcgroup(p_osm, mlid, &mcm_rec,
994 } else if (p_mgrp && !strncmp(p, "mcm_port", 8)) {
998 boolean_t proxy_join;
1000 PARSE_AHEAD(p, net64, " port_gid=0x",
1001 &port_gid.unicast.prefix);
1002 PARSE_AHEAD(p, net64, ":0x",
1003 &port_gid.unicast.interface_id);
1004 PARSE_AHEAD(p, net8, " scope_state=0x", &scope_state);
1005 PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
1008 guid = port_gid.unicast.interface_id;
1009 if (cl_qmap_get(&p_mgrp->mcm_port_tbl,
1010 port_gid.unicast.interface_id) ==
1011 cl_qmap_end(&p_mgrp->mcm_port_tbl))
1012 osm_mgrp_add_port(&p_osm->subn, &p_osm->log,
1014 scope_state, proxy_join);
1015 } else if (!strncmp(p, "Service Record:", 15)) {
1016 ib_service_record_t s_rec;
1017 uint32_t modified_time, lease_period;
1020 memset(&s_rec, 0, sizeof(s_rec));
1022 PARSE_AHEAD(p, net64, " id=0x", &s_rec.service_id);
1023 PARSE_AHEAD(p, net64, " gid=0x",
1024 &s_rec.service_gid.unicast.prefix);
1025 PARSE_AHEAD(p, net64, ":0x",
1026 &s_rec.service_gid.unicast.interface_id);
1027 PARSE_AHEAD(p, net16, " pkey=0x", &s_rec.service_pkey);
1028 PARSE_AHEAD(p, net32, " lease=0x",
1029 &s_rec.service_lease);
1030 PARSE_AHEAD(p, net64, " key=0x",
1031 (ib_net64_t *) (&s_rec.service_key[0]));
1032 PARSE_AHEAD(p, net64, ":0x",
1033 (ib_net64_t *) (&s_rec.service_key[8]));
1034 PARSE_AHEAD(p, string64, " name=", s_rec.service_name);
1035 PARSE_AHEAD(p, net64, " data8=0x",
1036 (ib_net64_t *) (&s_rec.service_data8[0]));
1037 PARSE_AHEAD(p, net64, ":0x",
1038 (ib_net64_t *) (&s_rec.service_data8[8]));
1039 PARSE_AHEAD(p, net64, " data16=0x",
1040 (ib_net64_t *) (&s_rec.service_data16[0]));
1041 PARSE_AHEAD(p, net64, ":0x",
1042 (ib_net64_t *) (&s_rec.service_data16[4]));
1043 PARSE_AHEAD(p, net64, " data32=0x",
1044 (ib_net64_t *) (&s_rec.service_data32[0]));
1045 PARSE_AHEAD(p, net64, ":0x",
1046 (ib_net64_t *) (&s_rec.service_data32[2]));
1047 PARSE_AHEAD(p, net64, " data64=0x",
1048 &s_rec.service_data64[0]);
1049 PARSE_AHEAD(p, net64, ":0x", &s_rec.service_data64[1]);
1050 PARSE_AHEAD(p, net32, " modified_time=0x",
1052 PARSE_AHEAD(p, net32, " lease_period=0x",
1055 if (load_svcr(p_osm, &s_rec, cl_ntoh32(modified_time),
1056 cl_ntoh32(lease_period)))
1058 } else if (!strncmp(p, "InformInfo Record:", 18)) {
1059 ib_inform_info_record_t i_rec;
1060 osm_mad_addr_t rep_addr;
1064 memset(&i_rec, 0, sizeof(i_rec));
1065 memset(&rep_addr, 0, sizeof(rep_addr));
1067 PARSE_AHEAD(p, net64, " subscriber_gid=0x",
1068 &i_rec.subscriber_gid.unicast.prefix);
1069 PARSE_AHEAD(p, net64, ":0x",
1070 &i_rec.subscriber_gid.unicast.interface_id);
1071 PARSE_AHEAD(p, net16, " subscriber_enum=0x",
1072 &i_rec.subscriber_enum);
1073 PARSE_AHEAD(p, net64, " gid=0x",
1074 &i_rec.inform_info.gid.unicast.prefix);
1075 PARSE_AHEAD(p, net64, ":0x",
1076 &i_rec.inform_info.gid.unicast.
1078 PARSE_AHEAD(p, net16, " lid_range_begin=0x",
1079 &i_rec.inform_info.lid_range_begin);
1080 PARSE_AHEAD(p, net16, " lid_range_end=0x",
1081 &i_rec.inform_info.lid_range_end);
1082 PARSE_AHEAD(p, net8, " is_generic=0x",
1083 &i_rec.inform_info.is_generic);
1084 PARSE_AHEAD(p, net8, " subscribe=0x",
1085 &i_rec.inform_info.subscribe);
1086 PARSE_AHEAD(p, net16, " trap_type=0x",
1087 &i_rec.inform_info.trap_type);
1088 PARSE_AHEAD(p, net16, " trap_num=0x",
1089 &i_rec.inform_info.g_or_v.generic.trap_num);
1090 PARSE_AHEAD(p, net32, " qpn_resp_time_val=0x",
1091 &i_rec.inform_info.g_or_v.generic.
1093 PARSE_AHEAD(p, net32, " node_type=0x",
1094 (uint32_t *) & i_rec.inform_info.g_or_v.
1097 PARSE_AHEAD(p, net16, " rep_addr: lid=0x",
1098 &rep_addr.dest_lid);
1099 PARSE_AHEAD(p, net8, " path_bits=0x",
1100 &rep_addr.path_bits);
1101 PARSE_AHEAD(p, net8, " static_rate=0x",
1102 &rep_addr.static_rate);
1103 PARSE_AHEAD(p, net32, " remote_qp=0x",
1104 &rep_addr.addr_type.gsi.remote_qp);
1105 PARSE_AHEAD(p, net32, " remote_qkey=0x",
1106 &rep_addr.addr_type.gsi.remote_qkey);
1107 PARSE_AHEAD(p, net16, " pkey_ix=0x", &val16);
1108 rep_addr.addr_type.gsi.pkey_ix = cl_ntoh16(val16);
1109 PARSE_AHEAD(p, net8, " sl=0x",
1110 &rep_addr.addr_type.gsi.service_level);
1112 if (load_infr(p_osm, &i_rec, &rep_addr))
1118 p_osm->subn.opt.no_clients_rereg = TRUE;